@font-face {
    font-family: 'Circe';
    src: url('/assets/fonts/Circe-ExtraLight.woff2') format('woff2');
    font-weight: 200;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Circe';
    src: url('/assets/fonts/Circe-Light.woff2') format('woff2');
    font-weight: 300;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Circe';
    src: url('/assets/fonts/Circe-Regular.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Circe';
    src: url('/assets/fonts/Circe-Bold.woff2') format('woff2');
    font-weight: 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Circe';
    src: url('/assets/fonts/Circe-ExtraBold.woff2') format('woff2');
    font-weight: 800;
    font-style: normal;
    font-display: swap;
}

:root {
    --felt-green: #0b6e4f;
    --felt-green-dark: #073d2c;
    --wood-brown: #5c3a21;
    --wood-brown-light: #8a5a34;
    --wood-brown-dark: #3b2414;
    --gold: #c9a24b;
    --gold-light: #e0c179;
    --cream: #f5efe6;
    --text-on-dark: #f5efe6;
    --text-on-light: #2a1c10;
    --danger: #b3402f;
    --radius: 12px;
    --shadow: 0 4px 14px rgba(0, 0, 0, 0.25);
    --font-body: 'Circe', 'Segoe UI', Roboto, Arial, sans-serif;
}

* {
    box-sizing: border-box;
}

html,
body {
    margin: 0;
    padding: 0;
    min-height: 100%;
}

body {
    font-family: var(--font-body);
    background: radial-gradient(ellipse at top, var(--felt-green) 0%, var(--felt-green-dark) 70%);
    color: var(--text-on-dark);
    display: flex;
    flex-direction: column;
}

a {
    color: var(--gold);
}

.site-header {
    background: linear-gradient(180deg, #0c8560 0%, var(--felt-green) 55%, var(--felt-green-dark) 100%);
    border-bottom: 2px solid var(--gold);
    box-shadow: var(--shadow);
    padding: 0.75rem 1rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    position: relative;
}

.site-header .brand {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--cream);
    text-decoration: none;
    letter-spacing: 0.02em;
}

.site-header .brand img {
    border-radius: 7px;
    display: block;
}

/* The hamburger + dropdown menu is the only account menu now, on every
   device size — there's no separate always-visible desktop nav to keep in sync. */
.nav-toggle {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 4px;
    width: 40px;
    height: 40px;
    background: transparent;
    border: none;
    cursor: pointer;
    padding: 0;
}

.nav-toggle span {
    display: block;
    width: 22px;
    height: 2px;
    border-radius: 1px;
    background: var(--cream);
}

.site-nav-mobile {
    display: none;
    position: absolute;
    top: 100%;
    right: 1rem;
    margin-top: 0.5rem;
    min-width: 190px;
    background: var(--felt-green-dark);
    border: 1px solid rgba(201, 162, 75, 0.4);
    border-radius: 10px;
    padding: 0.6rem;
    flex-direction: column;
    align-items: stretch;
    gap: 0.25rem;
    box-shadow: var(--shadow);
    z-index: 20;
}

.site-nav-mobile.open {
    display: flex;
}

/* Plain informational label (the current user's name) — deliberately
   styled unlike the menu links below it, so it doesn't read as tappable. */
.nav-mobile-user {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4rem 0.6rem 0.2rem;
}

.nav-mobile-label {
    font-size: 0.8rem;
    color: rgba(245, 239, 230, 0.6);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.avatar-circle {
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    display: inline-block;
}

.avatar-circle-fallback {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--gold);
    color: var(--wood-brown-dark);
    font-weight: 700;
}

.avatar-upload-row {
    display: flex;
    align-items: center;
    gap: 1rem;
}

.avatar-upload-row input[type='file'] {
    flex: 1;
    min-width: 0;
    color: var(--cream);
    font-size: 0.85rem;
}

.nav-menu-item {
    display: block;
    padding: 0.6rem;
    border-radius: 8px;
    color: var(--cream);
    text-decoration: none;
    font-size: 0.95rem;
}

.nav-menu-item:hover {
    background: rgba(255, 255, 255, 0.08);
}

.nav-menu-item-icon {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.nav-menu-item-icon svg {
    flex-shrink: 0;
    opacity: 0.85;
}

/* Deliberately plain — a bare underlined link, not a button — and set
   apart with extra top margin so it always reads as the last, separate
   action in the menu rather than one more item in the list. */
.nav-mobile-logout {
    display: block;
    text-align: left;
    background: none;
    border: none;
    border-radius: 8px;
    color: var(--gold-light);
    text-decoration: underline;
    font-weight: 400;
    font-size: 0.95rem;
    padding: 0.4rem 0.6rem;
    margin-top: 0.9rem;
}

.nav-mobile-logout:hover {
    background: rgba(255, 255, 255, 0.08);
}

@media (max-width: 600px) {
    .brand-text {
        display: none;
    }
}

.container {
    flex: 1;
    width: 100%;
    max-width: 480px;
    margin: 0 auto;
    padding: 1.5rem 1rem 3rem;
}

/* Narrow phones don't need the same side breathing room a centered
   desktop column does — every pixel of width matters more there, so this
   trims it down instead of wasting it as unused margin either side.
   Deliberately mobile-only for now; desktop's padding is a separate,
   not-yet-decided question. */
@media (max-width: 599px) {
    .container {
        padding: 1rem 0.5rem 2rem;
    }
}

.card {
    background: rgba(15, 15, 15, 0.28);
    border: 1px solid rgba(201, 162, 75, 0.35);
    border-radius: var(--radius);
    padding: 1.5rem;
    box-shadow: var(--shadow);
}

.card h1,
.card h2 {
    margin-top: 0;
    color: var(--gold);
}

.card h1 {
    font-size: 1.5rem;
}

@media (max-width: 600px) {
    .card h1 {
        font-size: 1.2rem;
    }
}

.field {
    margin-bottom: 1rem;
}

.field label {
    display: block;
    margin-bottom: 0.35rem;
    font-size: 0.9rem;
    color: var(--cream);
}

.field input[type='text'],
.field input[type='email'],
.field input[type='password'],
.field input[type='tel'],
.field input[type='number'],
.field input[type='date'] {
    width: 100%;
    padding: 0.7rem 0.85rem;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.25);
    background: rgba(255, 255, 255, 0.92);
    color: var(--text-on-light);
    font-size: 1rem;
}

.select-input {
    width: 100%;
    padding: 0.7rem 0.85rem;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.25);
    background: rgba(255, 255, 255, 0.92);
    color: var(--text-on-light);
    font-size: 1rem;
}

.meeting-row {
    display: block;
    margin-bottom: 0.75rem;
    text-decoration: none;
    color: inherit;
}

.meeting-row-status {
    text-align: left;
    margin-top: 0.35rem;
    font-size: 0.9rem;
    color: rgba(245, 239, 230, 0.75);
}

.meeting-row-participants {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: 0.6rem;
}

.meeting-row-player {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    background: rgba(255, 255, 255, 0.06);
    border-radius: 999px;
    padding: 0.2rem 0.6rem 0.2rem 0.2rem;
    font-size: 0.82rem;
    color: rgba(245, 239, 230, 0.85);
}

.meeting-row-player-name {
    max-width: 8rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.meeting-row-balls {
    font-weight: 700;
    color: var(--gold-light);
}

.meeting-row-wins {
    font-weight: 700;
    font-size: 0.85rem;
    color: rgba(245, 239, 230, 0.7);
}

.meeting-stats-table-wrap {
    margin-top: 0.75rem;
    overflow-x: auto;
}

.meeting-stats-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9rem;
}

.meeting-stats-table th,
.meeting-stats-table td {
    padding: 0.4rem 0.5rem;
    text-align: center;
    white-space: nowrap;
    border-bottom: 1px solid rgba(201, 162, 75, 0.15);
}

.meeting-stats-table thead th {
    color: rgba(245, 239, 230, 0.6);
    font-weight: 700;
    font-size: 0.8rem;
    border-bottom: 1px solid rgba(201, 162, 75, 0.3);
}

/* П/Ш/Д/Шт header buttons — reset to look like the plain <th> text around
   them (no button chrome) until clicked. */
.meeting-stats-sortable {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    cursor: pointer;
}

.meeting-stats-sortable:focus-visible {
    outline: 2px solid var(--gold);
    outline-offset: 2px;
}

.meeting-stats-sortable .sort-arrow {
    width: 9px;
    height: 9px;
    opacity: 0.3;
    transition: transform 0.15s ease, opacity 0.15s ease;
}

/* Defaults to pointing down (first click sorts biggest-first); an active
   column's arrow turns fully opaque, and flips to point up once toggled to
   ascending. */
.meeting-stats-sortable.sorted-asc .sort-arrow,
.meeting-stats-sortable.sorted-desc .sort-arrow {
    opacity: 1;
}

.meeting-stats-sortable.sorted-asc .sort-arrow {
    transform: rotate(180deg);
}

.meeting-stats-sortable.meeting-stats-col-active {
    color: var(--gold);
}

.meeting-stats-table td.meeting-stats-col-active {
    background: rgba(201, 162, 75, 0.14);
    color: var(--gold);
}

/* Specificity note: plain `.meeting-stats-table-name-col { text-align: left }`
   (one class) used to lose to `.meeting-stats-table th, .meeting-stats-table
   td { text-align: center }` (class + element) above, since the latter is
   MORE specific despite coming first in the file — the data rows only
   looked left-aligned anyway because .meeting-stats-table-name is a flex
   container that ignores its <td>'s text-align, but the plain-text <th>
   header had nothing to hide behind and rendered centered, out of step with
   the row below it. Qualifying with the element type here matches that
   specificity so the header wins too. */
.meeting-stats-table th.meeting-stats-table-name-col,
.meeting-stats-table td.meeting-stats-table-name-col {
    text-align: left;
    width: 100%;
}

.meeting-stats-table-name {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: 600;
}

.payment-results {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.payment-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.6rem 0.75rem;
    border-radius: 10px;
    background: rgba(255, 255, 255, 0.06);
}

.payment-card-player {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-width: 0;
}

.payment-card-player-info {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.payment-card-name {
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.payment-card-figures {
    font-size: 0.8rem;
    color: rgba(245, 239, 230, 0.65);
}

.payment-card-amount {
    flex-shrink: 0;
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--gold);
    white-space: nowrap;
}

.match-list-header {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
}

.match-list-header-right {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    flex-shrink: 0;
}

.match-list-status {
    font-size: 0.85rem;
    color: rgba(245, 239, 230, 0.7);
    white-space: nowrap;
}

.match-list-duration {
    font-size: 0.85rem;
    color: rgba(245, 239, 230, 0.5);
    white-space: nowrap;
}

/* One row per player, always — regardless of how many are in the match.
   Previously 2-player matches got a special centered "N : N" layout; that
   meant two different code paths to keep in sync, and the shared one
   below already reads fine for 2 as well as 10. */
.match-list-score {
    margin-top: 0.6rem;
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    font-size: 1.05rem;
    color: var(--cream);
}

.score-player-row {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

/* flex-basis: 0 (not "auto"/content-based) is what actually guarantees this
   column is the same width on every row regardless of the player's own
   name length — with "auto" some mobile browsers size it off its own
   content first and only then grow, which visibly shifted the score/icon
   columns next to short names like a single first name. */
.score-player-identity {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    flex: 1 1 0%;
    min-width: 0;
}

.score-player-name {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    text-align: left;
}

.score-player-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 18px;
    width: 18px;
}

.score-num {
    flex: 0 0 auto;
    min-width: 1.6rem;
    text-align: right;
    color: var(--gold);
    font-weight: 800;
}

.trophy-icon {
    width: 15px;
    height: 15px;
    color: var(--gold);
    flex-shrink: 0;
}

.last-ball-icon {
    width: 13px;
    height: 13px;
    color: rgba(245, 239, 230, 0.55);
    flex-shrink: 0;
}

@media (min-width: 600px) {
    .match-list-score {
        font-size: 1.3rem;
    }

    .match-list-score .score-num {
        font-size: 1.7rem;
    }

    .trophy-icon {
        width: 20px;
        height: 20px;
    }

    .last-ball-icon {
        width: 18px;
        height: 18px;
    }
}

.checkbox-option {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    cursor: pointer;
    color: var(--cream);
    font-size: 0.95rem;
}

.checkbox-option input {
    width: 18px;
    height: 18px;
    accent-color: var(--gold);
    flex-shrink: 0;
}

.participant-picker {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.6rem;
    margin-bottom: 1rem;
}

.participant-picker-item {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.45rem 0.7rem 0.45rem 0.5rem;
    border-radius: 5px;
    border: 1px solid rgba(201, 162, 75, 0.35);
    background: rgba(15, 15, 15, 0.28);
    font-size: 0.9rem;
    color: var(--cream);
    cursor: pointer;
}

/* Keeps the pill a single-line stadium shape regardless of name length —
   without this a long name wraps to a second line and the 999px
   border-radius turns the pill into a lopsided oval instead of matching
   its (single-line) siblings. */
.participant-picker-name {
    overflow: hidden;
    min-width: 0;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.participant-picker-item input[type='checkbox'] {
    width: 18px;
    height: 18px;
    accent-color: var(--gold);
}

/* Match presets ("Тип табло", "Последний шар") — a segmented two-way toggle
   rather than a native <select>: no dropdown-chrome quirks to fight
   (unreadable options, chevron misalignment — both bit us with the select
   approach), and a row of big, obviously-tappable pill buttons reads more
   clearly as "pick one" on a phone than a dropdown does. */
.preset-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 1rem;
}

.preset-label {
    font-size: 0.85rem;
    color: rgba(245, 239, 230, 0.6);
}

.segmented-control {
    display: flex;
    width: 10.5rem;
    padding: 3px;
    gap: 2px;
    border-radius: 999px;
    background: rgba(15, 15, 15, 0.3);
    border: 1px solid rgba(201, 162, 75, 0.35);
}

.segmented-option {
    position: relative;
    flex: 1 1 50%;
    cursor: pointer;
}

.segmented-option input {
    position: absolute;
    opacity: 0;
    width: 1px;
    height: 1px;
}

.segmented-option span {
    display: block;
    width: 100%;
    box-sizing: border-box;
    padding: 0.45rem 0.6rem;
    border-radius: 999px;
    font-size: 0.8rem;
    color: rgba(245, 239, 230, 0.7);
    text-align: center;
    white-space: nowrap;
    transition: background-color 0.15s ease, color 0.15s ease;
}

.segmented-option input:checked + span {
    background: var(--gold);
    color: var(--wood-brown-dark);
    font-weight: 700;
}

.segmented-option input:focus-visible + span {
    outline: 2px solid var(--gold);
    outline-offset: 2px;
}

.dropdown {
    position: relative;
}

.dropdown-trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    width: 100%;
    padding: 0.7rem 0.9rem;
    border-radius: 8px;
    border: 1px solid rgba(201, 162, 75, 0.4);
    background: rgba(15, 15, 15, 0.3);
    color: var(--cream);
    font-family: inherit;
    font-size: 0.95rem;
    text-align: left;
    cursor: pointer;
}

.dropdown-trigger:hover {
    border-color: rgba(201, 162, 75, 0.7);
}

.dropdown.open .dropdown-trigger {
    border-color: var(--gold);
}

.dropdown-trigger-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dropdown-caret {
    width: 8px;
    height: 8px;
    margin-top: -4px;
    border-right: 2px solid var(--gold);
    border-bottom: 2px solid var(--gold);
    transform: rotate(45deg);
    transition: transform 0.15s ease;
    flex-shrink: 0;
}

.dropdown.open .dropdown-caret {
    margin-top: 4px;
    transform: rotate(-135deg);
}

.dropdown-menu {
    display: none;
    position: absolute;
    top: calc(100% + 0.4rem);
    left: 0;
    right: 0;
    z-index: 30;
    max-height: 280px;
    overflow-y: auto;
    padding: 0.4rem;
    border-radius: 8px;
    border: 1px solid rgba(201, 162, 75, 0.4);
    background: var(--felt-green-dark);
    box-shadow: var(--shadow);
}

.dropdown.open .dropdown-menu {
    display: block;
}

.dropdown-option {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.55rem 0.6rem;
    border-radius: 6px;
    color: var(--cream);
    font-size: 0.9rem;
    cursor: pointer;
}

.dropdown-option:hover {
    background: rgba(201, 162, 75, 0.15);
}

.dropdown-option:has(input:checked) {
    background: rgba(201, 162, 75, 0.22);
    color: var(--gold-light);
    font-weight: 700;
}

.dropdown-option input {
    width: 16px;
    height: 16px;
    accent-color: var(--gold);
    flex-shrink: 0;
}

.invite-link-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 1rem;
    cursor: pointer;
}

.invite-link-row:focus-visible {
    outline: 2px solid var(--gold);
    outline-offset: 2px;
    border-radius: 8px;
}

.invite-link-input {
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.7rem 0.85rem;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.25);
    background: rgba(255, 255, 255, 0.92);
    color: var(--text-on-light);
    font-size: 0.9rem;
    /* The whole row is the click target now (see .invite-link-row) — the
       input itself no longer needs its own pointer/focus interaction. */
    pointer-events: none;
}

.invite-link-copy-icon {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    color: var(--gold);
}

.invite-link-copy-icon svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

.invite-link-copy-icon-copy {
    transition: opacity 0.15s ease;
}

.invite-link-copy-icon-check {
    opacity: 0;
    color: var(--felt-green);
    transition: opacity 0.15s ease;
}

.copy-done .invite-link-copy-icon-copy {
    opacity: 0;
}

.copy-done .invite-link-copy-icon-check {
    opacity: 1;
}

.qr-canvas {
    display: flex;
    justify-content: center;
    padding: 1rem;
    background: #fff;
    border-radius: var(--radius);
}

.qr-canvas svg {
    width: 100%;
    max-width: 260px;
    height: auto;
}

.stats-year-input {
    width: 4.5rem;
    padding: 0.3rem 0.5rem;
    border-radius: 6px;
    border: 1px solid rgba(255, 255, 255, 0.25);
    background: rgba(255, 255, 255, 0.92);
    color: var(--text-on-light);
    font-size: 0.9rem;
}

.stats-filter-dates {
    display: flex;
    gap: 0.75rem;
}

/* `display: flex` above has the same specificity as the UA stylesheet's
   `[hidden] { display: none }` and (being an author style) wins the
   cascade tie — without this, [hidden] on this element is silently
   ignored and the date fields never actually hide. */
.stats-filter-dates[hidden] {
    display: none;
}

.stats-filter-dates .field {
    flex: 1;
    min-width: 0;
}

.stats-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.75rem;
    margin-top: 1.5rem;
}

.stat-tile {
    background: rgba(15, 15, 15, 0.28);
    border: 1px solid rgba(201, 162, 75, 0.35);
    border-radius: var(--radius);
    padding: 0.9rem 1rem;
}

.stat-tile-value {
    font-size: 1.6rem;
    font-weight: 800;
    color: var(--gold);
    line-height: 1.15;
}

.stat-tile-label {
    margin-top: 0.25rem;
    font-size: 0.8rem;
    color: rgba(245, 239, 230, 0.75);
}

.chart-metric-toggle {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

.chart-metric-chip {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.6rem;
    border-radius: 999px;
    border: 1px solid rgba(201, 162, 75, 0.25);
    font-size: 0.8rem;
    color: var(--cream);
    cursor: pointer;
}

.chart-metric-chip input[type='checkbox'] {
    width: 14px;
    height: 14px;
}

.chart-metric-swatch {
    display: inline-block;
    width: 10px;
    height: 10px;
    border-radius: 50%;
}

#stats-chart svg {
    display: block;
    width: 100%;
    height: auto;
}

.h2h-scroll {
    overflow-x: auto;
    margin-top: 1rem;
}

.h2h-flex-table {
    display: flex;
    flex-direction: column;
    min-width: 460px;
    font-size: 0.9rem;
}

.h2h-frow {
    display: flex;
    align-items: center;
    border-bottom: 1px solid rgba(201, 162, 75, 0.2);
}

.h2h-fcell {
    flex: 1 1 0;
    min-width: 0;
    padding: 0.45rem 0.3rem;
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Minimal, content-independent width so the match-number column stays
   compact regardless of what's in the wider stat columns next to it. */
.h2h-fcell-num {
    flex: 0 0 1.7rem;
    padding-left: 0;
    padding-right: 0;
}

.h2h-fcell-delta {
    flex: 0 0 2.6rem;
}

/* flex-grow 4 == the combined width of the four flex-grow-1 stat cells
   (Ш/Д/Шт/С) below it, so the player-name row lines up with that row. */
.h2h-fcell-name {
    flex: 4 4 0;
    text-align: left;
    padding-left: 0.4rem;
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
}

.h2h-match-num {
    color: rgba(245, 239, 230, 0.4);
}

.h2h-divider {
    border-left: 1px solid rgba(201, 162, 75, 0.25);
}

.h2h-header-row .h2h-fcell {
    color: var(--gold);
    font-weight: 700;
    border-bottom: 1px solid rgba(201, 162, 75, 0.4);
}

/* The num-column header cells are always empty (no "1", "2"... there — that
   column only holds per-row match numbers in the body) — their border-bottom
   still rendered as a short, out-of-context dash with nothing around it to
   read as "part of a table row", since the cell itself is blank. */
.h2h-header-row .h2h-fcell-num {
    border-bottom: none;
}

/* Same issue, same fix, for the name-header row's own ΔШ/ΔП placeholder
   cells — those columns only get their "ΔШ"/"ΔП" label one row further
   down, so the blank cells directly under "Александр Шустов" etc. rendered
   as a lone stray line with no label to anchor it to. :empty (rather than
   scoping to a specific class) only ever matches the truly blank cells —
   the second header row's own ΔШ/ΔП cells have text content and keep their
   border as normal. */
.h2h-header-row .h2h-fcell-delta:empty {
    border-bottom: none;
}

.h2h-meeting-info {
    padding: 0.9rem 0.3rem 0.4rem;
    font-weight: 700;
    color: var(--gold-light);
}

.h2h-meeting-total {
    font-weight: 700;
    background: rgba(15, 15, 15, 0.28);
}

.h2h-grand-total {
    font-weight: 800;
    background: rgba(201, 162, 75, 0.18);
    color: var(--gold-light);
}

/* Win%/fluke% row directly under the period's grand total — same column
   grid as every other row (so it lines up under the Ш/Д cells it relates
   to and hides/shows with the extra-stats toggle exactly like they do),
   just dimmer since it's a derived figure rather than a raw count. */
.h2h-percent-row {
    font-size: 0.8rem;
    color: rgba(224, 193, 121, 0.75);
}

.h2h-percent-row .h2h-fcell-stat {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
}

.h2h-percent-trophy {
    width: 12px;
    height: 12px;
    flex-shrink: 0;
}

.h2h-card {
    position: relative;
    /* Explicit (not auto) z-index — needed so this always paints above
       later-in-DOM siblings such as the match list below it. z-index:auto
       positioned elements are stacked in tree order, so without a real
       number here the cards coming after it in the markup would win and
       paint over its (fully opaque) tooltip. */
    z-index: 3;
}

.tooltip-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-top: 0.5rem;
}

.tooltip-row {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
}

/* Takes the remaining row width and wraps within itself, so a long
   description stays on the same line as its icon/mini-button instead of
   the whole line dropping below it (flex items wrap as a unit otherwise). */
.tooltip-row-text {
    flex: 1 1 auto;
    min-width: 0;
}

.tooltip-group-label {
    font-weight: 700;
    color: var(--gold-light);
}

.tooltip-note {
    font-size: 0.8rem;
    color: rgba(245, 239, 230, 0.6);
}

.tooltip-mini-btn {
    display: inline-block;
    flex-shrink: 0;
    padding: 0.2rem 0.55rem;
    border-radius: 8px;
    font-size: 0.75rem;
    font-weight: 700;
    line-height: 1.3;
}

.tooltip-mini-btn-ball {
    background: var(--gold);
    color: var(--wood-brown-dark);
}

.tooltip-mini-btn-fluke,
.tooltip-mini-btn-series {
    background: rgba(255, 255, 255, 0.15);
    color: var(--cream);
    border: 1px solid rgba(255, 255, 255, 0.35);
}

.tooltip-mini-btn-penalty {
    background: rgba(200, 60, 60, 0.18);
    color: var(--cream);
    border: 1px solid rgba(200, 60, 60, 0.45);
}

.tooltip-mini-btn-undo {
    background: transparent;
    color: rgba(245, 239, 230, 0.6);
    border: 1px dashed rgba(245, 239, 230, 0.3);
}

.tooltip-drag-icon {
    flex-shrink: 0;
    color: rgba(245, 239, 230, 0.7);
}

/* Term column for plain "Ш — шары" style legend rows — a fixed min-width
   keeps the dash/definition lining up across rows regardless of how many
   letters the abbreviation itself has (Ш vs Шт vs ΔШ). */
.tooltip-term {
    flex: 0 0 auto;
    min-width: 1.8rem;
    font-weight: 700;
    color: var(--gold-light);
}

.tooltip-icon-slot {
    display: flex;
    align-items: center;
    flex-shrink: 0;
}

.tooltip-ball-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.35);
    background: rgba(255, 255, 255, 0.08);
    font-size: 0.7rem;
    line-height: 1;
}

/* Anchors a .h2h-help button/tooltip next to a plain <h2> that isn't inside
   a .h2h-card/.match-card (those already carry position:relative + the
   padding-right their own h2 rule gives) — e.g. the "Партии" heading. */
.section-heading {
    position: relative;
    /* Same reasoning as .h2h-card's z-index above — without an explicit
       value this heading (which comes before the match-list cards in the
       DOM) loses the z-index:auto tree-order tiebreak to those cards and
       its tooltip ends up painted underneath them. */
    z-index: 3;
    padding-right: 2.5rem;
}

/* .h2h-help's default top:1.5rem/right:1.5rem is calibrated for sitting
   inside a padded .card — .section-heading is just a thin heading wrapper
   with no such padding, so that offset pushed the button past the heading's
   own height and onto whatever card came right after it. Center it on the
   heading's own line instead. */
.section-heading .h2h-help {
    top: 50%;
    right: 0;
    transform: translateY(-50%);
}

/* Ш reads brighter than the extra (Д/Шт/С) columns by contrast. */
.h2h-fcell-extra {
    color: rgba(245, 239, 230, 0.55);
}

/* Actually collapses the hidden columns' width (not just visibility) so the
   table gets narrower, not just gappier. .h2h-fcell-name's flex-basis is
   calibrated to the number of VISIBLE stat cells per side — 4 (Ш/Д/Шт/С)
   normally, 1 (just Ш) once the extra three are hidden — so it has to move
   in lockstep with this rule. min-width on the table is relaxed too,
   otherwise the .h2h-scroll wrapper would keep reserving the old width. */
body.hide-extra-stats .h2h-fcell-extra {
    display: none;
}

body.hide-extra-stats .h2h-fcell-name {
    flex: 1 1 0;
}

body.hide-extra-stats .h2h-flex-table {
    min-width: 280px;
}

.h2h-card h2 {
    padding-right: 2.5rem;
}

.h2h-help {
    position: absolute;
    top: 1.5rem;
    right: 1.5rem;
}

.h2h-help-btn {
    width: 22px;
    height: 22px;
    border-radius: 50%;
    border: 1px solid rgba(201, 162, 75, 0.5);
    background: rgba(15, 15, 15, 0.3);
    color: var(--gold-light);
    font-size: 0.8rem;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    padding: 0;
}

.h2h-help {
    /* Forces a fresh stacking context regardless of what the surrounding
       card/list markup does with position/transform. */
    isolation: isolate;
    /* isolation alone only controls stacking WITHIN .h2h-help — it still
       needs an explicit z-index to win against LATER-in-DOM siblings that
       also get their own stacking context, like .match-leader-icon (any
       element with opacity < 1, which its blink animation always has,
       gets one automatically, position or not). Without this, the trophy
       painted on top of the open tooltip instead of behind it. Same
       auto-loses-to-later-DOM-order tiebreak as .section-heading/.h2h-card
       elsewhere in this file. */
    z-index: 10;
}

.h2h-help-tooltip {
    display: none;
    position: absolute;
    top: 130%;
    right: 0;
    z-index: 200;
    width: 260px;
    max-width: 80vw;
    padding: 0.75rem 0.9rem;
    border-radius: 8px;
    border: 1px solid rgba(201, 162, 75, 0.6);
    /* Same dark, opaque tone as the "?" button's own background
       (rgba(15,15,15,0.3) over the felt green) rather than near-black, so
       it reads as part of the site instead of a foreign black box. */
    background: #123528;
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.45);
    font-size: 0.85rem;
    font-weight: 400;
    color: var(--cream);
    text-align: left;
    white-space: normal;
}

.h2h-help.open .h2h-help-tooltip {
    display: block;
}

.btn {
    display: inline-block;
    padding: 0.75rem 1.25rem;
    border-radius: 8px;
    border: none;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    text-align: center;
    text-decoration: none;
    transition: transform 0.05s ease-in-out, filter 0.15s ease;
}

.tap-btn:disabled,
.btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.btn:active {
    transform: scale(0.97);
}

.btn-primary {
    background: var(--gold);
    color: var(--wood-brown-dark);
    width: 100%;
}

.btn-primary:hover {
    filter: brightness(1.08);
}

.btn-block {
    width: 100%;
    margin-bottom: 0.6rem;
}

.btn-vk {
    background: #0077ff;
    color: #fff;
}

.btn-yandex {
    background: #fc3f1d;
    color: #fff;
}

.btn-outline {
    background: transparent;
    border: 1px solid var(--gold);
    color: var(--gold);
}

.alert {
    padding: 0.75rem 1rem;
    border-radius: 8px;
    margin-bottom: 1rem;
    font-size: 0.9rem;
}

.alert-error {
    background: rgba(179, 64, 47, 0.25);
    border: 1px solid var(--danger);
    color: #ffd9d0;
}

.alert-success {
    background: rgba(11, 110, 79, 0.35);
    border: 1px solid var(--felt-green);
    color: #d9f5ea;
}

.alert-warning {
    background: rgba(201, 162, 75, 0.18);
    border: 1px solid var(--gold);
    color: var(--gold-light);
}

.alert-warning a {
    color: var(--gold-light);
    text-decoration: underline;
}

/* .alert-warning a's color would otherwise win over .btn-primary's (same
   class-count, but one more element in the selector) — gold-light text on a
   gold button background is nearly unreadable. */
.alert-warning .btn-primary {
    color: var(--wood-brown-dark);
    text-decoration: none;
}

.divider {
    display: flex;
    align-items: center;
    text-align: center;
    color: rgba(245, 239, 230, 0.6);
    margin: 1.25rem 0;
    font-size: 0.85rem;
}

.divider::before,
.divider::after {
    content: '';
    flex: 1;
    border-bottom: 1px solid rgba(245, 239, 230, 0.25);
}

.divider:not(:empty)::before {
    margin-right: 0.75rem;
}

.divider:not(:empty)::after {
    margin-left: 0.75rem;
}

.helper-text {
    margin-top: 1rem;
    font-size: 0.9rem;
    text-align: center;
    color: rgba(245, 239, 230, 0.85);
}

/* Match / meeting screens (touch-friendly, larger tap targets). Players
   stack vertically (up to 10 per match) rather than side-by-side, since a
   horizontal grid stops being usable past two or three players. */
.match-board {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}

.player-panel {
    background: rgba(15, 15, 15, 0.3);
    border: 1px solid rgba(201, 162, 75, 0.35);
    border-radius: var(--radius);
    padding: 0.85rem 1rem;
}

.player-panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.6rem;
}

.player-identity {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.player-drag-handle {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    margin-left: -0.4rem;
    padding: 0;
    border: none;
    background: transparent;
    color: rgba(245, 239, 230, 0.45);
    cursor: grab;
    touch-action: none;
}

.player-drag-handle:active {
    cursor: grabbing;
    color: var(--gold);
}

.player-panel-dragging {
    z-index: 5;
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
    transition: none !important;
}

.player-panel .player-name {
    font-weight: 700;
    color: var(--gold);
    word-break: break-word;
}

.player-panel .player-score {
    flex-shrink: 0;
    text-align: right;
    white-space: nowrap;
}

.player-panel .ball-count {
    font-size: 1.9rem;
    font-weight: 800;
}

.player-panel .series-count,
.player-panel .fluke-count,
.player-panel .penalty-count {
    display: block;
    font-size: 0.8rem;
    color: rgba(245, 239, 230, 0.7);
}

.player-actions {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.player-actions .tap-btn {
    flex: 1;
    margin-bottom: 0;
}

.tap-btn {
    display: block;
    width: 100%;
    padding: 0.85rem;
    margin-bottom: 0.5rem;
    font-size: 1.05rem;
    border-radius: 10px;
    border: none;
    font-weight: 700;
    cursor: pointer;
}

.tap-btn-ball {
    background: var(--gold);
    color: var(--wood-brown-dark);
}

.tap-btn-fluke {
    background: rgba(255, 255, 255, 0.15);
    color: var(--cream);
    border: 1px solid rgba(255, 255, 255, 0.35);
    font-size: 0.9rem;
}

.tap-btn-penalty {
    background: rgba(200, 60, 60, 0.18);
    color: var(--cream);
    border: 1px solid rgba(200, 60, 60, 0.45);
    font-size: 0.9rem;
}

.match-card {
    position: relative;
    padding: 1.5rem 0.6rem;
}

.match-card h2 {
    padding-right: 2.5rem;
}

.ball-shelf {
    margin-bottom: 0.75rem;
}

.extra-stats {
    margin-top: 1.25rem;
    margin-bottom: 1.25rem;
}

.extra-stats summary {
    cursor: pointer;
    font-size: 0.85rem;
    color: rgba(245, 239, 230, 0.6);
    margin-bottom: 0.5rem;
    user-select: none;
}

.extra-stats[open] summary {
    margin-bottom: 0.75rem;
}

.ball-shelf-row {
    display: flex;
    gap: 0.4rem;
    margin-bottom: 0.75rem;
    /* No touch-action override here (used to be `none`, back when the shelf
       supported drag-to-slide and needed to keep the browser from treating
       that drag as a page scroll). Now that setting a level is a plain tap,
       `none` only did harm: it told the browser to never treat a touch
       starting on this row as a scroll gesture at all, which is exactly
       what caused an ordinary scroll swipe that started on a ball cell to
       mis-register as taps instead of scrolling the page. */
}

.ball-shelf-cell {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1;
    aspect-ratio: 1;
    min-width: 0;
    padding: 0;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.35);
    background: rgba(255, 255, 255, 0.08);
    color: rgba(245, 239, 230, 0.4);
    font-weight: 700;
    font-size: 0.9rem;
    line-height: 1;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
    user-select: none;
}

/* Desktop: 16 cells in one row instead of two rows of 8 — on a wide screen
   two rows of 8 makes each ball needlessly huge. display:contents lifts
   each row's cells to be direct flex children of .ball-shelf, so the same
   flex:1 sizing rule above just divides by 16 instead of 8, no markup
   changes needed. */
@media (min-width: 600px) {
    .ball-shelf {
        display: flex;
        gap: 0.4rem;
    }

    .ball-shelf-row {
        display: contents;
    }
}

.ball-shelf-cell-potted {
    background: var(--gold);
    border-color: var(--gold);
    color: var(--wood-brown-dark);
}

.ball-shelf-cell:disabled {
    cursor: not-allowed;
}

.player-actions-undo .tap-btn-undo {
    margin-bottom: 0;
}

.tap-btn-undo {
    background: transparent;
    color: rgba(245, 239, 230, 0.6);
    border: 1px dashed rgba(245, 239, 230, 0.3);
    font-size: 0.8rem;
    padding: 0.45rem;
}

.series-row {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.series-input {
    width: 3.2rem;
    flex-shrink: 0;
    padding: 0.6rem 0.4rem;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.25);
    background: rgba(255, 255, 255, 0.92);
    color: var(--text-on-light);
    font-size: 1rem;
    text-align: center;
}

.series-step-btn {
    flex-shrink: 0;
    width: 2.4rem;
    border-radius: 8px;
    border: 1px solid rgba(255, 255, 255, 0.35);
    background: rgba(255, 255, 255, 0.15);
    color: var(--cream);
    font-size: 1.1rem;
    font-weight: 700;
    cursor: pointer;
}

.series-step-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.series-step-btn:active {
    transform: scale(0.94);
}

.tap-btn-series {
    flex: 1;
    margin-bottom: 0;
    padding: 0.6rem;
    font-size: 0.9rem;
    background: rgba(255, 255, 255, 0.15);
    color: var(--cream);
    border: 1px solid rgba(255, 255, 255, 0.35);
}

.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 44px;
    height: 44px;
    border-radius: 10px;
    border: 1px solid rgba(255, 255, 255, 0.25);
    background: rgba(255, 255, 255, 0.08);
    cursor: pointer;
    padding: 0;
}

.icon-btn svg {
    width: 22px;
    height: 22px;
}

.icon-btn:active {
    transform: scale(0.94);
}

.icon-btn-danger {
    border-color: rgba(179, 64, 47, 0.5);
    background: rgba(179, 64, 47, 0.18);
    color: #ff8a75;
}

.match-timer {
    text-align: center;
    font-size: 2.25rem;
    font-weight: 800;
    letter-spacing: 0.05em;
    margin: 1rem 0 0.15rem;
}

.match-status {
    text-align: center;
    font-size: 0.95rem;
    color: rgba(245, 239, 230, 0.75);
    margin-bottom: 0.75rem;
}

.match-leader {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

.match-leader-icon {
    display: flex;
    align-items: center;
    color: rgba(158, 158, 158, 0.6);
    animation: match-leader-blink 2.4s ease-in-out infinite;
}

.match-leader-icon .trophy-icon {
    width: 18px;
    height: 18px;
}

@keyframes match-leader-blink {
    0%, 100% { opacity: 0.3; }
    50% { opacity: 0.9; }
}

.match-leader-player {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-weight: 700;
    color: var(--gold);
}

/* Same author-vs-UA-stylesheet tie as .stats-filter-dates[hidden] elsewhere
   in this file — the unconditional `display: flex` above needs an explicit
   override or [hidden] is silently ignored. */
.match-leader-player[hidden] {
    display: none;
}

.match-leader[hidden] {
    display: none;
}

.match-controls {
    display: flex;
    gap: 0.6rem;
    margin: 1rem 0;
}

.match-controls .btn {
    flex: 1;
}

@media (min-width: 600px) {
    .container {
        max-width: 720px;
    }
}

/* First modal in the app (last-ball-scorer confirmation on finish) — kept
   deliberately minimal rather than a fully generic modal system, since
   there's only this one use so far. */
.modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 50;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(0, 0, 0, 0.6);
}

.modal-overlay[hidden] {
    display: none;
}

.modal {
    width: 100%;
    max-width: 360px;
    background: var(--felt-green-dark);
    border: 1px solid rgba(201, 162, 75, 0.4);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 1.25rem;
}

.modal-title {
    margin: 0 0 1rem;
    color: var(--gold);
    font-size: 1.1rem;
    text-align: center;
}

.modal-player-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 1rem;
}

.modal-player-option {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    padding: 0.6rem 0.75rem;
    border-radius: 10px;
    border: 1px solid rgba(201, 162, 75, 0.35);
    background: rgba(255, 255, 255, 0.06);
    color: var(--cream);
    font-size: 1rem;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}

.modal-player-option:active {
    background: rgba(201, 162, 75, 0.2);
}

/* Universal button-loading state (public/assets/js/app.js + match.js) — kept
   at the very end of the file on purpose: .btn-loading needs to win over
   earlier same-specificity color/opacity rules on every button variant it
   can be combined with (.btn-primary, .btn-outline, .tap-btn-*, .icon-btn-*),
   and later-in-source wins a same-specificity tie. */
.btn-loading {
    position: relative;
    overflow: hidden;
    color: transparent !important;
    cursor: wait;
}

.btn-loading:disabled {
    opacity: 1;
}

.btn-loading::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    width: 18px;
    height: 18px;
    margin: -9px 0 0 -9px;
    border-radius: 50%;
    border: 2px solid rgba(245, 239, 230, 0.9);
    border-top-color: transparent;
    animation: btn-spinner-spin 0.7s linear infinite;
}

@keyframes btn-spinner-spin {
    to {
        transform: rotate(360deg);
    }
}
