/* ==========================================
   BetPlatform — Stake.com-Inspired Theme
   Responsive: Desktop + Mobile
   ========================================== */

/* --- Fonts. As of 2026-08-22 the page is set ENTIRELY in Oxanium: --font-body,
   --font-display, --font-brand, --font-head and --font-odds all resolve to it,
   so every string on screen shares one voice. The Futura PT faces below are no
   longer referenced by any token and therefore no longer download — they are
   kept declared so reverting is a one-line change to the tokens rather than a
   re-upload. (The Bast wordmark is artwork, not text, and never depended on them.)
   Futura PT is licensed + user-supplied, self-hosted in /fonts. Every uploaded
   file is Bold or heavier — no book/regular cut exists in the set.
   NOTE: filenames don't all match their contents (checked via font metadata):
   FTN85__W.woff2 is Futura PT Web Bold; FuturaPTCond.woff2 is Cond BOLD. */
@font-face {
    font-family: 'Futura PT Cond';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('/fonts/FuturaPTCond.woff2') format('woff2');
}
@font-face {
    font-family: 'Futura PT Cond';
    font-style: italic;
    font-weight: 700;
    font-display: swap;
    src: url('/fonts/FuturaPTCondBoldOblique.woff2') format('woff2');
}
@font-face {
    font-family: 'Futura PT Cond';
    font-style: italic;
    font-weight: 800;
    font-display: swap;
    src: url('/fonts/futura-pt_cond-extrabold-oblique.woff2') format('woff2');
}
@font-face {
    font-family: 'Futura PT Web';
    font-style: normal;
    font-weight: 700;
    font-display: swap;
    src: url('/fonts/FTN85__W.woff2') format('woff2');
}
@font-face {
    font-family: 'Futura PT Web';
    font-style: italic;
    font-weight: 700;
    font-display: swap;
    src: url('/fonts/FuturaPTBoldOblique.woff2') format('woff2');
}

/* Oxanium (Google Fonts, OFL) — VARIABLE weight 400-800 in a single file, so
   --font-head (700) and any lighter use draw from the same download. Squared
   geometric face: it carries section heads without the pinched look Futura PT
   Cond has in sentence case, and its digits are naturally MONOSPACED (measured:
   "1.11" and "8.88" render identically wide), which is why the odds columns
   below use it — prices stop shifting as they re-price.
   Subsets are latin + latin-ext ONLY — Oxanium ships no Greek. The `el` locale
   therefore falls back to the system stack for headings; digits are unaffected,
   so the odds board is identical in every language. */
@font-face {
    font-family: 'Oxanium';
    font-style: normal;
    font-weight: 400 800;
    font-display: swap;
    src: url('/fonts/oxanium-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: 'Oxanium';
    font-style: normal;
    font-weight: 400 800;
    font-display: swap;
    src: url('/fonts/oxanium-latin-ext.woff2') format('woff2');
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --- Reset & Base --- */
*,
*::before,
*::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

:root {
    /* Backstop for any page that links this stylesheet. index.html declares the
       same thing inline on <html> so it lands before this file loads — see the
       comment there for why iOS needs it. Keep both: the inline one wins the
       first paint, this one covers pages that forget it. */
    color-scheme: dark;
    /* 2026-10-07 restyle (branch `sherbimi`): bet365-style charcoal palette — neutral
       greys for every surface, yellow prices, a teal header bar + section rules. Bast's
       own green stays the CTA/brand accent. See DESIGN-SYSTEM.md. */
    --bg-primary: #282828;
    /* rgb triplets, for rgba(var(--x-rgb), a) — alpha variants of the surfaces without
       hard-coding the colour a second time. MUST track the hex tokens they mirror. */
    --bg-primary-rgb: 40, 40, 40;
    --bg-secondary-rgb: 51, 51, 51;
    --bg-tertiary-rgb: 68, 67, 67;
    --bg-deep-rgb: 30, 30, 30;
    /* Fully-transparent --bg-primary, for gradients that fade the page background
       out. MUST track --bg-primary above. It exists as its own token because a
       gradient stop of `transparent` is rgba(0,0,0,0) — interpolating towards it
       drags the ramp through black and leaves a grey haze across the middle of the
       fade. Fading to the SAME colour at zero alpha keeps the ramp clean.
       (color-mix() would express this without the duplication, but it is Safari
       16.2+; an unsupported value invalidates the whole declaration, which on the
       bottom nav would mean no background at all.) */
    --bg-primary-fade: rgba(40, 40, 40, 0);
    --bg-secondary: #333333;
    --bg-tertiary: #444343;
    --bg-card: #333333;
    --bg-input: #1e1e1e;
    --bg-hover: #4a4a4a;
    /* My Bets: an open ticket's selection panel (b3t's mid grey) and the ticket row ink. */
    --bg-ticket-open: #666666;
    --ticket-row-bg: var(--accent-teal);
    --text-primary: #ffffff;
    --text-secondary: #dddddd;
    --text-muted: #a7a7a7;
    /* Teal: the top header bar, the 1px rule above every section header, and the
       selected-odd state. --accent-teal-light is the softer teal for active links. */
    --accent-teal: #106046;
    --accent-teal-light: #4acfa5;
    --accent-teal-rgb: 10, 186, 181;   /* for rgba() tints of the teal */
    --header-bg: var(--accent-teal);
    --header-ink: #ffffff;                 /* text/icons on the teal bar */
    --header-active: var(--accent-odds);   /* active-tab underline on the bar */
    --scrim: rgba(0, 0, 0, 0.5);           /* dim behind drawers/sheets */
    --shadow-drawer: 4px 0 24px rgba(0, 0, 0, 0.4);
    /* SOLID by design: `color:`, `border-color:`, `outline:` and nested gradient stops
       cannot take a <gradient> — the browser drops the whole declaration. This used to
       hold the gradient, which silently killed ~106 rules (active bottom-nav item,
       possession bar, betslip tab underline...). The gradient lives on as
       --accent-green-grad; use THAT only for real `background:` fills. */
    --accent-green: color(display-p3 .752941 .909804 .286275 / 1);
    --odd-h: 44px;          /* dense-board price-button height (b3t rows are 44px; was 60) */
    /* 1a dense board: hairline row divider (was a 5px slab between every row) and
       the row's vertical padding. Both are single knobs so the board's density can
       be tuned — or a future "compact" toggle can drop them — in one place. */
    --border-subtle: #383838;
    /* Vertical padding on BOTH live-row columns (.live-match-info and
       .live-match-oddscol) — they must stay equal or their grid band rows drift
       apart. 3px, not the old 9px, is what makes the 90px row exact:
           3 + 58 (odds block: 50px buttons + 4px padding) + 26 (band) + 3 = 90
       The band supplies the breathing room the padding used to; raise this and
       the row grows past 90 rather than clipping (see min-height on
       .live-match-row). */
    --live-row-pad: 3px;
    --live-row-hover: #3a3a3a;
    /* Price-button width. Shared by .live-odd-btn, the "1 X 2" header spans and
       the O/U header label so the columns can never drift apart — which is why
       widening the prices is a one-line change here and not a three-way edit. */
    --odd-w: 58px;
    --accent-green-grad: linear-gradient(to bottom,color(display-p3 .752941 .909804 .286275 / 1),#36f670);
    --accent-green-neon: color(display-p3 .752941 .909804 .286275 / 1);
    --accent-blue: var(--accent-teal);   /* was #1475e1 — the last blue patches (promo badge, agent role) follow the teal */
    --accent-blue-ligth: #ffdf1b;
    --accent-red: #ed4163;
    /* --accent-red on a 15% red tint measures 3.29:1 — below WCAG AA for small
       text. This lighter variant is for RED TEXT ON A RED-TINTED SURFACE
       (status pills, chips); plain --accent-red stays correct on the page
       background, where it already passes. */
    --accent-red-soft: #ff7d90;
    --accent-red-ink: #b0173c;   /* red TEXT on a light or red-tinted surface (5:1 on a 15% red tint over #f0f0f0) */
    --accent-orange: #ff8c00;
    /* Operator re-offer (old -> offered) on a ticket line. Its own token, not
       --accent-orange: this one is measured against the ticket-detail surface
       (5.47:1 on --bg-primary, AA for small text) and must not drift if the
       generic orange is ever retuned. */
    --accent-offer: #fd7e14;
    --accent-odds: #ffdf1b;   /* prices are yellow (was blue #64b2fa) */
    --border-color: #444343;
    --sidebar-width: 236px;   /* 1a: 260 -> 236, giving the board the difference */
    --betslip-width: 400px;
    /* --header-bar is the visible 60px bar; --header-height additionally includes
       the top safe area (0 in the browser; status-bar height when the site runs as
       a fullscreen home-screen app with viewport-fit=cover) so every top offset
       that uses it clears the notch automatically. Use --header-bar in calcs that
       reserve space at the BOTTOM of the screen (betslip keyboard) where the top
       inset must not leak in. --bottom-nav-height is the mobile nav incl. the
       home-indicator inset — use it wherever content must clear the nav. */
    --header-bar: 47px;   /* slim teal bar, b3t's 47px (was 75px, then 52px) — 2026-10-07 restyle */
    --header-height: calc(var(--header-bar) + env(safe-area-inset-top, 0px));
    /* Flat full-width bar (2026-10-07): 60px of items plus the home-indicator
       inset. The extra clearance the old floating glass pill needed is gone —
       the bar is solid --bg-deep right to the bottom edge, so iOS Safari samples
       a solid colour for its toolbar tint. */
    --bottom-nav-height: calc(60px + env(safe-area-inset-bottom, 0px));
    /* Square shape (2026-10-07): every card/button/panel radius is 0. --radius-lg25
       stays — it is the pill radius, and pills (and 50% circles) remain round. */
    --radius-sm: 0;
    --radius-md: 0;
    --radius-lg: 0;
    --radius-dec: 0;
    --radius-lg25: 25px;
    --bg-odds: #505050;   /* b3t price cells */
    --bg-event: #494949;  /* b3t event cards / list rows, one step under the prices */
    --bg-footer: #474747; /* b3t footer band */
    --text-footer: #bababa;
    --bg-darkb: #1e1e1e;
    --bg-lightg: #545454;
    --text-cat: #ffffff;
    --bg-secondary-search: #1e1e1e;

    /* Promoted from repeated hardcoded hex values (were scattered across the CSS).
       Named by role+shade because several are near-duplicates of the accents
       above (e.g. --green-soft #3aa56e vs --accent-green #00e701) — kept distinct
       to preserve the exact current appearance; unify here later if desired. */
    --bg-deep:       #1e1e1e;   /* darkest panel/surface (was 27×) */
    --bg-green-deep: #0a1d12;   /* dark green tint background */
    --green-soft:    #3aa56e;   /* muted success green */
    --gold:          #f5c518;   /* gold (stars / highlights) */
    --amber:         #e0a32e;   /* amber */
    --text-light:    #e4e4e4;   /* light gray text */
    --red-soft:      #ff6b6b;   /* soft/coral red */
    --live-indicator-red: #F44336;   /* the LIVE mark on a bet slip selection */
    --gray-mid:      #545454;   /* mid gray */
    /* The SELECTED-odd background on all six odds-button families — b3t style since
       2026-10-07: light grey with a dark-green price (was blue #1674e1, then teal).
       The name --blue-alt is kept so those rules need no edit; their text colour is
       re-pointed at --odd-selected-ink in the BETSLIP (b3t) block at the end. */
    --odd-selected-bg:  #e4e4e4;
    --odd-selected-ink: #14805e;
    --odd-selected-ink-rgb: 20 128 94;   /* space-separated, for --rise-rgb */
    --accent-red-ink-rgb: 176 23 60;     /* --accent-red-ink, space-separated, for --rise-rgb */
    /* Management trees (Finance, Tickets "Të grupuara"): an expanded branch's accounts
       wear one of these, a branch after another, so where one parent's accounts end
       and the next node begins reads at a glance. rgb triplets, for rgba() tints. */
    --mg-branch-1-rgb: 74, 207, 165;
    --mg-branch-2-rgb: 100, 178, 250;
    --mg-branch-3-rgb: 255, 140, 0;
    --mg-branch-4-rgb: 186, 120, 255;
    --mg-branch-5-rgb: 255, 223, 27;
    --mg-branch-6-rgb: 255, 125, 144;
    /* Live statistics as bet365's match-live grid (js/livesports.js): the split bars'
       track, and the "Show more" / scope pills. */
    --stat-track: #666666;
    --stat-pill-bg: rgba(255, 255, 255, 0.1);
    /* The pitch / video switch as the pitch modules' media button (css/live-mobile.css): its
       box, bet365's --color-white10p, and its rounded corners. */
    --media-switch-bg: rgba(255, 255, 255, 0.1);
    --media-switch-radius: 5px;
    /* The pitch modules' menu names (bet365's LocationEventsMenu_Text): the phone's
       statistics bar reads the same. */
    --ml-menu-text: rgba(255, 255, 255, 0.8);
    --blue-alt:      var(--odd-selected-bg);
    /* Betslip (b3t style): a LIGHT sheet over the dark page. */
    --slip-bar-bg:      #f0f0f0;   /* collapsed bar + sheet head */
    --slip-bg:          #dddddd;   /* selection rows */
    --slip-line:        #c7c7c7;   /* row and key separators */
    --slip-ink:         #404040;   /* match name, head text */
    --slip-ink-2:       #545454;   /* market line, prices */
    --slip-ink-3:       #757575;   /* small labels */
    --slip-ink-pick:    #000000;   /* the pick, apart from its market */
    --slip-accent:      #106046;   /* count disc, stake amount */
    --slip-accent-tint: rgba(74, 207, 165, 0.2);   /* behind the stake amount */
    --slip-accent-gkali: #4acfa5;
    --slip-place-bg:    #585858;   /* Place half of the footer */
    --slip-key-ink:     #666666;   /* keypad digits */
    --slip-delete:      #a63838;   /* swipe-to-delete panel */
    --mybets-total-bg:  #a9a9a9;   /* My Bets 'Totali' bar (b3t) */
    /* Match timeline (js/matchtimeline.js + css/matchtimeline.css): a finished match drawn
       from Betradar's timeline in the LIGHT statistics popup (My Bets, Management). The
       dark livescore page sets the same names to its own values (livescore.html :root). */
    --mtl-card:     #ffffff;                  /* cards on the popup's grey */
    --mtl-line:     #dcdcdc;                  /* card borders, set dividers */
    --mtl-text:     #262626;
    --mtl-mid:      var(--gray-mid);
    --mtl-muted:    #6b6b6b;
    --mtl-home:     var(--accent-teal);       /* home: its dot, the chart above the line */
    --mtl-home-ink: var(--accent-teal);       /* home name and score on white, 7.5:1 */
    --mtl-away:     var(--accent-orange);     /* away: its dot, the chart below the line */
    --mtl-away-ink: #a34f00;                  /* away name and score on white, 5.7:1 */
    --mtl-zero:     #bdbdbd;                  /* zero line, period cuts, empty bars */
    --mtl-chip:     #e6e6e6;                  /* set scores, totals */
    --mtl-win:      var(--accent-teal);       /* the winner's total, white on it like the header */
    --mtl-win-ink:  var(--header-ink);

    /* Display face for headings/big numbers. Was Futura PT Cond (restored 2026-08-03
       for hierarchy); repointed to Oxanium 2026-08-22 so the page speaks in ONE voice.
       Kept as a separate token from --font-body even though both now resolve to the
       same family: the ~40 rules that reference it are the "this is display type"
       inventory, and collapsing them into --font-body would throw that away and make
       any future split a manual re-hunt. Hierarchy now comes from weight and size —
       Oxanium is variable 400-800, which Futura PT Cond (bold-only) could not offer,
       so headings no longer have to shout to look like headings. */
    /* 2026-10-07 restyle: UI text is back on a neutral system stack (Helvetica-like,
       bet365-style). Oxanium is kept ONLY on --font-brand. */
    --font-display: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, 'Segoe UI', Roboto, Arial, sans-serif;

    /* UI face for EVERYTHING — Oxanium (2026-08-22). `body` reads this token and
       the whole app inherits from there, so this one line is the page's voice.
       The system stack stays behind it as the fallback and is doing real work:
       Oxanium ships latin + latin-ext only, so Greek (`el`) renders from the
       stack, and Oxanium has no italic cut, so <em> is synthesised.
       Trade-off worth knowing: Oxanium is a display face doing a body job. That
       suits this product — nearly all of its text is short (team names, market
       labels, prices) — but it is measurably slower to read in long prose. If the
       T&C / help pages start to feel heavy, give them `font-family: var(--font-read)`
       rather than reverting this token; the split is the fix, not the retreat. */
    --font-body: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, 'Segoe UI', Roboto, Arial, sans-serif;

    /* The old system stack, kept addressable for long-form reading surfaces. */
    --font-read: BlinkMacSystemFont, 'Helvetica Neue', 'Segoe UI', Tahoma, Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Open Sans', sans-serif;

    /* Branded display face — jackpot 777 branding + Bet Boost team names (grouped rule
       at the end of this file). Also Oxanium as of 2026-08-22: "everywhere on the page"
       includes these. The token stays so those surfaces remain addressable if the
       jackpot ever wants its own face again. NOTE the Bast wordmark itself is artwork
       (/img SVG), not text — it is unaffected by any of these tokens. */
    --font-brand: 'Oxanium', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, 'Segoe UI', Roboto, Arial, sans-serif;

    /* Section heads + prices moved off Futura PT Cond onto Oxanium (2026-08-22).
       Two separate tokens rather than repointing --font-display, because that var
       also carries the jackpot branding, page titles and the wallet balance —
       repointing it would have swept in a dozen surfaces nobody asked to change.
       --font-head : sentence-case section headings. Futura PT Cond is a condensed
                     cut, and condensed geometrics only look right in caps; set in
                     sentence case at 20px beside a system-ui UI it read as pinched.
       --font-odds : prices and the numerals around them. Oxanium's figures are
                     monospaced by construction, so a column of odds holds its
                     alignment through a re-price without tabular-nums having to
                     rescue it (the property is still set — belt and braces, and it
                     also covers the system-stack fallback). */
    /* System stack now (was Oxanium). Its digits are NOT monospaced, so price columns
       rely on `font-variant-numeric: tabular-nums` on the odds rules to hold alignment. */
    --font-head: var(--font-body);
    --font-odds: var(--font-body);

    /* ================================================================
       Design-token color palette (imported 2026-07-22, operator-supplied).
       Entries struck through in the source list (deprecated) were NOT added.
       ================================================================ */
    /* greens */
    --color-green126E51: #126e51;
    --color-green137A5A: #137a5a;
    --color-green14805E: #14805e;
    --color-green168361: #168361;
    --color-green189970: #189970;
    --color-green1F4D3E: #1f4d3e;
    --color-green2EC193: #2ec193;
    --color-green2F8E70: #2f8e70;
    --color-green26FFBE: #26ffbe;
    --color-green367A65: #367a65;
    --color-green3D8246: #3d8246;
    --color-green424C38: #424c38;
    --color-green50714D: #50714d;
    --color-green5C917B: #5c917b;
    --color-green58D7AF: #58d7af;
    --color-green007A56: #007a56;
    --color-greenF0FFF7: #f0fff7;
    --color-green94FFE2: #94ffe2;
    --color-green116E51: #116e51;
    --color-green0D221B: #0d221b;
    --color-green0D221B-20p: rgba(13, 34, 27, .2);
    --color-green0D221B-0p: rgba(13, 34, 27, 0);
    --color-green102420: #102420;
    --color-green0E3328: #0e3328;
    --color-green146E51: #146e51;
    --color-green164334: #164334;
    --color-green164334-95p: rgba(22, 67, 52, .95);
    --color-green0AA373: #0aa373;
    --color-green53FFA2: #53ffa2;
    --color-green9DED64: #9ded64;
    --color-green28594A: #28594a;
    --color-green32614E: #32614e;
    --color-green252928: #252928;
    --color-green189970-30p: rgba(24, 153, 112, .3);
    --color-green189970-75p: rgba(24, 153, 112, .75);
    --color-green28FFBB-60p: rgba(40, 255, 187, .6);
    --color-green28FFBB-90p: rgba(40, 255, 187, .9);
    --color-green28FFBB-1p: #28ffbb;
    --color-green28FFBB-50p: rgba(40, 255, 187, .5);
    --color-green51FFDF-15p: rgba(81, 255, 223, .15);
    --color-green1: #126e51;
    --color-green2: #189970;
    --color-green5: #00b050;
    --color-greenC9FF7D: #c9ff7d;
    --color-green2-75p: rgba(24, 153, 112, .75);
    --color-green2-30p: rgba(24, 153, 112, .3);

    /* yellows / oranges */
    --color-yellowFFE43C: #ffe43c;
    --color-orange1: #f56e14;
    --color-orangeFFBD96: #ffbd96;
    --color-orangeFFB240: #ffb240;
    --color-orangeCB9281: #cb9281;
    --color-orange945B25: #945b25;

    /* reds */
    --color-redA63838: #a63838;
    --color-redCB4545: #cb4545;
    --color-redFC5353: #fc5353;
    --color-redF0D1D2: #f0d1d2;
    --color-redFF6666: #f66;
    --color-red564B46: #564b46;
    --color-red3: #d32020;

    /* blues */
    --color-blue1: #379de6;
    --color-blue2-80p: #004679cc;
    --color-blue2-0p: #00467900;
    --color-blue379DE6: #379de6;

    /* greys (hex-named) */
    --color-grey00: #000;
    --color-grey11: #111;
    --color-grey14: #141414;
    --color-grey1F: #1f1f1f;
    --color-grey22: #222;
    --color-grey28: #282828;
    --color-grey33: #333;
    --color-grey38: #383838;
    --color-grey40: #404040;
    --color-grey44: #444;
    --color-grey47: #474747;
    --color-grey4C: #4c4c4c;
    --color-grey4F: #4f4f4f;
    --color-grey50: #505050;
    --color-grey5D: #5d5d5d;
    --color-grey54: #545454;
    --color-grey57: #575757;
    --color-grey58: #585858;
    --color-grey63: #636363;
    --color-grey66: #666;
    --color-grey6A: #6a6a6a;
    --color-grey6E: #6e6e6e;
    --color-grey75: #757575;
    --color-grey7A: #7a7a7a;
    --color-grey88: #888;
    --color-grey99: #999;
    --color-grey9C: #9c9c9c;
    --color-greyA7: #a7a7a7;
    --color-greyAE: #aeaeae;
    --color-greyBB: #bbb;
    --color-greyCC: #ccc;
    --color-greyDD: #ddd;
    --color-greyE4: #e4e4e4;
    --color-greyFF: #fff;
    --color-grey3E342E: #3e342e;
    --color-grey3E342E00: #3E342E00;
    --color-grey605854: #605854;
    --color-grey63786C-f5p: #63786cf5;
    --color-grey3A322D: #3a322d;
    --color-grey2E2B28: #2e2b28;
    --color-grey2E2B28-60p: rgba(46, 43, 40, .6);

    /* greys (numbered aliases) */
    --color-grey0: #000;
    --color-grey1: #1f1f1f;
    --color-grey2: #282828;
    --color-grey3: #383838;
    --color-grey4: #444;
    --color-grey5: #a7a7a7;
    --color-grey6: #ccc;
    --color-grey7: #ddd;
    --color-grey8: #fff;
    --color-grey9: #e4e4e4;
    --color-grey10: #4f4f4f;

    /* whites */
    --color-white80p: hsla(0, 0%, 100%, .8);
    --color-white75p: hsla(0, 0%, 100%, .75);
    --color-white70p: hsla(0, 0%, 100%, .7);
    --color-white65p: hsla(0, 0%, 100%, .65);
    --color-white60p: hsla(0, 0%, 100%, .6);
    --color-white55p: hsla(0, 0%, 100%, .55);
    --color-white50p: hsla(0, 0%, 100%, .5);
    --color-white40p: hsla(0, 0%, 100%, .4);
    --color-white30p: hsla(0, 0%, 100%, .3);
    --color-white25p: hsla(0, 0%, 100%, .25);
    --color-white20p: hsla(0, 0%, 100%, .2);
    --color-white15p: hsla(0, 0%, 100%, .15);
    --color-white10p: hsla(0, 0%, 100%, .1);
    --color-white7p: hsla(0, 0%, 100%, .07);
    --color-white5p: hsla(0, 0%, 100%, .05);
    --color-whiteB5: #b5b5b5;
    --color-whiteB8: #b8b8b8;
    --color-whiteC3: #c3c3c3;
    --color-whiteCE: #cecece;
    --color-whiteD4: #d4d4d4;
    --color-whiteDD: #ddd;
    --color-whiteE4: #e4e4e4;
    --color-whiteFF: #fff;
    --color-whiteF0: #f0f0f0;
    --color-whiteF8: #f8f8f8;

    /* black / alpha overlays */
    --color-grey00-10p: rgba(0, 0, 0, .1);
    --color-grey00-15p: rgba(0, 0, 0, .15);
    --color-grey00-20p: rgba(0, 0, 0, .2);
    --color-grey00-25p: rgba(0, 0, 0, .25);
    --color-grey00-30p: rgba(0, 0, 0, .3);
    --color-grey00-35p: rgba(0, 0, 0, .35);
    --color-grey00-40p: rgba(0, 0, 0, .4);
    --color-grey00-50p: rgba(0, 0, 0, .5);
    --color-grey00-60p: rgba(0, 0, 0, .6);
    --color-grey00-70p: rgba(0, 0, 0, .7);
    --color-grey00-80p: rgba(0, 0, 0, .8);
    --color-grey0-10p: rgba(0, 0, 0, .1);
    --color-grey0-15p: rgba(0, 0, 0, .15);
    --color-grey0-20p: rgba(0, 0, 0, .2);
    --color-grey0-25p: rgba(0, 0, 0, .25);
    --color-grey0-35p: rgba(0, 0, 0, .35);
    --color-grey0-40p: rgba(0, 0, 0, .4);
    --color-greyCC-40p: hsla(0, 0%, 80%, .4);
    --color-greyCC-50p: hsla(0, 0%, 80%, .5);
    --color-grey1F-45p: rgba(31, 31, 31, .45);
    --color-grey6-50p: hsla(0, 0%, 80%, .5);
    --color-grey8-15p: hsla(0, 0%, 80%, .15);
    --color-grey11-73p: hsla(0, 0%, 7%, .73);
    --color-grey11-74p: hsla(0, 0%, 7%, .74);
    --color-black60p: rgba(0, 0, 0, .6);
    --color-black40p: rgba(0, 0, 0, .4);
    --color-grey50p: hsla(0, 0%, 61%, .5);
    --color-grey30p: rgba(0, 0, 0, .3);
    --color-transparent: transparent;

    /* glow */
    --color-glow-light: hsl(222 70% 95%);
    --color-glow-medium: hsl(222 100% 80%);
    --color-glow-strong: hsl(222 100% 70%);

    /* gradients */
    --grad-green-303D39-grey-353535: linear-gradient(to bottom right, #303d39, #353535);
    --grad-green: linear-gradient(245deg, #c9ff7d, #c9ff7d 49%, rgba(222, 255, 175, 0));
    --grad-jackpot: linear-gradient(90deg, rgba(228, 249, 238, .35), rgba(138, 255, 171, .35));
    --color-gradient3: linear-gradient(to bottom right, #303d39, #353535);
    --color-gradient4: linear-gradient(120deg, #303d39, #444 56%);
    --color-champ-league-background: linear-gradient(-16deg, #383838 51%, #1e3d30);

    /* icon data-URIs (imported with the palette). NOTE: betBoost/superBoost carry a
       literal {1} and membersIcon a literal {0} fill/stroke placeholder from the
       source system — substitute a real color before first use. */
    --icon-androidShareButton: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7 0-.24-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92 0-1.61-1.31-2.92-2.92-2.92Z' fill='%23b5b5b5'/%3E%3C/svg%3E");
    --icon-arrowDown: url("data:image/svg+xml;charset=utf-8,%3Csvg height='4' width='7' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M3.5 4 7 0H0z' fill-rule='evenodd'/%3E%3C/svg%3E");
    --icon-arrowUp: url("data:image/svg+xml;charset=utf-8,%3Csvg height='4' width='7' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M3.5 0 0 4h7z' fill-rule='evenodd'/%3E%3C/svg%3E");
    --icon-arrowLeft: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13.982' height='12.705'%3E%3Cpath d='m6.307 0 .71.705-.315.317-.165.165-.223.225-.125.126-.204.205-.16.16-1.787 1.802-.21.21-1.755 1.769-.14.14-.176.178L13.982 6v1H2.052l.079.08.127.127.138.14.153.153.081.082.176.177.193.195L7.016 12l-.71.705-4.62-4.654-.203-.205-.121-.122-.112-.113-.053-.053-.1-.101-.049-.049-.093-.094-.045-.045-.09-.09-.178-.18-.19-.19-.102-.104L0 6.352.35 6l.703-.708.124-.126.28-.282.171-.172.095-.095.21-.212L3.328 3l.21-.21L5.365.949l.131-.133.332-.334.108-.11.056-.055.117-.118L6.307 0Z' fill='%23FFF' fill-rule='nonzero'/%3E%3C/svg%3E");
    --icon-arrowLeftThick: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='12'%3E%3Cpath fill='color(display-p3 1.000 1.000 1.000)' fill-rule='evenodd' d='M6.702.26a.891.891 0 0 1 0 1.26L3.135 5.092h9.954a.912.912 0 0 1 0 1.825H3.042l3.522 3.526a.913.913 0 0 1 0 1.29.91.91 0 0 1-1.288 0L.26 6.71a.891.891 0 0 1 0-1.26L5.444.261a.888.888 0 0 1 1.258 0Z'/%3E%3C/svg%3E");
    --icon-audio: url("data:image/svg+xml;charset=utf-8,%3Csvg width='12' height='9' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23353535' fill-rule='evenodd'%3E%3Cpath d='M9.027 8.57c1.149-1.57 1.516-2.745 1.516-4.038 0-1.296-.383-2.576-1.516-4.126L9.593 0l.06.083c1.165 1.616 1.63 3.057 1.63 4.45 0 1.413-.467 2.795-1.69 4.467l-.566-.43Z'/%3E%3Cpath d='M7.522 6.955c.716-.89 1.046-1.408 1.046-2.454 0-1.074-.312-1.588-1.046-2.459l.68-.406.082.1c.728.88 1.119 1.606 1.119 2.765 0 1.242-.528 2.024-1.202 2.863l-.679-.41Zm-4.513-4.5C3.616 1.923 5.279 0 5.266 0h.752v9h-.752L3.009 6.545H.752C.107 6.537-.005 6.261 0 5.727V3.273c.01-.541.467-.846.752-.818.73-.022 2.257 0 2.257 0Z'/%3E%3C/g%3E%3C/svg%3E");
    --icon-bell: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='19' height='21.4'%3E%3Cg fill='none' fill-rule='evenodd' stroke='%23383838'%3E%3Cpath d='M9.5.501c-.195 0-1.677-.11-1.797 1.583 0 1.688-3.591.329-3.591 6.859C4.112 15.609.5 13.492.5 16.95c3.42.03 5.743 0 5.743 0S6.069 20.9 9.5 20.9M9.5.501c.195 0 1.677-.11 1.797 1.583 0 1.688 3.592.329 3.592 6.859 0 6.666 3.611 4.549 3.611 8.007-3.42.03-5.743 0-5.743 0s.174 3.95-3.257 3.95'/%3E%3Cpath fill='%23B5B5B5' fill-rule='nonzero' stroke-linecap='square' d='m6.793 16.944 5.432.013'/%3E%3C/g%3E%3C/svg%3E");
    --icon-betBoost: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 11 9'%3E%3Cpath fill='{1}' fill-rule='evenodd' d='M6.798 0 11 4.504 6.798 9H3.952l4.202-4.5L3.952 0h2.846ZM2.846 0l4.202 4.504L2.846 9H0l4.202-4.5L0 0h2.846Z'/%3E%3C/svg%3E");
    --icon-charity: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10'%3E%3Cpath fill='%23B5B5B5' fill-rule='evenodd' d='M9 0a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1h8ZM5.13 1.709c-1.875 0-3.03 1.294-3.03 3.393 0 2.103 1.16 3.397 3.03 3.397 1.558 0 2.695-.962 2.807-2.359H6.621c-.13.712-.712 1.168-1.486 1.168-1.02 0-1.652-.846-1.652-2.206 0-1.361.631-2.202 1.647-2.202.77 0 1.356.487 1.486 1.23h1.316C7.834 2.725 6.661 1.709 5.13 1.709Z'/%3E%3C/svg%3E");
    --icon-checkmark: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='10'%3E%3Cpath fill='%23FFF' d='M0 4.809 4.76 10 13 1.145 12.005 0 4.76 7.71 1.066 3.74z'/%3E%3C/svg%3E");
    --icon-chevronDown: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='5' viewBox='0 0 12 7'%3E%3Cpath fill='%23333' fill-rule='evenodd' d='M12 .784 11.243 0 6 5.431.757 0 0 .784l5.243 5.432L6 7l.757-.784z'/%3E%3C/svg%3E");
    --icon-chevronDownThick: url("data:image/svg+xml;charset=utf-8,%3Csvg width='14' height='9' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m12 0 1.414 1.414-6.707 6.707L0 1.414 1.414 0l5.293 5.292z' fill='%23FFF'/%3E%3C/svg%3E");
    --icon-chevronLeft: url("data:image/svg+xml;charset=utf-8,%3Csvg height='12' width='7' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6.216 12 7 11.243 1.569 6 7 .757 6.216 0 .784 5.243 0 6l.784.757z' fill='%23333' fill-rule='evenodd'/%3E%3C/svg%3E");
    --icon-chevronRight: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='7' height='12'%3E%3Cpath fill='%23333' fill-rule='evenodd' d='M.784 12 0 11.242 5.43 6 0 .758.784 0l5.432 5.242L7 6l-.784.758z'/%3E%3C/svg%3E");
    --icon-chevronUp: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='7'%3E%3Cpath fill='%23333' fill-rule='evenodd' d='M12 6.216 11.243 7 6 1.569.757 7 0 6.216 5.243.784 6 0l.757.784z'/%3E%3C/svg%3E");
    --icon-cross: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12'%3E%3Cpath fill='%23444' fill-rule='evenodd' d='M1.5 12 0 10.5 4.5 6 0 1.5 1.5 0 6 4.5 10.5 0 12 1.5 7.5 6l4.5 4.5-1.5 1.5L6 7.5z'/%3E%3C/svg%3E");
    --icon-cup: url("data:image/svg+xml;charset=utf-8,%3Csvg height='12' width='12' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5.538 7.4c-.73-.629-2.63-2.51-2.786-2.581a5.995 5.995 0 0 1-.812-.438C.425 3.371-.529 1.977.316.855c.422-.56 1.157-.66 2.061-.46.12.026.243.057.392.105-.006-.314.011-.5 0-.5h6.462c-.007 0 .011.185 0 .5.153-.049.273-.08.392-.106.904-.199 1.639-.1 2.061.461.845 1.122-.109 2.516-1.624 3.526-.217.145-.492.29-.812.438-.143.065-2.065 1.952-2.786 2.581v3l1.846.6v1H3.692v-1l1.846-.587zM2.772 1.42c-.187-.063-.437-.162-.61-.2-.574-.126-.94-.077-1.087.119-.433.574.554 1.655 1.697 2.416zm6.507 0v2.335c1.143-.761 2.13-1.842 1.697-2.416-.147-.196-.513-.245-1.088-.119-.172.038-.422.137-.61.2z' fill='%23333'/%3E%3C/svg%3E");
    --icon-favouriteStar: url("data:image/svg+xml;charset=utf-8,%3Csvg height='21' width='21' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10.5 17.412 4.01 21l1.24-7.6L0 8.018 7.255 6.91 10.499 0l3.244 6.91L21 8.018 15.751 13.4l1.234 7.6' fill='%23fff'/%3E%3C/svg%3E");
    --icon-favouriteStarOutlined: url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 21 21' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m16.22 19.908-1.093-6.703 4.663-4.779-6.441-.984-2.849-6.07-2.849 6.07-6.44.984 4.662 4.78-1.093 6.702 5.72-3.162z' fill='none' stroke='%23FFF' stroke-width='1.167'/%3E%3C/svg%3E");
    --icon-fluctuation: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='9.008' height='7'%3E%3Cpath fill='%23383838' fill-rule='evenodd' d='M9.008 7 4.504 0 0 7h1.462l3.042-5.007L7.539 7z'/%3E%3C/svg%3E");
    --icon-hamburger: url("data:image/svg+xml;charset=utf-8,%3Csvg width='9' height='9' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%23DDD' fill-rule='evenodd'%3E%3Cpath d='M9 0v1H0V0zM9 4v1H0V4zM9 8v1H0V8z'/%3E%3C/g%3E%3C/svg%3E");
    --icon-iOSShareButtonNew: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='31' height='30'%3E%3Cpath fill='%23fff' d='M11.584 21.105h6.838q.985 0 1.496-.509.51-.509.51-1.481v-5.77q0-.973-.51-1.482-.511-.509-1.496-.509H16.85v1.318h1.459q.386 0 .594.2.208.2.208.61v5.495q0 .408-.208.61-.208.2-.594.2h-6.616q-.39 0-.594-.2-.204-.202-.204-.61v-5.495q0-.41.204-.61t.594-.2h1.482v-1.318h-1.591q-.983 0-1.495.507-.512.507-.512 1.484v5.77q0 .976.512 1.483.512.507 1.495.507ZM15 16.322q.255 0 .432-.178.177-.177.177-.421V9.839l-.05-.875.34.445.784.834q.16.176.4.176.215 0 .375-.145t.16-.372q0-.207-.169-.377l-1.98-1.903q-.117-.117-.231-.164-.115-.047-.238-.047-.119 0-.233.047-.113.047-.236.164l-1.98 1.903q-.165.17-.165.377 0 .227.156.372t.374.145q.245 0 .405-.176l.78-.834.345-.445-.051.875v5.884q0 .244.178.421.177.178.427.178Z'/%3E%3C/svg%3E");
    --icon-line: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='2'%3E%3Cpath fill='%23FFF' fill-opacity='.4' fill-rule='evenodd' d='M0 0h12v2H0z'/%3E%3C/svg%3E");
    --icon-lock: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='13'%3E%3Cpath fill='%23333' fill-rule='evenodd' d='M4.919 0c1.914 0 3.466 1.585 3.466 3.54v1.406h.774c.464 0 .841.377.841.841v6.372a.842.842 0 0 1-.841.841H.841A.842.842 0 0 1 0 12.159V5.787a.84.84 0 0 1 .841-.84l.61-.001V3.54C1.451 1.585 3.004 0 4.919 0ZM5 6.907c-.584 0-1.057.486-1.057 1.086 0 .363.174.685.44.882l-.15 1.794-.002.029c0 .189.153.342.342.342h.894l.015-.002a.34.34 0 0 0 .311-.369l-.152-1.812c.253-.199.416-.512.416-.864 0-.6-.473-1.086-1.057-1.086Zm-.081-5.269c-1.021 0-1.85.836-1.867 1.873v.031l-.001 1.404h3.734V3.542c0-1.051-.836-1.904-1.866-1.904Z'/%3E%3C/svg%3E");
    --icon-membersIcon: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 19'%3E%3Cpath fill='none' stroke='{0}' d='M8.455 12.167c3.278 0 6.178 1.26 7.863 3.377-2.078 1.707-4.459 2.759-7.094 2.93-4.177-.191-6.72-1.298-8.556-3.025 1.696-2.06 4.558-3.282 7.787-3.282ZM8.5.5c1.243 0 2.368.504 3.182 1.318A4.486 4.486 0 0 1 13 5a4.486 4.486 0 0 1-1.318 3.182A4.486 4.486 0 0 1 8.5 9.5a4.486 4.486 0 0 1-3.182-1.318A4.486 4.486 0 0 1 4 5c0-1.243.504-2.368 1.318-3.182A4.486 4.486 0 0 1 8.5.5Z'/%3E%3C/svg%3E");
    --icon-neutralVenue: url("data:image/svg+xml;charset=utf-8,%3Csvg width='12' height='12' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0 0h12v12H0V0Zm4.636 2.5H3v6.75h1.636V5.2l2.728 4.05H9V2.5H7.364v3.873L4.636 2.5Z' fill='%23353535' fill-rule='evenodd'/%3E%3C/svg%3E");
    --icon-plus: url("data:image/svg+xml;charset=utf-8,%3Csvg width='7' height='7' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='%2326FFBE' fill-rule='evenodd'%3E%3Cpath d='M0 2.8h7v1.4H0z'/%3E%3Cpath d='M2.8 0h1.4v7H2.8z'/%3E%3C/g%3E%3C/svg%3E");
    --icon-questionMarkInfo: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16'%3E%3Cg fill='none' fill-rule='evenodd' transform='translate(1 1)'%3E%3Ccircle cx='7' cy='7' r='7' stroke='%23383838'/%3E%3Cpath fill='%23383838' fill-rule='nonzero' d='M5.939 8.349h1.553v-.314c0-.19.03-.356.088-.496.058-.14.16-.273.304-.4.145-.127.347-.266.607-.416.412-.242.724-.522.934-.84.211-.32.317-.698.317-1.138v-.011c0-.446-.116-.838-.347-1.178a2.317 2.317 0 0 0-.973-.797c-.417-.191-.905-.287-1.463-.287-.598 0-1.107.104-1.527.31-.42.208-.742.495-.967.863-.224.369-.342.79-.354 1.267v.012l1.585-.006.012-.003c.01-.218.063-.41.16-.572.098-.163.232-.29.4-.378.17-.09.365-.134.588-.134a1.3 1.3 0 0 1 .585.125.978.978 0 0 1 .39.338.89.89 0 0 1 .138.492v.012c0 .182-.029.341-.087.48-.06.137-.16.268-.304.393a4.126 4.126 0 0 1-.593.413 2.832 2.832 0 0 0-.649.507c-.165.18-.28.384-.344.612a2.33 2.33 0 0 0-.062.806l.01.34Zm.838 2.821c.33 0 .59-.087.78-.262.189-.175.283-.414.283-.716 0-.307-.094-.548-.284-.722-.19-.175-.449-.263-.779-.263-.328 0-.588.088-.78.263-.19.174-.286.415-.286.722 0 .302.095.541.287.716.191.175.45.262.779.262Z'/%3E%3C/g%3E%3C/svg%3E");
    --icon-riskFree: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='17' height='11'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cpath stroke='%23131415' stroke-width='1.5' d='m7.5 5.59 8-4.09-1.349 8z'/%3E%3Cpath fill='%23131415' fill-rule='nonzero' d='m10.5.5-.238 1.412-.05.294L3.411 5.67l5.658 3.313-.07.415-.185 1.102-1.117-.656-6.224-3.659L.5 5.613l1.017-.52 7.487-3.828z'/%3E%3C/g%3E%3C/svg%3E");
    --icon-SGP: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='23.277' height='9.009'%3E%3Cg fill='none'%3E%3Cpath fill='%23FFF' d='M4.147 0C2.314 0 .962 1.157.962 2.73c0 1.17.455 1.729 2.002 2.509.819.403 1.014.611 1.014.988 0 .533-.468.884-1.157.884-.598 0-1.053-.182-1.833-.715L0 8.06c1.157.715 1.885.949 2.925.949 1.937 0 3.315-1.222 3.315-2.964 0-1.144-.494-1.755-1.924-2.431-.884-.416-1.105-.624-1.105-1.04 0-.468.377-.754.975-.754.468 0 .936.195 1.521.637L6.669.793C5.824.247 5.031 0 4.147 0Zm7.115 5.759h2.015c-.195.819-.936 1.352-1.885 1.352-1.326 0-2.275-1.001-2.275-2.405 0-1.625 1.053-2.847 2.43-2.847.95 0 1.6.468 2.029 1.417l1.91-.741c-.35-.832-.571-1.131-1.117-1.599C13.628.312 12.705 0 11.599 0 8.857 0 6.855 2.002 6.855 4.745c0 2.522 1.768 4.264 4.316 4.264 1.885 0 3.432-.975 4.043-2.587.286-.728.403-1.443.429-2.405H11.47l-.208 1.742Z'/%3E%3Cpath fill='%2328FFBB' d='M16.062 8.84h2.197l.351-2.873h.975c1.378 0 2.418-.351 3.016-1.001.585-.637.676-1.417.676-2.041 0-.572-.078-1.352-.728-1.989S21.015.169 20.027.169h-2.899L16.062 8.84Zm3.653-6.851c.312 0 .78-.013 1.066.286.13.13.247.364.247.741 0 .195-.026.52-.273.767-.338.338-.91.364-1.222.364h-.689l.26-2.158h.611Z'/%3E%3C/g%3E%3C/svg%3E");
    --icon-share: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='18'%3E%3Cpath fill='%23FFF' d='M11.7 5.385H9.1v.854h2.6c.358 0 .406.06.406.408v10.092c0 .347-.048.411-.406.411H1.3c-.357 0-.38-.064-.38-.411V6.647c0-.346.022-.408.38-.408h2.6v-.854H1.3c-.719 0-1.3.564-1.3 1.262v10.092C0 17.436.581 18 1.3 18h10.4c.719 0 1.3-.564 1.3-1.261V6.647c0-.698-.581-1.262-1.3-1.262ZM4.132 3.403l1.889-1.986v9.96c0 .173.3.316.479.316.178 0 .467-.143.467-.316v-9.96l1.9 1.982c.066.064.431.158.616 0 .223-.158.127-.518 0-.64L6.967.236c-.263-.315-.703-.315-.946 0l-2.6 2.523c-.127.122-.22.456 0 .64.265.206.581.127.711.004Z'/%3E%3C/svg%3E");
    --icon-stats: url("data:image/svg+xml;charset=utf-8,%3Csvg width='13' height='13' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M5 0h3v13H5V0Zm5 3h3v10h-3V3ZM0 7h3v6H0V7Z' fill='%23333' fill-rule='evenodd'/%3E%3C/svg%3E");
    --icon-streaming: url("data:image/svg+xml;charset=utf-8,%3Csvg width='25' height='15' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Crect stroke-opacity='.4' stroke='%23FFF' x='.5' y='.5' width='24' height='14' rx='2.333'/%3E%3Cpath fill='%23DDD' opacity='.8' d='m10 11 .005-7L16 7.513z'/%3E%3C/g%3E%3C/svg%3E");
    --icon-superBoost: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 17 9'%3E%3Cpath fill='{1}' fill-rule='evenodd' d='m7.769 0 4.981 4.504L7.769 9H4.395l4.98-4.5L4.395 0h3.374Zm4.25 0L17 4.504 12.019 9H8.645l4.98-4.5L8.645 0h3.374ZM3.374 0l4.981 4.504L3.375 9H0l4.981-4.5L0 0h3.374Z'/%3E%3C/svg%3E");
    --icon-winningBoost: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='9'%3E%3Cpath fill='%23fff' fill-rule='evenodd' d='M7.285 0 12 4.504 7.285 9H4.091l4.715-4.5L4.091 0h3.194ZM2.983 2.077l-.001 1.817h1.79v1.212l-1.79-.001.001 1.818H1.79l-.001-1.818H0v-1.21l1.789-.001V2.077h1.194Z'/%3E%3C/svg%3E");

    /* Live football pitch (js/livepitch.js, css/livepitch.css). Illustration
       colours for the stadium scene; team colours come from the feed. */
    --pitch-stadium:      #121412;   /* behind everything: the dark bowl */
    --pitch-roof:         #0a0b0a;
    --pitch-roof-edge:    rgba(255, 255, 255, 0.16);
    --pitch-grass:        #3b7d36;
    --pitch-grass-stripe: #43883d;
    --pitch-light-in:     rgba(255, 255, 255, 0.10);
    --pitch-light-out:    rgba(0, 0, 0, 0.28);
    --pitch-line:         rgba(236, 243, 234, 0.85);
    --pitch-net:          rgba(255, 255, 255, 0.42);
    --pitch-post:         #f4f4f4;
    --pitch-ball:         #ffffff;
    --pitch-shadow:       rgba(0, 0, 0, 0.45);
    --pitch-board-bg:     #0d1810;
    --pitch-board-ink:    #ffffff;
    --pitch-board-copy:   var(--accent-teal-light);
    --pitch-flash-bg:     #ffffff;
    --pitch-flash-ink:    #161616;
    --pitch-chrome:       rgba(0, 0, 0, 0.62);   /* clock pill */
    --pitch-clock-ink:    var(--accent-teal-light);
    --pitch-card-top:     #2c362e;
    --pitch-card-bottom:  #1b1f1c;
    --pitch-card-sub:     var(--accent-teal-light);
    --pitch-card-yellow:  #f4d415;
    --pitch-card-red:     #df2a34;
    --pitch-wipe-base:    #0b100c;
    --pitch-info-top:     #262826;
    --pitch-info-bottom:  #1f201f;

    /* Tennis league headers in the court's colour (.live-league-group[data-court]) */
    --court-clay:   #b84a2e;   /* terre battue */
    --court-grass:  #5e8a2c;   /* lawn, lighter than football's pitch */
    --court-indoor: #55509e;   /* indoor / carpet */
}

/* Wide-gamut (Display-P3) overrides for the token palette — browsers that support
   color(display-p3) get the more saturated originals; these tokens have NO sRGB
   base definition (their struck-through sRGB entries were deliberately dropped),
   so they only exist on P3-capable browsers. */
@supports (color:color(display-p3 0 1 0)) {
    :root {
        --color-green28FFBB: color(display-p3 .157 1 .733);
        --color-green94FFDD: color(display-p3 .58 1 .867);
        --color-green00DEA9: color(display-p3 .282 .859 .675);
        --color-yellowFFDF1B: color(display-p3 1 .875 .106);
        --color-yellowFFDF1B-65p: color(display-p3 1 .875 .106 / .65);
        --color-redB42C33: color(display-p3 .651 .22 .22);
        --color-redE14D53: color(display-p3 .816 .345 .345);
        --grad-green-28FFBB-green-53FFA2: linear-gradient(to bottom right, color(display-p3 .157 1 .733), color(display-p3 .541 1 .671));
        --grad-green-004E42-green-1E2B29: linear-gradient(to bottom right, color(display-p3 .106 .302 .259), #1e2b29);
        --color-green28FFBB-30p: color(display-p3 .157 1 .733 / .3);
        --color-green28FFBB-65p: color(display-p3 .157 1 .733 / .65);
        --color-green28FFBB-70p: color(display-p3 .157 1 .733 / .7);
        --color-green28FFBB-80p: color(display-p3 .157 1 .733 / .8);
        --color-green28FFBB-95p: color(display-p3 .157 1 .733 / .95);
        --color-green28FFBE-20p: color(display-p3 .157 1 .733 / .2);
        --color-green3: color(display-p3 .157 1 .733);
        --color-green4: color(display-p3 .282 .859 .675);
        --color-yellow1: color(display-p3 1 .875 .106);
        --color-red1: color(display-p3 .651 .22 .22);
        --color-red2: color(display-p3 .816 .345 .345);
        --color-green3-30p: color(display-p3 .157 1 .733 / .3);
        --color-gradient1: linear-gradient(to bottom right, color(display-p3 .157 1 .733), color(display-p3 .541 1 .671));
        --color-gradient2: linear-gradient(to bottom right, color(display-p3 .106 .302 .259), #1e2b29);
    }
}

/* Headings + KPI numbers get the condensed display face. Slight positive
   tracking because condensed bold sets tight at large sizes. Div-based
   title classes that don't use h-tags are listed explicitly. */
h1, h2, h3, h4,
.sidebar-heading,
.browse-section-title,
.dash-kpi-value {
    font-family: var(--font-display);
    font-weight: 700;
    letter-spacing: 0.015em;
}

html {
    height: 100%;
    /* Set here as well as on body. Body-background propagation already paints the
       canvas, so this changes nothing on screen — but iOS Safari reads the ROOT
       element to tint its own toolbar, and a transparent root leaves it guessing.
       That is why the toolbar came out darker than the page and why theme-color
       appeared to be ignored: it wasn't ignored, it was being overruled by what
       Safari sampled here.
       Must stay the same value as body's background below. */
    background: var(--bg-primary);
    /* IMPORTANT: do NOT add `overflow-x: hidden` here. It creates a new
       scrolling context that kills `position: sticky` on the sidebar
       (sidebar would scroll along with the page). The horizontal-drift
       fix lives on body + touch-action instead.
       `overscroll-behavior-x: none` is safe and disables the rubber-band
       bounce on iOS without changing the scrolling context. */
    overscroll-behavior-x: none;
}

body {
    /* Reads the token rather than repeating the stack — the two had already
       drifted apart (this listed the same faces in a different order), so a
       change to --font-body silently did nothing to the page it was named for. */
    font-family: var(--font-body);
    background: var(--bg-primary);
    color: var(--text-primary);
    min-height: 100vh;
    font-size: 14px;
    line-height: 1.5;
    /* `clip`, NOT `hidden` — and the two lines are a deliberate pair.
       `overflow-x: hidden` makes the OTHER axis compute to `auto`, so body
       becomes a scroll container. FIREFOX then treats body as the nearest
       scrolling ancestor for `position: sticky` descendants — but body isn't
       what actually scrolls (the viewport is), so sticky never engages and the
       element just rides the page. That is why the live match-detail rail
       (.live-md-side, the scout pitch) pinned in Chrome and scrolled away in
       Firefox off identical CSS.
       `overflow: clip` clips WITHOUT creating a scroll container, which is
       exactly what the horizontal-drift fix wanted in the first place — it is
       also stricter, since clipped content can't be scrolled to even
       programmatically. The `hidden` line above it is the fallback for engines
       without `clip` (Safari < 16); they ignore the second declaration.
       See the matching note on `html` above: do NOT move either of these to the
       root element, which kills sticky in every browser. */
    overflow-x: hidden;
    overflow-x: clip;
    overscroll-behavior-x: none;
    /* Constrain page-level gestures to vertical pans only. Horizontal
       scrollers (`.matches-scroll`, etc.) override this with their own
       `touch-action: pan-x` further down the cascade, so they keep
       working — but the page itself stops sliding sideways during a
       noisy mostly-vertical swipe. */
    touch-action: pan-y;
}

a {
    color: inherit;
    text-decoration: none;
    cursor: pointer;
}

button {
    font-family: inherit;
    cursor: pointer;
    border: none;
    outline: none;
}

/* Accessibility — keyboard focus ring.
 * The resets above strip default outlines, which left keyboard users with no
 * visible focus anywhere. Restore one consistent ring for every interactive
 * element. :focus-visible only fires for keyboard/programmatic focus, so it
 * never shows on mouse/touch. :where() keeps specificity low; the :focus-visible
 * pseudo still outranks the `outline: none` element resets. Component-specific
 * focus rules (e.g. .live-odd-btn:focus-visible) continue to override this. */
/* Keyboard focus ring for actionable elements. Text inputs/selects/textareas are
 * intentionally excluded — they already show focus via their own border-color
 * change, and Safari applies :focus-visible to inputs on plain tap (not just
 * keyboard), which produced an unwanted blue outline on the betslip stake box. */
:where(a, button, [role="button"], [role="tab"], [tabindex]):focus-visible {
    outline: 2px solid var(--accent-odds);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

/* Visually hidden but available to screen readers (skip-link target, the
 * landing <h1>, etc.). */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Skip link — hidden off-screen until it receives keyboard focus, then slides
 * into the top-left corner. First focusable element on the page. */
.skip-link {
    position: fixed;
    top: 8px;
    left: 8px;
    z-index: 1000;
    transform: translateY(-150%);
    padding: 10px 16px;
    background: var(--bg-secondary);
    color: var(--text-primary);
    border: 1px solid var(--accent-green);
    border-radius: var(--radius-md);
    font-weight: 700;
    transition: transform 0.15s ease;
}
.skip-link:focus {
    transform: translateY(0);
}

/* Clickable elements */
.match-card,
.league-match-row,
.league-card,
.browse-sport-item,
.modal-match-item,
.modal-league-item,
.country-pill,
.sidebar-item,
.tab-btn,
.md-cat-btn,
.promo-slide,
.nav-link,
.bottom-nav-item {
    cursor: pointer;
}

/* Disable double-tap zoom on interactive elements */
button,
a,
input,
select,
textarea,
.match-card,
.league-match-row,
.league-card,
.odd-btn-inline,
.odd-btn-card,
.md-odd-btn {
    touch-action: manipulation;
}

input {
    font-family: inherit;
    outline: none;
}

/* --- Page Loader --- */
.page-loader {
    position: fixed;
    inset: 0;
    z-index: 9999;
    background: var(--bg-primary);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: opacity 0.4s ease, visibility 0.4s;
    overflow: hidden;
}

.page-loader::before {
    content: '';
    position: absolute;
    width: 300px;
    height: 300px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(0, 231, 1, 0.08) 0%, transparent 70%);
    animation: loaderPulseGlow 2s ease-in-out infinite;
}

.page-loader.hidden {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

.loader-content {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 28px;
    z-index: 1;
}

.loader-logo {
    height: 70px;
    width: auto;
    animation: loaderLogoFloat 2s ease-in-out infinite;
}

.loader-dots {
    display: flex;
    gap: 8px;
    align-items: center;
}

.loader-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    background: var(--accent-green-grad);
    animation: loaderDotBounce 1.4s ease-in-out infinite;
}

.loader-dot:nth-child(1) {
    animation-delay: 0s;
}

.loader-dot:nth-child(2) {
    animation-delay: 0.16s;
}

.loader-dot:nth-child(3) {
    animation-delay: 0.32s;
}

.loader-bar {
    width: 120px;
    height: 3px;
    background: var(--border-color);
    border-radius: 2px;
    overflow: hidden;
    margin-top: -8px;
}

.loader-bar-inner {
    width: 40%;
    height: 100%;
    background: var(--accent-green-grad);
    border-radius: 0;
    animation: loaderBarSlide 1.2s ease-in-out infinite;
}

@keyframes loaderLogoFloat {

    0%,
    100% {
        transform: translateY(0);
    }

    50% {
        transform: translateY(-8px);
    }
}

@keyframes loaderDotBounce {

    0%,
    80%,
    100% {
        transform: scale(0.6);
        opacity: 0.4;
    }

    40% {
        transform: scale(1);
        opacity: 1;
    }
}

@keyframes loaderBarSlide {
    0% {
        transform: translateX(-100%);
    }

    50% {
        transform: translateX(200%);
    }

    100% {
        transform: translateX(-100%);
    }
}

@keyframes loaderPulseGlow {

    0%,
    100% {
        transform: scale(0.8);
        opacity: 0.3;
    }

    50% {
        transform: scale(1.2);
        opacity: 0.6;
    }
}

/* --- Remove borders from cards/panels --- */
.match-card,
.league-card,
.league-group,
.sidebar,
.betslip-panel,
.md-market {
    border: none !important;
}

/* --- Scrollbar --- */
::-webkit-scrollbar {
    width: 6px;
}

::-webkit-scrollbar-track {
    background: var(--bg-primary);
}

::-webkit-scrollbar-thumb {
    background: var(--bg-hover);
    border-radius: 0;
}

/* ==========================================
   LOGIN
   ========================================== */
.login-overlay {
    position: relative;
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 16px;
    padding: 20px;
    /* Sport-oriented backdrop: a tinted stadium photo under a dark gradient so the
       frosted card stays legible and the green accent reads against it. The gradient
       sits ABOVE the image (listed first) and fades top→bottom for a vignette feel. */
    background:
        linear-gradient(160deg, rgba(var(--bg-primary-rgb), 0.82) 0%, rgba(var(--bg-deep-rgb), 0.72) 45%, rgba(var(--bg-primary-rgb), 0.94) 100%),
        url('/img/banners/sports_bg.jpg') center / cover no-repeat;
    overflow: hidden;
}

/* Soft green glow behind the card — subtle "stadium floodlight" energy. */
.login-overlay::before {
    content: '';
    position: absolute;
    top: 42%;
    left: 50%;
    width: 520px;
    height: 520px;
    transform: translate(-50%, -50%);
    background: radial-gradient(circle, rgba(0, 231, 1, 0.12) 0%, rgba(0, 231, 1, 0) 70%);
    pointer-events: none;
    z-index: 0;
}

.login-container {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 420px;
    padding: 40px;
    /* Frosted glass panel over the stadium photo. */
    background: rgba(var(--bg-secondary-rgb), 0.74);
    backdrop-filter: blur(18px) saturate(125%);
    -webkit-backdrop-filter: blur(18px) saturate(125%);
    border-radius: 0;
    border: 1px solid rgba(255, 255, 255, 0.09);
    box-shadow: 0 28px 70px rgba(0, 0, 0, 0.55);
    overflow: hidden;
}

/* Green accent bar across the top edge of the card. */
.login-container::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: linear-gradient(90deg, transparent, var(--accent-green) 50%, transparent);
}

.login-logo {
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 18px;
}

.login-logo-img {
    height: 52px;
    width: auto;
}

/* Welcome heading inside the login form (hidden automatically with the form when the
   forgot-password view is shown, since it lives inside #login-form). */
.login-welcome {
    text-align: center;
    margin-bottom: 28px;
}

.login-welcome h1 {
    font-size: 22px;
    font-weight: 800;
    color: var(--text-primary);
    margin: 0 0 6px;
    letter-spacing: -0.3px;
}

.login-welcome p {
    font-size: 13px;
    color: var(--text-muted);
    margin: 0;
}

/* ---- Exchange teaser strip under the login card ---- */
.login-promo {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 420px;
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 18px;
    border-radius: 0;
    background: rgba(var(--bg-secondary-rgb), 0.6);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    /* Neutral border at rest so the green Hyr CTA stays the single strongest
       focal point. The badge + icon carry the green accent instead. */
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
}

.login-promo-icon {
    flex-shrink: 0;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 0;
    color: var(--accent-green);
    background: rgba(0, 231, 1, 0.12);
    border: 1px solid rgba(0, 231, 1, 0.25);
}

.login-promo-text {
    min-width: 0;
}

.login-promo-top {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 3px;
}

.login-promo-badge {
    flex-shrink: 0;
    padding: 2px 7px;
    border-radius: 999px;
    background: var(--accent-green-grad);
    color: #06210b;
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.08em;
    white-space: nowrap;
}

.login-promo-name {
    font-size: 13px;
    font-weight: 700;
    color: var(--text-primary);
}

.login-promo-slogan {
    font-size: 12px;
    line-height: 1.35;
    color: var(--text-secondary);
}

.login-promo {
    cursor: pointer;
    transition: border-color 0.15s, transform 0.15s;
}

.login-promo:hover {
    border-color: rgba(0, 231, 1, 0.35);
    transform: translateY(-1px);
}

.login-promo:focus-visible {
    outline: 2px solid var(--accent-green);
    outline-offset: 2px;
}

/* ---- Exchange promo modal ---- */
.exchange-modal {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}

.exchange-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(var(--bg-deep-rgb), 0.72);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}

.exchange-modal-card {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 560px;
    max-height: calc(100dvh - 40px);
    overflow-y: auto;
    padding: 44px 36px 40px;
    text-align: center;
    border-radius: 0;
    border: 1px solid rgba(255, 255, 255, 0.08);
    background:
        radial-gradient(120% 90% at 50% 0%, rgba(0, 231, 1, 0.16) 0%, rgba(0, 231, 1, 0) 55%),
        linear-gradient(160deg, #123127 0%, #0a1f18 55%, var(--bg-primary) 100%);
    box-shadow: 0 32px 80px rgba(0, 0, 0, 0.6);
    animation: exchangeModalIn 0.22s ease;
}

@keyframes exchangeModalIn {
    from { opacity: 0; transform: translateY(12px) scale(0.98); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

.exchange-modal-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: linear-gradient(90deg, transparent, var(--accent-green) 50%, transparent);
}

.exchange-modal-close {
    position: absolute;
    top: 14px;
    right: 14px;
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.1);
    color: var(--text-secondary);
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}

.exchange-modal-close:hover {
    background: rgba(255, 255, 255, 0.12);
    color: var(--text-primary);
}

/* ---- Login corner language dropdown ---- */
.login-lang-corner {
    position: absolute;
    top: 18px;
    right: 18px;
    z-index: 20;
}

.login-lang-select {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 40px;
    padding: 8px 12px;
    background: rgba(var(--bg-secondary-rgb), 0.7);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 0;
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 500;
    cursor: pointer;
    transition: border-color 0.15s, color 0.15s;
}

.login-lang-select:hover {
    border-color: var(--accent-green);
    color: var(--text-primary);
}

.login-lang-chev {
    color: var(--text-muted);
    flex-shrink: 0;
}

.login-lang-flag {
    display: inline-flex;
    align-items: center;
}

.login-lang-flag img {
    width: 20px;
    height: 20px;
    border-radius: 0;
    display: block;
}

.login-lang-menu {
    position: absolute;
    top: calc(100% + 6px);
    right: 0;
    min-width: 170px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
    overflow: hidden;
    z-index: 21;
}

.login-lang-opt {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 10px 14px;
    background: transparent;
    border: none;
    color: var(--text-secondary);
    font-size: 13px;
    text-align: left;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}

.login-lang-opt:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}

.login-lang-opt.active {
    color: var(--accent-green);
}

@media (max-width: 520px) {
    .login-container {
        padding: 32px 24px;
    }
    .login-lang-corner {
        /* In-flow above the card (right-aligned) instead of floating over its
           top-right corner. Stays `relative` so the dropdown menu still anchors to it. */
        position: relative;
        top: auto;
        right: auto;
        align-self: flex-end;
        margin-bottom: 6px;
    }
    .login-lang-name {
        display: none;   /* flag + chevron only on narrow screens */
    }
}

.form-group {
    margin-bottom: 20px;
}

.form-group label {
    display: block;
    margin-bottom: 6px;
    font-size: 13px;
    font-weight: 500;
    color: var(--text-secondary);
}

.form-group input {
    width: 100%;
    padding: 12px 16px;
    border: 2px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-input);
    color: var(--text-primary);
    font-size: 14px;
    transition: border-color 0.2s;
}

.form-group input::placeholder {
    color: var(--text-muted);
}

.form-group input:focus {
    border-color: var(--accent-green);
}

/* Every primary action on the auth card. The two unlock buttons were missing
   from this list, so they fell through to the global button reset and
   rendered as bare highlighted text ("Send code", "Unlock account"). */
#login-btn,
#forgot-btn,
#unlock-send-btn,
#unlock-btn {
    width: 100%;
    padding: 14px;
    background: var(--accent-green-grad);
    color: var(--bg-deep);
    border: none;
    border-radius: var(--radius-md);
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
    transition: opacity 0.2s;
}

#login-btn:hover,
#forgot-btn:hover,
#unlock-send-btn:hover,
#unlock-btn:hover {
    opacity: 0.9;
}

#login-btn:disabled,
#forgot-btn:disabled,
#unlock-send-btn:disabled,
#unlock-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.error-message {
    margin-top: 16px;
    padding: 10px 14px;
    background: rgba(237, 65, 99, 0.15);
    border: 1px solid var(--accent-red);
    border-radius: var(--radius-sm);
    color: var(--accent-red);
    font-size: 13px;
    text-align: center;
}
/* Confirmations share the message slot ("a reset link is on its way", "a code
   is on its way", "Account unlocked"). They used to repaint only the TEXT green
   inline and kept the red error box — green-on-red read as a failure. auth.js
   toggles this class instead of touching style.color. */
.error-message.is-success {
    background: color-mix(in srgb, var(--accent-green) 12%, transparent);
    border-color: color-mix(in srgb, var(--accent-green) 55%, transparent);
    color: var(--accent-green);
}

/* Unlock view, step 2: the send button turns into a quiet "Resend code" and the
   code field + "Unlock account" take over as the primary path. */
#unlock-send-btn.is-secondary {
    background: transparent;
    color: var(--text-secondary);
    border: 1px solid var(--border-color);
}
#unlock-send-btn.is-secondary:hover {
    opacity: 1;
    color: var(--accent-green);
    border-color: var(--accent-green);
}
#unlock-code-group { margin-top: 20px; }
#unlock-code {
    letter-spacing: 0.35em;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.login-footer {
    margin-top: 8px;
    text-align: center;
    font-size: 13px;
    color: var(--text-muted);
}

.login-footer a {
    display: inline-block;
    /* 14px top/bottom padding → ~44px tap target around the link text. */
    padding: 14px 8px;
    color: var(--text-secondary);
    transition: color 0.2s;
}

.login-footer a:hover {
    color: var(--accent-green);
}

.login-footer .separator {
    margin: 0 10px;
    color: var(--border-color);
}

/* Self-service unlock link — shown under the login error only after a lockout. */
.login-unlock-link {
    display: block;
    text-align: center;
    margin: 8px 0 0;
    padding: 6px 8px;
    font-size: 13px;
    font-weight: 600;
    color: var(--accent-green);
    transition: opacity 0.2s;
}
.login-unlock-link:hover { opacity: 0.85; }

/* ==========================================
   REGISTER
   Shares the login overlay backdrop. Container is a bit wider to hold the country
   + currency dropdowns alongside the standard form fields.
   ========================================== */
.register-overlay {
    min-height: 100dvh;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    background: linear-gradient(135deg, var(--bg-deep) 0%, var(--bg-secondary) 50%, var(--bg-deep) 100%);
    padding: 32px 20px;
    overflow-y: auto;
}

.register-container {
    width: 100%;
    max-width: 460px;
    padding: 32px;
    background: var(--bg-secondary);
    border-radius: var(--radius-lg);
    border: 1px solid var(--border-color);
}

.register-header {
    text-align: center;
    margin-bottom: 24px;
}

.register-logo-img {
    height: 40px;
    width: auto;
    margin-bottom: 14px;
}

.register-header h2 {
    margin: 0 0 8px;
    font-size: 20px;
    font-weight: 700;
    color: var(--text-primary);
}

.register-subtitle {
    margin: 0;
    font-size: 12px;
    color: var(--text-muted);
    line-height: 1.5;
}

.reg-field {
    margin-bottom: 16px;
    position: relative;
}

.reg-field label {
    display: block;
    margin-bottom: 6px;
    font-size: 13px;
    font-weight: 500;
    color: var(--text-secondary);
}

.reg-field input {
    width: 100%;
    padding: 12px 14px;
    border: 2px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-input);
    color: var(--text-primary);
    font-size: 14px;
    transition: border-color 0.2s;
    box-sizing: border-box;
}

.reg-field input:focus {
    outline: none;
    border-color: var(--accent-green);
}

.reg-field input::placeholder {
    color: var(--text-muted);
}

.reg-password-row {
    position: relative;
    display: flex;
    align-items: center;
}

.reg-password-row input {
    padding-right: 70px;
}

.reg-pwd-toggle {
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    /* ≥40px tall so the tap target meets the ~44px guideline (the surrounding input
       padding makes the effective touch zone larger still). */
    min-height: 30px;
    padding: 0 12px;
    background: transparent;
    color: var(--text-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    font-size: 11px;
    cursor: pointer;
    font-weight: 600;
}

.reg-pwd-toggle:hover {
    color: var(--text-primary);
    border-color: var(--accent-green);
}

.reg-select-wrap {
    position: relative;
}

.reg-select {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 12px 14px;
    border: 2px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-input);
    color: var(--text-primary);
    font-size: 14px;
    cursor: pointer;
    box-sizing: border-box;
    user-select: none;
}

.reg-select:hover {
    border-color: var(--accent-green);
}

.reg-country-flag {
    font-size: 18px;
    line-height: 1;
}

.reg-country-name {
    flex: 1;
}

.reg-chevron {
    color: var(--text-muted);
    flex-shrink: 0;
}

.reg-dropdown {
    position: absolute;
    top: calc(100% + 4px);
    left: 0;
    right: 0;
    max-height: 280px;
    overflow-y: auto;
    background: var(--bg-input);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    z-index: 100;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
}

.reg-options {
    list-style: none;
    padding: 4px;
    margin: 0;
}

.reg-option {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    cursor: pointer;
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-size: 13px;
    transition: background 0.15s;
}

.reg-option:hover,
.reg-option.is-active {
    background: var(--bg-hover);
}

/* The pickers are keyboard controls now (Register._bindSelect). */
.reg-select:focus-visible {
    outline: none;
    border-color: var(--accent-green);
    box-shadow: 0 0 0 3px rgba(0, 202, 81, 0.25);
}

.reg-option-text {
    flex: 1;
}

.reg-error {
    margin-top: 6px;
    font-size: 12px;
    color: var(--accent-red);
}

.reg-hint {
    margin-top: 6px;
    font-size: 11px;
    color: var(--text-muted);
}

.reg-error-main {
    margin: 12px 0;
    padding: 10px 14px;
    background: rgba(237, 65, 99, 0.15);
    border: 1px solid var(--accent-red);
    border-radius: var(--radius-sm);
    text-align: center;
    font-size: 13px;
}

.reg-captcha-wrap,
.login-captcha,
.mt-captcha {
    margin: 16px 0;
    display: flex;
    justify-content: center;
}

.reg-actions {
    margin-top: 8px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.reg-submit {
    width: 100%;
    padding: 14px;
    background: var(--accent-green-grad);
    color: var(--bg-deep);
    border: none;
    border-radius: var(--radius-md);
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
    transition: opacity 0.2s;
}

.reg-submit:hover {
    opacity: 0.9;
}

.reg-submit:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.reg-back {
    width: 100%;
    padding: 12px;
    background: transparent;
    color: var(--text-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    font-size: 14px;
    cursor: pointer;
    transition: border-color 0.2s, color 0.2s;
}

.reg-back:hover {
    color: var(--text-primary);
    border-color: var(--text-secondary);
}

@media (max-width: 520px) {
    .register-container {
        padding: 24px 20px;
    }
    .register-header h2 {
        font-size: 18px;
    }
}

/* ==========================================
   TOP HEADER
   ========================================== */
.top-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 100;
    height: var(--header-height);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: env(safe-area-inset-top, 0px) 16px 0;
    /* Solid page colour — no frost. The header's structure is carried by the
       ROUNDED GROUPS on it (.header-left, .guest-actions), not by a slab with a
       drop shadow, so an opaque bar in the same colour as the page still reads as
       part of the app rather than a lighter band bolted above it.
       No bottom edge by design — no hairline, no shadow. */
    background: var(--bg-primary);
}

/* Brand + product switcher as one rounded card. Previously the logo and the
   toggle floated loose on the bar, so two unrelated-looking controls sat in the
   same corner; grouping them says "this is the brand, and this is which product
   you are in" as a single object. */
.header-left {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 4px 10px 4px 6px;
    border-radius: 999px;
    background: var(--bg-secondary);
    margin-top:5px;
    
}

/* Sidebar quick-nav — five icon buttons across the top of the rail, replacing the
   "Live / Live Overview" section (a labelled heading spent on one link).
   Grid rather than flex with space-between: equal 1fr tracks keep the icons on a
   fixed rhythm, so the row does not re-space itself if a button is ever added or
   hidden. */
.sidebar-quicknav {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    align-items: center;
    gap: 2px;
    padding: 4px 2px 12px;
    margin-bottom: 10px;
    border-bottom: 1px solid var(--border-subtle, var(--border-subtle));
}

.sq-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 38px;
    border-radius: 0;
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    color: var(--text-muted, #7c8798);
    transition: color 0.15s ease, background-color 0.15s ease;
}

.sq-btn svg {
    /* The source icons are 32x32 artboards with the glyph inset — drawn at 32 they
       would read far heavier than the 18px sport icons below them. 26 lands the
       visible glyph at roughly the same weight. */
    width: 26px;
    height: 26px;
    display: block;
}

.sq-btn:hover {
    color: var(--text-primary, #fff);
    background: var(--bg-hover, rgba(255, 255, 255, 0.07));
}

/* Current destination. Colour only — a filled chip here would compete with the
   accent disc in the header toggle two rows above it. */
.sq-btn.active {
    color: var(--accent-green-neon, #c0e849);
}

.sidebar-toggle {
    display: none;
    background: none;
    color: var(--text-secondary);
    padding: 6px;
    border-radius: var(--radius-sm);
}

.sidebar-toggle:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
}

.logo {
    display: flex;
    align-items: center;
}

.logo-img {
    height: 55px;
    width: 105px;
    padding-left: 6px;
}

/* Sports / Casino product switcher — two round icon buttons sitting in a recessed
   track, the selected one a filled accent disc.
   Was four background-image SVGs (default-/active- × sports/casino, plus -mini
   variants for phones) painting the whole 82x44 button. That shape carried three
   problems: the art files had to be kept in visual sync by hand for what is two
   states of one control; the wide artwork obliged a text label beside each icon;
   and the pair ate ~92px of a 375px header — enough that the sign-in button
   overlapped the casino tab. Drawing the states in CSS means the accent colour is
   defined once, and the control is now ~84px with the labels gone. */
.product-toggle {
    display: flex;
    align-items: center;
    gap: 4px;
    /* The track. A container reads the pair as ONE control with two positions,
       which two free-floating buttons did not — the old version relied entirely on
       the artwork differing to say which product you were in. */
    padding: 3px;
    border-radius: 999px;
    /* Darker than the card it sits in, so the track reads as recessed. A lighter
       tint would have made it a raised chip on a raised card — two levels going
       the same direction, which is why the toggle looked detached before. */
    background: rgba(0, 0, 0, 0.28);
}

.product-toggle-btn {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    color: var(--text-muted, #7c8798);
    /* Scale is on the list because the press feedback has to survive on a control
       with no label and no border — colour alone is a weak acknowledgement on a
       38px target. */
    transition: background-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
}

/* 38px circles (36px on phones): the tap area reaches 4px further up and down,
   44px on a phone. Not sideways — the two halves touch. */
.product-toggle-btn::after {
    content: '';
    position: absolute;
    inset: -4px 0;
}

.product-toggle-icon {
    width: 21px;
    height: 21px;
    flex-shrink: 0;
    /* Both glyphs are solid-fill single paths, so they take the button's colour.
       The casino icon arrives stroke-less; do not add a stroke here or the two
       will not weigh the same beside each other. */
}

.product-toggle-btn.active {
    background: var(--accent-green-neon, #c0e849);
    /* Dark glyph on the accent disc, NOT white: the accent is a light green, and
       white-on-it fails contrast badly (this is the same pairing .guest-btn-register
       already uses for its label). */
    color: var(--bg-deep);
}

.product-toggle-btn:active {
    transform: scale(0.92);
}

@media (hover: hover) {
    .product-toggle-btn:not(.active):hover {
        color: var(--text-primary, #fff);
        background: rgba(255, 255, 255, 0.07);
    }
}

.header-center {
    flex: 1;
    max-width: 480px;
    margin: 0 20px;
}

.search-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    background: var(--bg-input);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    transition: border-color 0.2s;
}

.search-bar:focus-within {
    border-color: var(--accent-green);
}

.search-icon {
    color: var(--text-muted);
    flex-shrink: 0;
}

.search-bar input {
    flex: 1;
    background: none;
    border: none;
    color: var(--text-primary);
    font-size: 13px;
}

.search-bar input::placeholder {
    color: var(--text-muted);
}

/* Search Dropdown */
.search-wrapper {
    position: relative;
    width: 100%;
}

.search-wrapper.active .search-bar {
    position: relative;
    z-index: 202;
}

.search-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(var(--bg-primary-rgb), 0.6);
    z-index: 200;
}

.search-overlay.active {
    display: block;
}

/* Search category toggle */
.search-category-toggle {
    position: relative;
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 5px 10px;
    background: var(--bg-tertiary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    flex-shrink: 0;
    transition: background 0.15s;
}

.search-category-toggle:hover {
    background: var(--bg-hover);
}

.search-category-dropdown {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    min-width: 120px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
    overflow: hidden;
    z-index: 210;
}

.search-cat-option {
    padding: 10px 14px;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-secondary);
    cursor: pointer;
    transition: all 0.1s;
}

.search-cat-option:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}

.search-cat-option.active {
    color: var(--accent-green);
    background: var(--bg-tertiary);
}

.search-clear {
    background: none;
    border: none;
    color: var(--text-muted);
    padding: 4px;
    cursor: pointer;
    flex-shrink: 0;
    transition: color 0.15s;
}

.search-clear:hover {
    color: var(--text-primary);
}

.search-dropdown {
    position: fixed;
    top: var(--header-height);
    left: 50%;
    transform: translateX(-50%);
    width: 100%;
    max-width: 600px;
    max-height: calc(100vh - var(--header-height) - 40px);
    max-height: calc(100dvh - var(--header-height) - 40px);
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
    overflow: hidden;
    z-index: 201;
    display: flex;
    flex-direction: column;
    margin-top: 12px;
}

@media (max-width: 600px) {
    .search-dropdown {
        max-width: none;
        left: 8px;
        right: 8px;
        width: auto;
        transform: none;
        max-height: calc(100vh - var(--header-height) - 20px);
        max-height: calc(100dvh - var(--header-height) - 20px);
        margin-top: 8px;
    }
}

.search-dropdown-header {
    display: flex;
    align-items: center;
    padding-right: 8px;
    flex-shrink: 0;
    border-bottom: 1px solid var(--border-color);
    height: 50px;
}

.search-dropdown-close {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    border-radius: 50%;
    transition: all 0.15s;
}

.search-dropdown-close:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
}

.search-sport-tabs {
    display: flex;
    gap: 6px;
    padding: 10px 14px;
    overflow-x: auto;
    scrollbar-width: none;
    flex: 1;
}

.search-sport-tabs::-webkit-scrollbar {
    display: none;
}

.search-sport-tab {
    display: flex;
    align-items: center;
    gap: 5px;
    padding: 6px 12px;
    background: var(--bg-tertiary);
    border: 1px solid var(--border-color);
    border-radius: 0;
    color: var(--text-secondary);
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    font-family: inherit;
    transition: all 0.15s;
}

.search-sport-tab:hover {
    background: var(--bg-hover);
}

.search-sport-tab.active {
    background: var(--accent-green-grad);
    color: var(--bg-deep);
    border-color: var(--accent-green);
}

.search-sport-tab-count {
    font-size: 10px;
    font-weight: 700;
    background: rgba(0, 0, 0, 0.15);
    padding: 1px 5px;
    border-radius: 0;
}

.search-results {
    overflow-y: auto;
    flex: 1;
    padding: 5px 16px 16px;
}

.search-result-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 10px;
    border-bottom: 1px solid rgba(var(--bg-tertiary-rgb), 0.3);
    cursor: pointer;
    transition: background 0.1s;
    border-radius: var(--radius-sm);
}

.search-result-item:hover {
    background: var(--bg-tertiary);
}

.search-result-item:last-child {
    border-bottom: none;
}

.search-result-kits {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex-shrink: 0;
}

.search-result-kits img {
    width: 20px;
    height: 20px;
    object-fit: contain;
}

.search-result-info {
    flex: 1;
    min-width: 0;
}

.search-result-teams {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.search-result-team {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.search-result-meta {
    font-size: 11px;
    color: var(--text-muted);
    margin-top: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.search-result-live-badge {
    font-size: 10px;
    font-weight: 700;
    color: var(--accent-red);
    padding: 1px 6px;
    background: rgba(237, 65, 99, 0.15);
    border-radius: var(--radius-sm);
    margin-right: 4px;
}

.search-empty {
    padding: 32px 16px;
    text-align: center;
    color: var(--text-muted);
    font-size: 13px;
}

/* Slot game result rows in the global search (when category = Casino).
   Lighter card style than the sports search match rows — square thumb on
   the left, name + provider chip on the right. Click anywhere on the row
   to launch the game (the row is the click target, not just inner pieces). */
.search-slot-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 12px;
    border-bottom: 1px solid var(--border-color);
    cursor: pointer;
    transition: background 0.12s ease;
}
.search-slot-row:hover {
    background: rgba(255, 255, 255, 0.04);
}
.search-slot-thumb-wrap {
    flex-shrink: 0;
    width: 56px;
    height: 56px;
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: linear-gradient(135deg, var(--bg-secondary), var(--bg-primary));
}
.search-slot-thumb {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.search-slot-text {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.search-slot-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    text-transform: capitalize;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.search-slot-provider {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
}

.header-right {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 200px;
    justify-content: flex-end;
}

.wallet-display {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    background: var(--bg-tertiary);
    border-radius: var(--radius-md);
    font-weight: 600;
    font-size: 14px;
    color: var(--text-primary);
    border: 1px solid var(--color-white10p);
    height: 30px;
}

.wallet-display svg {
    color: var(--accent-green);
}

.currency-badge {
    font-size: 11px;
    font-weight: 700;
    padding: 2px 6px;
    background: var(--bg-hover);
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
}

.wallet-display:hover {
    border:1px solid var(--color-green28FFBB)
}

/* User Menu */
.user-menu {
    position: relative;
    flex-shrink: 0;   /* never let a long balance squeeze/clip the menu icon */
}

.user-avatar {
    width: 36px;
    height: 36px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border-radius: 50%;
    color: #ffffff;
    cursor: pointer;
    transition: all 0.2s;
}

.user-avatar:hover {
    color: var(--text-muted);
}

/* User dropdown — sporty "player card" feel.
   - 300px on desktop, capped 92vw on mobile (room for fingers without
     dominating the viewport)
   - Player-card header with circular avatar + balance pill
   - Bigger touch targets on items (44px tall — meets the iOS HIG minimum)
   - Chevron arrow on every navigable item so it's obvious it goes somewhere
   - Slide-in animation feels native and mobile-friendly */
.user-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: 300px;
    max-width: 92vw;
    background:
        radial-gradient(circle at top right, rgba(58, 165, 110, 0.10), transparent 55%),
        linear-gradient(180deg, var(--bg-tertiary), var(--bg-tertiary));
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: 0 18px 48px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.4);
    /* Cap the height to the viewport and scroll when the list is long (e.g. admins
       see many extra items). overflow-x stays hidden so the rounded corners still clip;
       overflow-y auto adds the scrollbar only when needed. */
    overflow-x: hidden;
    overflow-y: auto;
    max-height: calc(100dvh - 90px);
    -webkit-overflow-scrolling: touch;
    /* Subtle slide + fade on appear. JS toggles display: block which is
       enough — `animation` fires on each display change. */
    animation: user-dropdown-in 180ms cubic-bezier(0.22, 0.61, 0.36, 1);
    transform-origin: top right;
}
@keyframes user-dropdown-in {
    from { opacity: 0; transform: translateY(-6px) scale(0.98); }
    to   { opacity: 1; transform: translateY(0)    scale(1); }
}

/* "Player card" header — avatar bubble + name on top, big balance line below.
   The dark accent diagonal gives it a touch of sport-app feel. */
.dropdown-user-info {
    position: relative;
    padding: 18px 18px 16px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    background:
        linear-gradient(135deg, rgba(58, 165, 110, 0.18) 0%, transparent 60%);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
/* Avatar circle in front of the username. Pure CSS — no extra HTML. */
.dropdown-user-info::before {
    content: '';
    position: absolute;
    top: 18px;
    right: 18px;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background:
        radial-gradient(circle at 50% 35%, #4cb37c, #2a7a52);
    box-shadow: 0 4px 12px rgba(58, 165, 110, 0.4),
                inset 0 -2px 6px rgba(0, 0, 0, 0.25);
}
/* Subtle "person" silhouette inside the avatar — drawn with SVG-via-mask. */
.dropdown-user-info::after {
    content: '';
    position: absolute;
    top: 26px;
    right: 26px;
    width: 24px;
    height: 24px;
    background: rgba(255, 255, 255, 0.92);
    -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 12c2.7 0 5-2.3 5-5s-2.3-5-5-5-5 2.3-5 5 2.3 5 5 5zm0 2c-3.3 0-10 1.7-10 5v2h20v-2c0-3.3-6.7-5-10-5z'/></svg>") center / contain no-repeat;
            mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 12c2.7 0 5-2.3 5-5s-2.3-5-5-5-5 2.3-5 5 2.3 5 5 5zm0 2c-3.3 0-10 1.7-10 5v2h20v-2c0-3.3-6.7-5-10-5z'/></svg>") center / contain no-repeat;
}

.dropdown-username {
    font-weight: 700;
    font-size: 15px;
    letter-spacing: 0.01em;
    /* Leave room for the avatar circle on the right. */
    padding-right: 52px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* "Balance" mini-label above the value so the pill reads as data, not just a number. */
.dropdown-user-info .dropdown-username + .dropdown-balance::before {
    content: attr(data-label);
    display: block;
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 2px;
}

.dropdown-balance {
    font-size: 18px;
    color: var(--accent-green);
    font-weight: 800;
    letter-spacing: 0.01em;
    line-height: 1;
}

/* Brief tint flash on the header balance pill whenever the value moves.
   Green = increase (win settled, slot withdraw, top-up), red = decrease
   (bet placed, slot deposit). 700ms total; JS strips the class on completion. */
#user-balance {
    transition: color 0.18s ease, background-color 0.18s ease, text-shadow 0.18s ease;
    /* Condensed display face: wide proportional digits truncated the balance
       on phones ("153,61…"); Futura PT Cond digits are ~25% narrower and the
       pill is bold anyway, so the full amount fits. Size bumped one notch
       because condensed reads smaller at equal px. */
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 10px;
    letter-spacing: 0.02em;
}
#user-balance.balance-flash-up {
    color: #5fe19a;
    text-shadow: 0 0 8px rgba(95, 225, 154, 0.6);
}
#user-balance.balance-flash-down {
    color: #ff7080;
    text-shadow: 0 0 8px rgba(255, 112, 128, 0.55);
}

.dropdown-divider {
    height: 1px;
    background: rgba(255, 255, 255, 0.05);
    margin: 4px 0;
}

/* Bigger, sportier menu items. Each row is 44px tall (iOS touch target),
   has an icon chip on the left, label in the middle, and a chevron on the
   right for "tap to navigate" affordance. Hover/tap shows a green left
   accent strip. */
.dropdown-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    font-size: 14px;
    font-weight: 600;
    color: var( --text-cat);
    transition: background 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
    position: relative;
    /* Make sure the row clears the new padding even on tall content. */
    min-height: 44px;
}
.dropdown-item svg {
    flex-shrink: 0;
    width: 18px;
    height: 18px;
    /* Chip background behind the icon */
    padding: 4px;
    box-sizing: content-box;
    background: rgba(255, 255, 255, 0.05);
    border-radius: 0;
    color: var(--accent-green);
    transition: background 0.15s ease, color 0.15s ease;
}
/* Chevron at the right edge — pure CSS, no extra HTML. */
.dropdown-item span[data-i18n],
.dropdown-item > span {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.dropdown-item::after {
    content: '';
    flex-shrink: 0;
    width: 14px;
    height: 14px;
    background-color: currentColor;
    opacity: 0.4;
    -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>") center / contain no-repeat;
            mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='9 18 15 12 9 6'/></svg>") center / contain no-repeat;
    transition: transform 0.15s ease, opacity 0.15s ease;
}

.dropdown-item:hover,
.dropdown-item:active {
    background: rgba(58, 165, 110, 0.08);
    color: var(--text-primary);
    /* Green left accent bar slides in on hover/tap */
    box-shadow: inset 3px 0 0 var(--accent-green);
}
.dropdown-item:hover svg,
.dropdown-item:active svg {
    background: rgba(58, 165, 110, 0.18);
    color: var(--accent-green);
}
.dropdown-item:hover::after,
.dropdown-item:active::after {
    opacity: 0.9;
    transform: translateX(2px);
}

/* Sign Out — keep the danger color but apply the same chip + chevron treatment. */
.dropdown-item.logout-item {
    color: var(--accent-red);
}
.dropdown-item.logout-item svg {
    color: var(--accent-red);
}
.dropdown-item.logout-item:hover,
.dropdown-item.logout-item:active {
    background: rgba(237, 65, 99, 0.12);
    box-shadow: inset 3px 0 0 var(--accent-red);
}
.dropdown-item.logout-item:hover svg,
.dropdown-item.logout-item:active svg {
    background: rgba(237, 65, 99, 0.18);
    color: var(--accent-red);
}
/* Sign Out doesn't navigate inside the app — drop the chevron. */
.dropdown-item.logout-item::after {
    display: none;
}

/* Mobile: dock to the right edge of the screen with extra breathing room.
   Bottom safe-area inset keeps the last item out of the iOS home-bar zone. */
@media (max-width: 600px) {
    .user-dropdown {
        width: 92vw;
        max-width: 360px;
        right: -8px;   /* line up a touch closer to the viewport edge */
        padding-bottom: env(safe-area-inset-bottom, 0);
    }
    .dropdown-item {
        padding: 14px 16px;
        font-size: 15px;
        min-height: 48px;
    }
    .dropdown-user-info {
        padding: 20px 18px 18px;
    }
    .dropdown-username { font-size: 16px; }
    .dropdown-balance  { font-size: 20px; }
}


/* ==========================================
   MAIN LAYOUT
   ========================================== */
.main-layout {
    display: flex;
    margin-top: var(--header-height);
    min-height: calc(100vh - var(--header-height));
}

/* --- Sidebar --- */
.sidebar {
    width: var(--sidebar-width);
    flex-shrink: 0;
    /* Darker base so each section card stands out on top of it */
    /* background: var(--bg-input); */
    border-right: 1px solid var(--border-subtle, var(--bg-tertiary));
    padding: 12px 10px;
    overflow-y: auto;
    height: calc(100vh - var(--header-height));
    position: sticky;
    top: var(--header-height);
    /* Don't let `align-items: stretch` on .main-layout grow the sidebar
       to match the very-tall .content sibling — sticky needs the element
       to be shorter than its container to engage. Pairs with the same
       safeguard on .betslip-panel. */
    align-self: flex-start;
    -webkit-overflow-scrolling: touch;
    -webkit-overflow-scroll: touch;
    scrollbar-width: none;
    scrollbar-color: #241521 #8c2b9800;
    min-height: 0;
    overflow: hidden auto;
}

/* 1a sidebar order: what you were doing (Continue), then Sports, then Casino —
   done with flex `order` so the markup keeps its original, semantically fine
   sequence and nothing in the click wiring has to move. */
.sidebar {
    display: flex;
    flex-direction: column;
}
#sidebar-live-section     { order: 0; }   /* Live Overview leads the rail */
.sidebar-sort             { order: 1; }
#sidebar-frequent-section { order: 2; }
#sidebar-sports-section   { order: 3; }
#sidebar-casino-section   { order: 4; }
#sidebar-exchange-section { order: 5; }

/* Frequently Visited belongs to POPULAR, not to A-Z: A-Z is "every sport we
   offer, in order", while Popular is "what's hot and what you keep coming back
   to". `:not([hidden])` so this never overrides _renderFrequentlyVisited()
   hiding the section while it's empty. */
#sidebar-frequent-section { display: none; }
.sidebar.mode-popular #sidebar-frequent-section:not([hidden]) { display: block; }

/* A–Z / Popular segmented control. */
.sidebar-sort {
    display: flex;
    gap: 4px;
    padding: 3px;
    margin-bottom: 14px;
    background: var(--bg-primary);
    border: 1px solid var(--border-subtle, var(--bg-tertiary));
    border-radius: 0;
    flex-shrink: 0;
}

.sidebar-sort-btn {
    flex: 1;
    padding: 7px 0;
    background: none;
    border: none;
    border-radius: 0;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 11.5px;
    font-weight: 700;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}

.sidebar-sort-btn.active {
    background: var(--bg-tertiary);
    color: #fff;
}

/* Popular mode's two groups inside the sports rail. */
.sidebar-subheading {
    padding: 10px 8px 6px;
    font-size: 10px;
    line-height: 1;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.13em;
    color: var(--text-muted);
}
.sidebar-subheading:first-child {
    padding-top: 0;
}

.sidebar-league-flag {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    width: 17px;
}

/* UEFA competition mark, rendered into the same slot the country flag uses (see
   App._leagueCompLogo).

   BOUNDED BY DEFAULT — this matters. The hosts differ (the sidebar rail gives
   17px of width and NO height; the homepage card gives a 36x36 box), so
   percentage sizing is out: `max-height: 100%` against an auto-height parent
   resolves to none and the SVG renders at its natural size. The first version
   set explicit sizes per host and left the base rule with none — which meant any
   host not listed below fell back to natural size, and a ~250px starball filled
   the homepage league-group header. There are FOUR hosts, not the two that were
   obvious, and a fifth may appear. So the base carries a sane size and each host
   narrows it, rather than each host being obliged to remember. */
.league-comp-logo {
    width: 18px;
    height: 18px;
    object-fit: contain;
    display: block;
    flex-shrink: 0;
}
.sidebar-league-flag .league-comp-logo { width: 17px; height: 17px; }
.league-icon .league-comp-logo { width: 26px; height: 26px; }
/* Live league header: sits inline beside the star, at the header's own 13px
   text size, so 16px keeps it level with the league name rather than
   inflating the row. */
.live-league-header-left .league-comp-logo { width: 16px; height: 16px; }
/* Homepage league-group header — the title runs a little larger here, so 20px
   sits level with the uppercase league name without lifting the row height. */
.league-group-title .league-comp-logo { width: 20px; height: 20px; }

.sidebar-league-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Match count on a live league row — accent chip, per the mockup's "4" badge. */
.sidebar-count-badge {
    flex-shrink: 0;
    padding: 2px 5px;
    border-radius: 0;
    background: rgba(200, 239, 74, 0.12);
    color: var(--accent-green);
    font-size: 10px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* Sidebar worlds. The rail carries whichever product you are in: sports pages get
   leagues and the sport list, casino pages get game categories. Driven by
   `data-world` on #sidebar, set in App.updateProductToggle() from the SAME
   sports/casino test that lights the header toggle — one definition of "which
   world am I in", so the rail and the header can never disagree.
   `!important` on the hides: several of these sections also manage their own
   `hidden` attribute and inline display (Frequently Visited, Top Leagues), and a
   world switch has to win over a section that thinks it should be showing. */
.sidebar[data-world="casino"] .sidebar-sports-only,
.sidebar:not([data-world="casino"]) .sidebar-casino-only {
    display: none !important;
}

/* The casino block leads the rail in casino mode, so it loses the top margin that
   was separating it from the sort toggle above it (which is a sports control and
   is now hidden). */
.sidebar[data-world="casino"] #sidebar-casino-section {
    margin-top: 0;
}

/* The sidebar is a flex column whose sections are sequenced by explicit `order`
   (sort 1, frequent 2, sports 3, casino 4, exchange 5) — NOT by document order.
   Anything added without an order defaults to 0 and jumps to the top: that is why
   the categories block first rendered above both the quick-nav and the casino
   links it belongs under. New sections must claim a number.
   Quick-nav is pinned ahead of everything at -1 (it is the rail's masthead in both
   worlds); categories follow the casino links they filter. */
.sidebar-quicknav {
    order: -1;
}

#sidebar-top-leagues-section {
    order: 0;
}

#sidebar-slots-cats-section {
    order: 6;
}

/* Category rows are text-only — no flag, no icon — so they need the indent the
   icon would have provided, or they hang left of every other row in the rail.
   The button reset is NOT optional: .sidebar-item was only ever applied to <a>,
   so it never had to cancel a background or a border, and these rows came out
   wearing the browser's default grey button chrome. */
.sidebar-slots-cat {
    padding-left: 12px;
    width: 100%;
    background: none;
    border: none;
    text-align: left;
    font-family: inherit;
}

.sidebar-slots-cat .sidebar-count-badge {
    background: rgba(255, 255, 255, 0.07);
    color: var(--text-muted, #7c8798);
}

.sidebar-slots-cat.active {
    color: var(--text-primary, #fff);
    background: var(--bg-hover, rgba(255, 255, 255, 0.07));
}

/* Top-league rows stack country over league name, so the flag and the count sit
   beside a two-line block rather than a single line. */
.sidebar-top-league-text {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 1px;
    flex: 1;
    min-width: 0;   /* or the ellipsis on both lines never engages */
}

/* Eyebrow: quieter and smaller than the league it qualifies. Uppercased because
   at 10px a mixed-case country reads as a second title rather than a label. */
.sidebar-top-league-country {
    font-size: 10px;
    font-weight: 600;
    line-height: 1.15;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted, #7c8798);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* .sidebar-league-name carries `flex: 1` for the single-line rows it was written
   for. Inside this COLUMN that grows it along the block axis instead, which
   splits the two lines to opposite ends of the row. */
.sidebar-top-league .sidebar-league-name {
    flex: 0 0 auto;
    line-height: 1.2;
}

/* Top-league rows borrow the live-league layout but NOT its accent badge. The
   green chip means "matches in play"; on these rows the number is upcoming
   fixtures, so wearing the live colour would claim a state the row does not have.
   Neutral chip, same geometry. */
.sidebar-top-league .sidebar-count-badge {
    background: rgba(255, 255, 255, 0.07);
    color: var(--text-muted, #7c8798);
}

/* Corner bands: two colours cut diagonally into the top-left and bottom-right
   corners — the scoreboard-card look. Worn by the sidebar's top leagues and
   Frequently Visited, the home page's league cards, and the Browse page's
   Frequently Visited rows.
   --band-a / --band-b are "r,g,b" triplets (CountryFlags.bands for a league's
   flag, App._COMP_BANDS for a UEFA mark, App._SPORT_BANDS for a sport's icon)
   so each colour can be drawn as a wedge and again as the stripe beside it.
   --band-solid / --band-stripe set how strongly, and any ancestor can override
   them. The defaults are toned down on purpose: at full strength (1 / .35) the
   wedges read as stickers on the dark UI, and much below this they go muddy.
   Stops are px, not %: a percentage is measured along the gradient line, which
   grows with the element, so a wider card would push the wedges in under its
   content. It is a ::before rather than a background layer because these
   hosts' :hover rules use the `background` shorthand, which would wipe it. */
.corner-bands {
    position: relative;
    isolation: isolate;     /* ::before sits under the content with no z-index on each child */
}
.corner-bands::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    border-radius: inherit; /* follows the host's corners, so the host needs no overflow: hidden */
    pointer-events: none;
    background-image: linear-gradient(120deg,
        rgba(var(--band-a), var(--band-solid, 0.6)) 0 22px,
        rgba(var(--band-a), var(--band-stripe, 0.2)) 22.5px 31px,
        transparent 31.5px calc(100% - 31.5px),
        rgba(var(--band-b), var(--band-stripe, 0.2)) calc(100% - 31px) calc(100% - 22.5px),
        rgba(var(--band-b), var(--band-solid, 0.6)) calc(100% - 22px) 100%);
}

/* A small flag or icon on a wedge of its own colour disappears into it —
   Italy's green, Albania's red on red, a basketball on orange. A hairline in
   the rail's dark follows its outline: drop-shadow, not a border, because the
   image box is square and the flag isn't. The league cards need none: their
   flag sits in a tile of its own. */
.sidebar-top-league.corner-bands .sidebar-league-flag img,
.sidebar-freq-item.corner-bands .sidebar-freq-ico,
.browse-sport-item.corner-bands .browse-sport-left img {
    filter: drop-shadow(0 0 0.6px var(--bg-input)) drop-shadow(0 0 0.6px var(--bg-input)) drop-shadow(0 0 0.6px var(--bg-input));
}

/* The count sits over the right-hand stripe; an opaque chip in the rail's row
   colour keeps it legible whatever colour is underneath. */
.sidebar-top-league.corner-bands .sidebar-count-badge {
    background: var(--bg-input);
}

/* Frequently Visited rows are bare text on the rail; wedges on them float with
   no card around them. Give banded rows the top-league rows' ground, and end
   the name before the right-hand wedge — these rows have no count chip to
   cover it, so a long name's "…" landed on the colour. */
#sidebar-frequent-list .sidebar-freq-item.corner-bands {
    background: rgba(var(--bg-deep-rgb), 0.64);
    padding-right: 26px;
}

/* The sport NAME takes the slack, so everything after it lands in a fixed
   column. Without this the name is content-width and the free space is split
   between the two `margin-left: auto` siblings (this count and the submenu
   caret), which made the count drift with the length of the sport's name —
   "10 live" and "5 live" started 14px apart. */
.sidebar-item > span:not([class]) {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Live match count beside a sport — red, the same signal the rest of the app
   uses for in-play. Fixed-width, right-aligned column so the numbers stack
   regardless of name length or whether the row has a caret. Empty (and so
   invisible) when the sport has none. */
/* Live count — a scoreboard figure (waves glyph + boxed number), not the old
   loose "18 live" text pinned to a 46px right-aligned slot. Built by
   App._updateSidebarLiveCounts. */
.sidebar-live-count {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex-shrink: 0;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.sb-live-num {
    min-width: 22px;
    padding: 2px 5px;
    border-radius: 0;
    text-align: center;
    background: color-mix(in srgb, var(--accent-red, #ed4163) 20%, transparent);
    border: 1px solid color-mix(in srgb, var(--accent-red, #ed4163) 38%, transparent);
    color: #ffe3e8;
    font-size: 11px;
    font-weight: 800;
    line-height: 1.25;
}

/* STATIC on-air glyph. `.live-waves` animates five paths on a 1s loop; one
   badge per sport is ~30 looping elements in a rail that is on screen for the
   whole session, all signalling the same thing and all competing with a board
   whose odds already flash. The live-now header carries the same judgement — it
   dropped its waves because TWO loops for one signal were already too many.
   Holding the arcs at their end state also fixes a legibility problem: with the
   animation running, `fill-mode: both` keeps each arc invisible until its delay
   elapses, so at any given instant the badge often looks like a bare dot.
   The single ANIMATED instance stays on Live Overview, where it earns the
   attention. Delete this block to animate them everywhere. */
.sb-live-waves {
    color: var(--accent-red, #ed4163);
    flex: none;
}

.sb-live-waves svg {
    width: 17px;
    height: 13px;
}

/* DOUBLE class on the same element — `.sb-live-waves.live-waves` — is load
   bearing. The keyframes are attached by `.live-waves .prp-c` further down this
   file; a single-class override here ties at (0,2,0) and loses on source order,
   leaving the animation running. */
.sb-live-waves.live-waves .prp-c,
.sb-live-waves.live-waves .prp-1d,
.sb-live-waves.live-waves .prp-45,
.sb-live-waves.live-waves .prp-0d,
.sb-live-waves.live-waves .prp-d6 {
    animation: none;
    opacity: 1;
}

.sidebar-live-count:empty {
    display: none;
}

/* 1a "same structure, quieter". Every group used to be its own card — filled
   background, rounded, with a solid header BAR on --bg-tertiary. Stacked four
   deep that read as four competing panels rather than one navigation list. Now
   the groups are separated by a hairline and the heading is just a label. */
.sidebar-section {
    margin-bottom: 14px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--border-subtle, var(--bg-tertiary));
}

.sidebar-section:last-child {
    border-bottom: none;
    margin-bottom: 0;
}

.sidebar-heading {
    padding: 0 8px 8px;
    font-size: 10px;
    line-height: 1;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.13em;
    color: var(--text-muted);
    background: none;
}

.sidebar-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px;
    font-size: 14px;
    color: var(--text-secondary);
    transition: background 0.15s, color 0.15s;
    cursor: pointer;
    font-weight: 600;
    border-radius: 0;
    margin: 8px 0 2px;
}



#sidebar-top-leagues .sidebar-item {
  background: rgba(var(--bg-deep-rgb), 0.64);
  margin: 4px 0 2px;
  height: 45px;
}

/* The lit row's ground. These rows set their own background under an id, which
   outranks .sidebar-item.active — a lit league only went bold. */
#sidebar-top-leagues .sidebar-item.active,
#sidebar-frequent-list .sidebar-item.active {
  background: var(--bg-secondary);
}

/* Frequently Visited — reuses .sidebar-item (flex row, 10px gap); only the sport icon
   needs sizing, matching the 18px SVGs used by the other sidebar entries. */
.sidebar-freq-ico {
    width: 18px;
    height: 18px;
    object-fit: contain;
    flex-shrink: 0;
}

/* League names can be long ("England - Premier League") — clip rather than wrap. */
.sidebar-freq-item span {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sidebar-item:hover {
    background: var(--bg-secondary);
    color: var(--text-primary);
}

.sidebar-item.active {
    background: var(--bg-secondary);
    color: var(--text-primary);
    font-weight: 700;
}

.sidebar-item svg,
.sidebar-item .sport-icon {
    flex-shrink: 0;
    width: 18px;
    text-align: center;
    font-size: 16px;
}

/* --- Expandable sport sub-categories (e.g. Football) --- */
/* The caret is the link's sibling and sits over the row's right end; the link
   keeps its room (8px + the 24px caret + the 10px gap it had inside the row),
   so the live count stays where it was. Centred with auto margins, not a
   transform, which would fight the rotate on open. */
.sidebar-item-row {
    position: relative;
}

.sidebar-item.has-submenu {
    padding-right: 42px;
}

.sidebar-item-row > .sidebar-submenu-toggle {
    position: absolute;
    right: 8px;
    top: 0;
    bottom: 0;
    height: 24px;
    margin: auto 0;
    border: 0;
}

.sidebar-submenu-toggle:focus-visible {
    outline: 2px solid var(--accent-green);
    outline-offset: 1px;
}

.sidebar-submenu-toggle {
    margin-left: auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 4px;
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    background: none;
    cursor: pointer;
    transition: transform 0.2s ease, color 0.15s, background 0.15s;
}

.sidebar-submenu-toggle svg {
    width: 16px;
    height: 16px;
}

.sidebar-submenu-toggle:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
}

.sidebar-item-group.open .sidebar-submenu-toggle {
    transform: rotate(180deg);
}

.sidebar-submenu {
    display: none;
    flex-direction: column;
}

.sidebar-item-group.open .sidebar-submenu {
    display: flex;
}

.sidebar-subitem {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 5px 18px 5px 46px;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-secondary);
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
    margin: 5px;
}

/* ---- Sidebar submenu: the sport's filters as small cards ---------------------
   The same card as the sport rows, smaller and indented under its sport, with
   each filter's icon at the right-hand end. The indent and the cards carry the
   nesting, so the old guide rail and ticks are gone; the current filter is a
   green tint and outline.
   Everything below is scoped to `.sidebar` ON PURPOSE: _sidebarSubitemsHtml is
   shared with #sport-subnav, the same items as a horizontal pill row on the
   sport page, which keeps its own chrome. */
.sidebar .sidebar-submenu {
    padding: 2px 0 4px 14px;
}

.sidebar .sidebar-subitem {
    margin: 0 0 3px;
    padding: 7px 10px;
    border-radius: 0;
    gap: 9px;
    background: rgba(var(--bg-deep-rgb), 0.64);
}

.sidebar .sidebar-subitem svg {
    width: 15px;
    height: 15px;
    flex: none;
    order: 2;
    margin-left: auto;
}

.sidebar .sidebar-subitem:hover {
    background: var(--bg-secondary);
    color: #fff;
}

.sidebar .sidebar-subitem.active {
    background: color-mix(in srgb, var(--accent-green) 12%, var(--bg-input));
    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent-green) 45%, transparent);
    color: #fff;
}

.sidebar-subitem svg {
    flex-shrink: 0;
    width: 15px;
    height: 15px;
}

.sidebar-subitem:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
    border-radius: var(--radius-md);
}

.sidebar-subitem.active {
    color: var(--accent-green);
}

.sidebar-badge {
    margin-left: auto;
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    background: var(--bg-primary);
    padding: 1px 6px;
    border-radius: 0;
}

/* ==========================================
   CONTENT AREA
   ========================================== */
.content {
    flex: 1;
    min-width: 0;
    padding: 8px;
    /* No overflow-y here — keeping it removed so the window is the scroll container,
       which lets `position: sticky` on descendants (e.g. .content-tabs) engage. */
    max-width: 1200px;
    margin: 0 auto;
}

.page {
    display: none;
}

.page.active {
    display: block;
    min-height: 800px;
}

/* --- Content Tabs --- */
.content-tabs {
    display: flex;
    gap: 4px;
    margin-bottom: 20px;
    background: var(--bg-input);
    padding: 4px;
    border: 1px solid var(--bg-lightg);
    border-radius: var(--radius-lg25);
    overflow-x: auto;
    overflow-y: hidden;
    /* Smooth touch scrolling on iOS Safari */
    -webkit-overflow-scrolling: touch;
    /* Tabs may overflow horizontally on narrow screens / long locales (Albanian
       "Fillon Së Shpejti", Greek labels). Allow scroll but hide the scrollbar UI. */
    scrollbar-width: none;
    height: 55px;
    /* Pinned below the fixed header so the tabs stay reachable while scrolling.
       `top` is derived from --header-height rather than a literal, so it tracks
       --header-bar (60px -> 70px, 2026-08-22) and the iOS safe-area inset on its
       own — a hardcoded offset here is how the strip ends up overlapping or
       floating below the bar the next time the header's height changes.
       App.loadSuperTopLeagues' league-card scroll subtracts this element's height
       from its target as well; that assumes the strip is pinned, so the two must
       stay in step. */
    position: sticky;
    top: calc(var(--header-height) + 0px);
    z-index: 50;
    box-shadow: 0 6px 14px -8px rgba(0, 0, 0, 0.55);
}
.content-tabs::-webkit-scrollbar { display: none; }
/* Make sure each tab keeps its natural width even when the container is too narrow */
.content-tabs > .tab-btn { flex: 0 0 auto; }

/* On phones the four labels can take ~360 px (Albanian) and don't fit at 360 px viewport.
   Tighten padding + font so the common case fits without scrolling. */
@media (max-width: 600px) {
    .content-tabs { padding: 3px; gap: 2px; height: 55px; }
    .content-tabs > .tab-btn {
        padding: 6px 12px;
        font-size: 14px;
    }
}

/* Empty-state placeholder for filtered league-matches-grouped */
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 48px 20px;
    margin: 12px 0;
    background: var(--bg-secondary);
    border: 1px dashed var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-muted);
    text-align: center;
    font-size: 14px;
}

.empty-state svg {
    color: var(--accent-odds);
    opacity: 0.7;
}

.empty-state p {
    margin: 0;
    max-width: 320px;
    line-height: 1.5;
}

.empty-state-cta {
    display: inline-flex;
    align-items: center;
    padding: 10px 20px;
    background: var(--accent-green-grad);
    color: var(--bg-deep);
    border-radius: var(--radius-md);
    font-size: 14px;
    font-weight: 700;
    text-decoration: none;
    transition: opacity 0.15s;
}

.empty-state-cta:hover { opacity: 0.9; }

.tab-btn {
    padding: 8px 18px;
    background: transparent;
    color: var(--text-primary);
    font-size: 13px;
    font-weight: 600;
    border-radius: var(--radius-lg25);
    transition: all 0.15s;
    white-space: nowrap;
    display: flex;
    align-items: center;
    gap: 6px;
}

.tab-btn:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
}

.tab-btn.active {
    color: var(--text-primary);
    background: var(--bg-tertiary);
}

.live-dot {
    width: 6px;
    height: 6px;
    background: var(--accent-red);
    border-radius: 50%;
    animation: pulse 1.5s ease-in-out infinite;
}

@keyframes pulse {

    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0.4;
    }
}

/* --- Promo Carousel --- */
/* ============================================================================
   1a "ONE hero" — featured live match + demoted promo rail.
   Replaces the full-width promo carousel that used to open the landing page.
   The `.promo-carousel*` / `.promo-slide*` rules below are kept because the
   markup is gone from index.html but the classes are still referenced by the
   login-page promo strip; nothing renders the carousel itself any more.
   ========================================================================== */
.home-hero-grid {
    display: grid;
    grid-template-columns: 1fr 300px;
    gap: 12px;
    margin-bottom: 24px;
    align-items: start;
}

.home-hero {
    position: relative;
    height: var(--hero-h, 250px);
    border-radius: var(--radius-lg, 12px);
    overflow: hidden;
    background: var(--bg-input, var(--bg-odds));
}

/* No live match to feature — collapse rather than show an empty 250px box.
   The rail then takes the full width on its own. */
.home-hero.is-empty {
    display: none;
}
.home-hero.is-empty ~ .home-promo-rail,
.home-hero-grid:has(.home-hero.is-empty) {
    grid-template-columns: 1fr;
}

.home-hero-slides {
    position: absolute;
    inset: 0;
}

/* Slides crossfade rather than slide: the score is the thing being read, and a
   horizontal translate makes big digits smear. */
.home-hero-slide {
    position: absolute;
    inset: 0;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.35s ease;
    cursor: pointer;
    background-position: center;
    background-size: cover;
    background-repeat: no-repeat;
}

.home-hero-slide.active {
    opacity: 1;
    pointer-events: auto;
}

@media (prefers-reduced-motion: reduce) {
    .home-hero-slide { transition: none; }
}

/* Per-sport artwork, same pack + same ordering rule as .match-detail-top:
   `[data-sport-id]` and `[data-sport-id="1"]` share specificity, so the generic
   fallback MUST stay first. */
.home-hero-slide[data-sport-id] {
    background-image: url('/img/banners/sports/sports-backgrounds-pack/headers/generic-sports-header.webp');
}
.home-hero-slide[data-sport-id="1"] {
    background-image: url('/img/banners/sports/sports-backgrounds-pack/headers/football-header.webp');
}
.home-hero-slide[data-sport-id="2"] {
    background-image: url('/img/banners/sports/sports-backgrounds-pack/headers/basketball-header.webp');
}
.home-hero-slide[data-sport-id="3"] {
    background-image: url('/img/banners/sports/sports-backgrounds-pack/headers/tennis-header.webp');
}
.home-hero-slide[data-sport-id="11"],
.home-hero-slide[data-sport-id="15"] {
    background-image: url('/img/banners/sports/sports-backgrounds-pack/headers/volleyball-header.webp');
}
.home-hero-slide[data-sport-id="12"] {
    background-image: url('/img/banners/sports/sports-backgrounds-pack/headers/table-tennis-header.webp');
}
.home-hero-slide[data-sport-id="18"] {
    background-image: url('/img/banners/sports/sports-backgrounds-pack/headers/cricket-header.webp');
}

/* The competition's banner beats the sport photo, same rule and same ordering
   trap as the match header: equal specificity, so this must stay below every
   per-sport rule above. Only the image changes — position, size and the scrim
   are the slide's own. */
.home-hero-slide[data-league-bg] {
    background-image: var(--league-art);
}

/* Left-weighted scrim so the text side stays legible over any artwork while the
   right side keeps enough image to read as a photo. */
.home-hero-slide::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, var(--bg-primary) 6%, rgba(var(--bg-primary-rgb), 0.86) 42%, rgba(var(--bg-primary-rgb), 0.15) 100%);
}

.hero-inner {
    position: relative;
    height: 100%;
    padding: 22px 24px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    /* The mockup used 60% because its sample names were "CELTIC" / "DUNDEE".
       Real ones are "Independiente Yumbo" / "Envigado FC", so the text column
       gets more of the slide and the artwork keeps the rest. */
    max-width: 72%;
    min-width: 0;
}

.hero-top {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.hero-live {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex-shrink: 0;
    padding: 4px 8px;
    border-radius: 0;
    background: var(--accent-red, #ed4163);
    color: #fff;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.1em;
}

.hero-live-dot {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: #fff;
    animation: hero-pulse 1.4s infinite;
}

@keyframes hero-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.35; }
}

@media (prefers-reduced-motion: reduce) {
    .hero-live-dot { animation: none; }
}

.hero-league {
    font-size: 11.5px;
    font-weight: 600;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.hero-minute {
    flex-shrink: 0;
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 700;
    color: #fff;
    font-variant-numeric: tabular-nums;
}

.hero-mid {
    min-width: 0;
}

/* Stacked scoreboard — see the note in _heroSlideHtml for why this isn't the
   mockup's single-line "TEAM 2 · 1 TEAM". */
.hero-teams {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 10px;
    min-width: 0;
}

.hero-team-row {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}

.hero-teams .hero-kit,
.hero-teams .hero-kit img {
    width: 28px;
    height: 28px;
    object-fit: contain;
    flex-shrink: 0;
}

/* Team names shrink before the scores do — the scoreline must never wrap.
   26px, not the mockup's 34px: at 34px a real name ("Independiente Yumbo")
   ellipsised to "INDEPE…" on a 662px hero. The score keeps display scale. */
.hero-team {
    font-family: var(--font-display);
    font-size: 26px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: 0.01em;
    color: #fff;
    text-transform: uppercase;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    flex: 1 1 auto;
}

/* Score sits hard right of its own line so the two stack into a column. */
.hero-score {
    margin-left: auto;
}

.hero-score {
    flex-shrink: 0;
    font-family: var(--font-display);
    font-size: 32px;
    font-weight: 700;
    line-height: 1;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    transition: color 0.2s;
}

/* The side that's ahead gets the accent — the scoreline's one piece of colour. */
.hero-score.lead {
    color: var(--accent-green);
}

.hero-momentum {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 11.5px;
    font-weight: 600;
    color: var(--text-muted);
}

.hero-mom-track {
    display: flex;
    width: 170px;
    height: 5px;
    border-radius: 3px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.08);
}

.hero-mom-fill {
    background: var(--accent-green);
    transition: width 0.6s ease;
}

@media (prefers-reduced-motion: reduce) {
    .hero-mom-fill { transition: none; }
}

.hero-mom-pct {
    color: #fff;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.hero-odds {
    display: flex;
    gap: 6px;
    min-width: 0;
}

.hero-odd {
    flex: 1 1 0;
    min-width: 0;
    height: 52px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    background: var(--bg-input, var(--bg-odds));
    border: 1px solid var(--border-color, var(--border-color));
    border-radius: 0;
    font-family: inherit;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
}

.hero-odd:hover {
    border-color: var(--accent-green);
}

.hero-odd.locked {
    cursor: default;
    opacity: 0.65;
}

.hero-odd.selected {
    border-color: var(--accent-green);
    background: rgba(200, 239, 74, 0.12);
}

.hero-odd-label {
    font-size: 9px;
    font-weight: 700;
    color: var(--text-muted);
    max-width: 100%;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.hero-odd-value {
    font-family: var(--font-display);
    font-size: 19px;
    font-weight: 700;
    color: var(--accent-odds);
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

.hero-all-markets {
    flex-shrink: 0;
    /* 96px per the design — it holds "+184", not the wordy "All markets"
       fallback, which only appears against an SP without the count. */
    width: 96px;
    height: 52px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid var(--border-color, var(--border-color));
    border-radius: 0;
    font-size: 11.5px;
    font-weight: 700;
    color: var(--text-secondary);
    text-decoration: none;
    text-align: center;
}

.hero-all-markets:hover {
    border-color: var(--accent-green);
}

/* Slide controls live in the TOP-RIGHT corner, not vertically centred on the
   left/right edges as in the mockup. The text column is left-weighted and full
   height, so edge-centred arrows sat straight on top of the team kits and the
   scoreline. The corner beyond `.hero-inner`'s 72% is the one reliably empty
   region of the slide. */
.home-hero-arrow {
    position: absolute;
    top: 10px;
    width: 30px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(var(--bg-primary-rgb), 0.72);
    border: 1px solid var(--border-color, var(--border-color));
    border-radius: 50%;
    color: var(--text-secondary);
    cursor: pointer;
    z-index: 3;
}

.home-hero-arrow:hover {
    color: #fff;
    border-color: var(--accent-green);
}

.home-hero-prev { right: 52px; }
.home-hero-next { right: 16px; }

/* One featured match → the arrows and dots are noise. */
.home-hero.is-single .home-hero-arrow,
.home-hero.is-single .home-hero-dots {
    display: none;
}

/* Dots sit under the arrows in the same clear corner, so nothing overlaps the
   odds row along the bottom of the text column. */
/* Each dot is a 24px target (WCAG 2.5.8) around the bar it draws. The bar was
   the whole button, 10×4px, and a tap 5px below it went through to the hero card
   and opened the match. The bar sits at the top of its box, where it always was
   (y 45), and the box reaches down past it rather than up into the arrows. */
.home-hero-dots {
    position: absolute;
    right: 16px;
    top: 42px;
    display: flex;
    z-index: 3;
}

.home-hero-dot {
    position: relative;
    width: 24px;
    height: 24px;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
    transition: width 0.2s;
}

.home-hero-dot::before {
    content: '';
    position: absolute;
    top: 3px;
    left: 50%;
    width: 10px;
    height: 4px;
    border-radius: 2px;
    background: rgba(255, 255, 255, 0.24);
    transform: translateX(-50%);
    transition: width 0.2s, background 0.2s;
}

.home-hero-dot.active {
    width: 34px;
}

.home-hero-dot.active::before {
    width: 26px;
    background: var(--accent-green);
}

.home-hero-dot:focus-visible {
    outline: 2px solid var(--accent-green);
    outline-offset: -2px;
    border-radius: 0;
}

/* ============================================================================
   1a "LIVE TANI" — the homepage live section as a BOARD, not a card carousel.
   Rows are rendered by Live._renderMatchRow (the live page's own renderer), so
   everything below is container chrome: the frame, the column header, and the
   market switcher that shows one odds group at a time.
   ========================================================================== */
/* Three groups, one row: title unit | market control (pushed right) | view-all.
   `gap` + `margin-left:auto` rather than space-between, so the control and the
   link stay together on the right instead of drifting to opposite edges. */
.live-now-header {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}

.live-now-header h3 {
    margin-right: auto;
}

/* The count belongs to the title, so it reads as "LIVE 29" — one object. A bare
   Futura number floating after the heading had no label and no relationship to
   anything; as a chip it's unmistakably a count of the thing just named. */
.live-now-count {
    display: inline-flex;
    align-items: center;
    min-width: 20px;
    justify-content: center;
    padding: 2px 6px;
    border-radius: 0;
    background: rgba(237, 65, 99, 0.14);
    color: var(--accent-red, #ed4163);
    font-size: 11px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0;
}

.live-now-count:empty {
    display: none;
}

/* Market switcher — same segmented-control language as the sidebar's A–Z /
   Popular pair, so the two controls read as the same kind of thing. */
.live-now-markets {
    display: flex;
    gap: 3px;
    padding: 10px;
    background: var(--bg-input, var(--bg-input));
    /* border: 1px solid var(--border-color, #2f4553); */
    border-radius: var(--radius-md);
    flex-shrink: 0;
}

/* The board-head copy of the market switcher is rendered on every width but
   only USED under 600px. Above that the head's right side is taken by the
   column labels (1/X/2, O/U, Tregje), and the section-header copy already sits
   inline with the title — so there is no separate row to reclaim. */
.lnb-head-markets {
    display: none;
}

.live-now-viewall {
    flex-shrink: 0;
}

.live-now-mkt-btn {
    padding: 6px 13px;
    background: none;
    border: none;
    border-radius: 0;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.15s, color 0.15s;
}

.live-now-mkt-btn.active {
    background: var(--bg-tertiary);
    color: #fff;
}

.live-now-markets[hidden] { display: none; }
/* O/U and Corners are icons: the ball and the statistics corner flag. Dimmed
   until chosen, like the text of the inactive "1 X 2". */
.live-now-mkt-ico-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
}
.live-now-mkt-ico {
    display: block;
    width: 20px;
    height: 20px;
    opacity: 0.7;
    transition: opacity 0.15s;
}
/* The corner flag fills less of its 22px canvas than the ball does. */
.live-now-mkt-btn[data-market="cou"] .live-now-mkt-ico { width: 24px; height: 24px; margin: -2px 0; }
.live-now-mkt-ico-btn:hover .live-now-mkt-ico,
.live-now-mkt-ico-btn.active .live-now-mkt-ico { opacity: 1; }
.live-now-mkt-btn:focus-visible { outline: 2px solid var(--accent-green-neon); outline-offset: 1px; }

.live-now-board {
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 0;
    overflow: hidden;
}

/* One head per SPORT block, repeated down the board — it names the sport AND
   re-states that block's odds columns, because tennis has no draw and the
   football header was lying about it. Kept to 26px so it separates without
   competing with the 60px rows. */
.live-now-board-head {
    display: flex;
    align-items: center;
    /* NO right padding — the head's column cells must end exactly where the
       rows' do, and rows have none. 12px here pushed every 1/X/2 label 12px off
       the buttons it labels (same trap as .live-league-header). */
    padding: 5px 0 5px 12px;
    /* background: var(--bg-input, #16252e); */
    border-top: 1px solid var(--border-subtle, var(--border-subtle));
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
    height: 35px;
}

.live-now-board-head:first-child {
    border-top: none;
}

.lnb-head-match {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 7px;
}

/* .lnb-sport-icon removed — the live board's per-sport head no longer carries a
   sport glyph, only the name and the count. Rule deleted with it so the class does
   not linger as dead CSS waiting to be re-attached by accident. */

.lnb-sport-name {
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.lnb-sport-count {
    flex-shrink: 0;
    padding: 1px 5px;
    border-radius: 0;
    background: rgba(255, 255, 255, 0.07);
    color: var(--text-muted);
    letter-spacing: 0;
    font-variant-numeric: tabular-nums;
}

/* Holds the kit column open for sports with no kit art (tennis) so every row's
   name starts at the same x. */
.team-kit-placeholder {
    display: inline-block;
    flex-shrink: 0;
}

/* Match the real kit <img> exactly (.live-match-team img), or the reserved slot
   is a few px off and the names still don't line up across sports. */
.live-match-team .team-kit-placeholder {
    width: 17px;
    height: 17px;
}

.live-now-board .live-match-row:last-child {
    border-bottom: none;
}

/* One odds group visible at a time. The row always renders all three, so the
   switcher is pure CSS — no re-render, no refetch, and the betslip bindings on
   the hidden buttons stay intact. */
.live-now-board.mkt-1x2 .live-match-ou,
.live-now-board.mkt-1x2 .live-match-cou,
.live-now-board.mkt-1x2 .live-league-ou-header,
.live-now-board.mkt-1x2 .live-league-cou-header,
.live-now-board.mkt-ou .live-match-odds,
.live-now-board.mkt-ou .live-match-cou,
.live-now-board.mkt-ou .live-league-odds-header,
.live-now-board.mkt-ou .live-league-cou-header,
.live-now-board.mkt-cou .live-match-odds,
.live-now-board.mkt-cou .live-match-ou,
.live-now-board.mkt-cou .live-league-odds-header,
.live-now-board.mkt-cou .live-league-ou-header {
    display: none;
}

/* ...and SHOW the selected one, at every width.
   This has to live at base level, not inside a media query. Two responsive rules
   hide these groups for the LIVE PAGE — `.live-match-cou` (with the market count)
   below 1100px, and `.live-match-ou, .live-match-cou` below 600px — and both
   match on the home board too. The counter-rule used to sit inside the 600px
   block, so it only rescued the switcher on phones: between 601px and 1100px the
   1100px rule hid corners and nothing brought them back, so picking "Këndore"
   rendered a board with no odds at all. Above 1100px neither hide applies, which
   is why it looked fine on a wide desktop and broken on a narrow window.
   At (0,3,0) this outranks both single-class hides wherever they apply, so one
   base rule covers every width.

   ROW CELLS ONLY — deliberately NOT the league-header cells. The home board's
   head hides every column label on purpose (see the .live-now-board-head rule:
   "only its column labels go; the sport name and count stay"). Adding
   .live-league-ou-header here force-showed an "O/U" label in that head, and
   since the head is space-between it squeezed "FUTBOLL 10" out entirely. */
.live-now-board.mkt-ou  .live-match-ou,
.live-now-board.mkt-cou .live-match-cou {
    display: flex;
}

/* A sport without O/U columns (tennis, basketball…) keeps its own prices in
   every mode: O/U and Corners only switch the football rows. Before, picking
   them folded tennis's 1 / 2 away and left a dash and two padlocks. The row
   and head carry the flag (Live._renderMatchRow, App._liveNowSportHeadHtml). */
.live-now-board.mkt-ou  .live-match-row--no-ou .live-match-odds,
.live-now-board.mkt-cou .live-match-row--no-ou .live-match-odds {
    display: flex;
}
.live-now-board.mkt-ou  .live-match-row--no-ou .live-match-ou,
.live-now-board.mkt-cou .live-match-row--no-ou .live-match-cou {
    display: none;
}
/* Its 1 / 2 labels too — above 600px only, where the head shows labels at all. */
@media (min-width: 601px) {
    .live-now-board.mkt-ou  .lnb-no-ou .live-league-odds-header,
    .live-now-board.mkt-cou .lnb-no-ou .live-league-odds-header {
        display: flex;
    }
}

/* The wrapped-row mobile treatment belongs to the live PAGE only — on the home
   board the hidden groups are already gone, so the visible one stays inline. */
@media (max-width: 600px) {
    /* Two tiers instead of one crushed row: title + view-all on the first line,
       the market control full-width on the second. All three previously shared a
       375px row (338px of content) and only "fitted" because the control scrolled
       internally — i.e. a control was half-hidden by default. */
    .live-now-header h3 {
        margin-right: 0;
    }
    .live-now-viewall {
        margin-left: auto;
    }
    /* The switcher moves INTO the board head here. In the section header it had
       to wrap onto a row of its own (title + View All already filled the line),
       costing 58px above a board head that was 35px of "Futboll 9" and 310px of
       nothing. Merging the two reclaims ~43px without shrinking the control. */
    #live-now-markets {
        display: none;
    }
    .lnb-head-markets {
        display: flex;
        margin-left: auto;      /* right edge, opposite the sport name */
    }
    /* `flex: 1` on the name block claimed the whole row, leaving the switcher
       12px. It only ever needed to be a floor for min-width:0 ellipsising. */
    .live-now-board-head .lnb-head-match {
        flex: 0 1 auto;
    }
    /* The head is a 35px label strip; it now carries a real control, so let it
       size to it rather than squashing the buttons. */
    .live-now-board-head:has(.lnb-head-markets) {
        min-height: 52px;
        padding-top: 4px;
        padding-bottom: 4px;
    }
    .live-now-mkt-btn {
        padding: 5px 10px;
        /* Matches --odd-h, the 44px tap floor this board already uses for prices;
           at desktop's 27px these were fine for a mouse but not for a thumb.
           Kept when moving into the head — the head grows instead. */
        /* min-height: var(--odd-h, 44px); */
        font-size: 14px;
    }
    /* The re-show rule that used to live here has moved to base level, next to
       the mkt-* hide block. Scoping it to this media query meant it only rescued
       the switcher below 600px, while the 1100px rule kept hiding corners in the
       601-1100 band — "Këndore" rendered an empty board on any narrow desktop or
       tablet window. */

    .live-now-board .live-match-ou,
    .live-now-board .live-match-cou {
        padding: 4px 4px 4px 0;
    }
    /* Kept on mobile. This rule used to hide it, from when the head was ONE column
       header for the whole board — but it's the per-sport separator now, and
       hiding it left football and tennis running together with no break, which is
       the one thing the separator exists to prevent. Only its column labels go;
       the sport name and count stay. */
    .live-now-board-head .live-league-odds-header,
    .live-now-board-head .live-league-mkt-header,
    .live-now-board-head .live-league-actions-header {
        display: none;
    }
}

/* --- Promo rail: the old carousel's banners, stacked and quieter ---
   Fixed to the hero's height and scrolled, rather than showing three and hiding
   the rest behind a toggle: the rail stays pinned to the hero's footprint no
   matter how many banners the JSON carries, and all of them stay reachable. */
.home-promo-rail {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
    height: var(--hero-h, 250px);
    overflow-y: auto;
    scrollbar-width: none;
    /* Both axes — a bare pan-y here would fight the page on touch. */
    touch-action: pan-x pan-y;
}

.home-promo-rail::-webkit-scrollbar {
    display: none;
}

/* Cards must not squash to fit the fixed height — they scroll instead. */
.home-promo-rail .promo-rail-card {
    flex: 0 0 78px;
}

.promo-rail-card {
    position: relative;
    height: 78px;
    border-radius: 0;
    overflow: hidden;
    background: var(--bg-input, var(--bg-odds));
    display: flex;
    align-items: center;
    padding: 0 14px;
    cursor: pointer;
}

.promo-rail-bg {
    position: absolute;
    inset: 0;
    background-position: right center;
    background-size: cover;
    background-repeat: no-repeat;
}

/* Scrim from the text side so the title stays readable over any banner. */
.promo-rail-bg::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg, var(--bg-odds) 20%, rgba(var(--bg-secondary-rgb), 0.55) 100%);
}

.promo-rail-text {
    position: relative;
    min-width: 0;
}

.promo-rail-badge {
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.11em;
    color: var(--accent-odds);
    margin-bottom: 3px;
}

.promo-rail-title {
    font-size: 13.5px;
    font-weight: 700;
    line-height: 1.2;
    color: #fff;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Tablet and below: the 300px rail can't hold its width next to a hero that
   still needs room for the scoreline — stack them, and drop the fixed height so
   the rail lays out as a horizontal strip instead. */
@media (max-width: 1024px) {
    .home-hero-grid {
        grid-template-columns: 1fr;
    }
    .home-promo-rail {
        flex-direction: row;
        height: auto;
        overflow-x: auto;
        overflow-y: hidden;
    }
    .home-promo-rail .promo-rail-card {
        flex: 0 0 240px;
    }
}

@media (max-width: 600px) {
    .home-hero {
        --hero-h: 220px;
    }
    .hero-inner {
        max-width: 100%;
        padding: 14px 14px 12px;
    }
    /* Names step down again on a phone; the score keeps display scale so the
       scoreboard still reads as the hero's subject. */
    .hero-team {
        font-size: 19px;
    }
    .hero-score {
        font-size: 24px;
    }
    .hero-teams {
        gap: 3px;
    }
    .hero-team-row {
        gap: 8px;
    }
    .hero-teams .hero-kit,
    .hero-teams .hero-kit img {
        width: 24px;
        height: 24px;
    }
    .hero-mom-track {
        width: 92px;
    }
    .hero-all-markets {
        width: 62px;
        font-size: 13px;
    }
    .hero-all-markets svg { display: none; }
    .home-hero-arrow { display: none; }
}

.promo-carousel-wrapper {
    margin-bottom: 20px;
    position: relative;
}

.promo-carousel {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 4px;
}

.promo-carousel::-webkit-scrollbar {
    display: none;
}

.promo-slide {
    flex: 0 0 340px;
    min-width: 340px;
    scroll-snap-align: start;
    border-radius: var(--radius-lg);
    overflow: hidden;
    position: relative;
    cursor: pointer;
    border: 2px solid transparent;
    transition: border-color 0.2s;
}

.promo-slide:hover {
    border-color: var(--accent-green);
}

.promo-slide-bg {
    width: 100%;
    height: 150px;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding: 16px;
    position: relative;
    background-size: cover;
    background-position: 100% 0;
}

.promo-slide-bg::before {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(0deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.2) 50%, transparent 100%);
}

.promo-slide-content {
    position: relative;
    z-index: 1;
}

.promo-badge {
    display: inline-block;
    padding: 3px 10px;
    background: var(--accent-green-grad);
    color: var(--bg-deep);
    font-size: 10px;
    font-weight: 800;
    border-radius: var(--radius-sm);
    letter-spacing: 0.05em;
    margin-bottom: 8px;
}

.promo-badge.red {
    background: var(--accent-red);
    color: #fff;
}

.promo-badge.blue {
    background: var(--accent-blue);
    color: #fff;
}

.promo-badge.orange {
    background: var(--accent-orange);
    color: var(--bg-deep);
}

.promo-slide-title {
    font-size: 18px;
    font-weight: 700;
    color: #fff;
    margin-bottom: 4px;
    line-height: 1.2;
}

.promo-slide-subtitle {
    font-size: 12px;
    color: rgba(255, 255, 255, 0.7);
    line-height: 1.3;
}

.promo-dots {
    display: flex;
    justify-content: center;
    gap: 6px;
    margin-top: 12px;
}

.promo-dot {
    width: 8px;
    height: 3px;
    border-radius: 2px;
    background: var(--border-color);
    transition: all 0.2s;
    cursor: pointer;
}

.promo-dot.active {
    width: 20px;
    background: var(--accent-green-grad);
}

/* Carousel Arrows — desktop only, fade on hover */
.carousel-arrow {
    position: absolute;
    top: 50%;
    transform: translateY(calc(-50% - 12px));
    z-index: 5;
    width: 36px;
    height: 36px;
    display: none;
    /* hidden on mobile */
    align-items: center;
    justify-content: center;
    background: rgba(var(--bg-deep-rgb), 0.9);
    border: 1px solid var(--border-color);
    border-radius: 50%;
    color: var(--text-secondary);
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.25s, background 0.15s, border-color 0.15s, color 0.15s;
    /* `-webkit-backdrop-filter` first for Safari 9–17.x; standard property second. */
    -webkit-backdrop-filter: blur(4px);
    backdrop-filter: blur(4px);
}

.carousel-arrow:hover {
    background: var(--bg-tertiary);
    color: var(--text-primary);
    border-color: var(--accent-green);
}

.carousel-arrow-left {
    left: 8px;
}

.carousel-arrow-right {
    right: 8px;
}

/* Show arrows only on desktop, fade in on hover */
@media (min-width: 901px) {
    .carousel-arrow {
        display: flex;
    }

    .promo-carousel-wrapper:hover .carousel-arrow {
        opacity: 1;
    }
}

/* --- Section Blocks --- */
.section-block {
    margin-bottom: 20px;
}

.section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 20px;
}

.section-header h3 {
    font-size: 20px;
    font-weight: 700;
    display: flex;
    align-items: center;
    gap: 8px;
}

/* Section headings reuse the app's OWN artwork rather than generic line icons:
   the football from the sport set (/img/icons/1.svg, same file the sport tabs
   and every icon fallback use) and the slot-machine glyph from the bottom nav.
   They are <img>, so unlike the inline SVGs they replaced they do NOT inherit
   the heading's colour — the football is a full-colour illustration and the
   casino glyph is drawn in white, which is what we want against the dark
   header. Sized up from the old 18px because these carry more detail than a
   2px-stroke outline and sit beside a 20px heading — keep the box square, the
   img letterboxes into it via object-fit. */
.section-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 25px;
    height: 25px;
    color: var(--text-primary);
    flex-shrink: 0;
}

.section-icon svg,
.section-icon img {
    width: 100%;
    height: 100%;
    display: block;
    object-fit: contain;
}

/* "On air" broadcast waves — timing matches the bet365 reference CSS the
   user extracted: 1s ease-in-out cycle, dot leads (0.1s), inner arcs follow
   (0.45s), outer arcs last (0.8s). fill-mode:both holds each shape at its
   0% keyframe (invisible) until its delay elapses, so on first paint the
   signal visibly builds outward from the dot. currentColor = the tint knob. */
.live-waves {
    display: inline-flex;
    align-items: center;
    color: var(--accent-green);
}
.live-waves svg {
    display: block;
    width: 18px;
    height: 18px;
}
.live-waves .prp-c,
.live-waves .prp-1d {
    animation: live-waves-arc 1s ease-in-out infinite;
    animation-delay: 0.8s;
    animation-fill-mode: both;
}
.live-waves .prp-45,
.live-waves .prp-0d {
    animation: live-waves-arc 1s ease-in-out infinite;
    animation-delay: 0.45s;
    animation-fill-mode: both;
}
.live-waves .prp-d6 {
    animation: live-waves-dot 1s ease-in-out infinite;
    animation-delay: 0.1s;
    animation-fill-mode: both;
}
@keyframes live-waves-arc {
    0%   { opacity: 0; }
    50%  { opacity: 1; }
    100% { opacity: 0; }
}
@keyframes live-waves-dot {
    0%   { opacity: 0.35; }
    50%  { opacity: 1; }
    100% { opacity: 0.35; }
}

.view-all {
    font-size: 13px;
    color: #ffffff;
    font-weight: 700;
    transition: color 0.2s;
    padding: 0px 25px;
}

.view-all:hover {
    color: var(--accent-teal-light);
}

/* --- Match Cards (always horizontal scroll) --- */
.matches-scroll {
    display: flex;
    gap: 12px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 4px;
}

.matches-scroll::-webkit-scrollbar {
    display: none;
}

/* Global touch-action rule for the app's horizontal scroller patterns.
   MUST be `pan-x pan-y`, NOT bare `pan-x`: `pan-x` alone means touches that
   START on the element may ONLY pan horizontally — a vertical swipe landing
   on a carousel would be swallowed and the page wouldn't scroll at all
   (user had to aim between the carousels to scroll the page). `pan-x pan-y`
   lets the element scroll horizontally itself while vertical pans fall
   through to the document scroll. The page-level sideways-drift problem is
   handled separately by body's `overflow-x: hidden` +
   `overscroll-behavior-x: none`, so loosening this is safe. */
.matches-scroll,
.content-tabs,
.lmst-tabs,
.mybets-scroller,
.mybets-date-presets,
.slots-categories,
.search-sport-tabs,
.sport-countries-scroll,
.ss-strip,
.ff-row,
.ovm-ClassificationBar_Scroller {
    touch-action: pan-x pan-y;
    overscroll-behavior-x: contain;
}

/* Home page "Top Slots / Your Favorites" promo strip. Each card is a compact
   variant of the slots-page grid card: smaller square thumb, heart in the
   corner, name below. Cards snap to the scroll grid so the arrow buttons
   land on whole-card boundaries. */
.slot-card-promo {
    flex: 0 0 140px;
    scroll-snap-align: start;
    /* Override the grid-card hover translate so the row stays steady. */
    transform: none;
}
.slot-card-promo:hover {
    transform: translateY(-2px);
}
.slot-card-promo .slot-card-thumb-wrap {
    /* Portrait, matching the grid tile and the 3:4 provider art. */
    aspect-ratio: 3 / 4;
}
.slot-card-promo .slot-card-meta {
    padding: 6px 8px;
}
.slot-card-promo .slot-card-name {
    font-size: 11px;
}
.slot-card-promo .slot-card-heart {
    width: 24px;
    height: 24px;
    top: 4px;
    right: 4px;
}
.slot-card-promo .slot-card-provider {
    /* Provider chip would crowd the small thumb — hide on the promo variant.
       The full slots page still shows it. */
    display: none;
}
.slot-card-promo .slot-card-overlay {
    /* Skip the big "Play" hover overlay on small cards; clicking anywhere
       launches. Keeps the row uncluttered. */
    display: none;
}
@media (max-width: 600px) {
    .slot-card-promo {
        flex-basis: 130px;
    }
}

/* ===== Live Now homepage cards ===== */
/* Sport artwork behind the homepage live cards.
 *
 * The per-sport rules set ONLY a custom property; the base and :hover rules
 * below compose the actual layers from it. Doing it this way avoids a
 * specificity fight — `.live-now-card:hover` and `.live-now-card[data-sport-id]`
 * both score (0,2,0), so a per-sport `background` shorthand would be wiped by
 * the hover rule (defined later) and the artwork would vanish on hover.
 * Variables cascade independently of that, so both states keep the image.
 *
 * Ids are the DOMAIN sport ids from the `sports` table — 1 Futboll,
 * 2 Basketboll, 3 Tenis, 11 Voleyball, 12 Ping Pong, 15 Beach Volleyball,
 * 18 Cricket. Anything else falls through to the generic artwork. */
.live-now-card[data-sport-id],
.match-card[data-sport-id]       { --sport-card-bg: url('/img/banners/sports/sports-backgrounds-pack/cards/generic-sports-card.webp'); }
.live-now-card[data-sport-id="1"],
.match-card[data-sport-id="1"]   { --sport-card-bg: url('/img/banners/sports/sports-backgrounds-pack/cards/football-card.webp'); }
.live-now-card[data-sport-id="2"],
.match-card[data-sport-id="2"]   { --sport-card-bg: url('/img/banners/sports/sports-backgrounds-pack/cards/basketball-card.webp'); }
.live-now-card[data-sport-id="3"],
.match-card[data-sport-id="3"]   { --sport-card-bg: url('/img/banners/sports/sports-backgrounds-pack/cards/tennis-card.webp'); }
.live-now-card[data-sport-id="11"],
.live-now-card[data-sport-id="15"],
.match-card[data-sport-id="11"],
.match-card[data-sport-id="15"]  { --sport-card-bg: url('/img/banners/sports/sports-backgrounds-pack/cards/volleyball-card.webp'); }
.live-now-card[data-sport-id="12"],
.match-card[data-sport-id="12"]  { --sport-card-bg: url('/img/banners/sports/sports-backgrounds-pack/cards/table-tennis-card.webp'); }
.live-now-card[data-sport-id="18"],
.match-card[data-sport-id="18"]  { --sport-card-bg: url('/img/banners/sports/sports-backgrounds-pack/cards/cricket-card.webp'); }

/* Featured-matches cards (homepage rail) — same artwork treatment as the live
   cards. The card body has its own opaque sections (mc-header / odds row), so
   the image reads through the middle band; see .match-card below. */
.match-card[data-sport-id] {
    background:
        linear-gradient(100deg, rgba(var(--bg-tertiary-rgb), 0.92) 12%, rgba(var(--bg-tertiary-rgb), 0.62) 48%, rgba(var(--bg-tertiary-rgb), 0.30) 100%),
        var(--sport-card-bg, none) right center / cover no-repeat;
    background-color: var(--bg-tertiary);
}

.live-now-card {
    flex: 0 0 280px;
    scroll-snap-align: start;
    display: flex;
    flex-direction: column;
    gap: 10px;
    padding: 12px 14px;
    /* background:
        linear-gradient(
160deg, #b2e90b -80%, var(--bg-secondary) 25%); */
    /* Overlay is heaviest on the LEFT — where the league, team names, scores and
       stats sit — and thins sharply toward the right so the artwork actually
       READS there. The pack images are already dark teal, so a heavy scrim (the
       first attempt used 0.93→0.76) rendered them invisible; text stays legible
       because the art is dark, not because the scrim is thick. `none` fallback =
       plain card when JS didn't stamp a sport id. */
    background:
        linear-gradient(100deg, rgba(var(--bg-tertiary-rgb), 0.94) 14%, rgba(var(--bg-tertiary-rgb), 0.60) 50%, rgba(var(--bg-tertiary-rgb), 0.22) 100%),
        var(--sport-card-bg, none) right center / cover no-repeat;
    background-color: var(--bg-tertiary);
    border: 1px solid transparent;
    border-radius: var(--radius-dec);
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: transform 0.18s ease, background 0.18s ease, box-shadow 0.18s ease;
    box-shadow: #0003 0 4px 6px -1px, #0000001f 0 2px 4px -1px;
}

/* Vertical accent strip on the leading edge — green pulse for live energy */
.live-now-card::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    /* background: linear-gradient(180deg, var(--accent-green), transparent); */
    opacity: 0.7;
}

/* Hover keeps the sport artwork — it just adds the green tint over it and
   lightens the overlay slightly so the image reads a touch stronger. */
.live-now-card:hover {
    background:
        linear-gradient(135deg, rgba(0, 231, 1, 0.09) 0%, rgba(0, 231, 1, 0) 40%),
        linear-gradient(100deg, rgba(var(--bg-tertiary-rgb), 0.90) 12%, rgba(var(--bg-tertiary-rgb), 0.52) 48%, rgba(var(--bg-tertiary-rgb), 0.12) 100%),
        var(--sport-card-bg, none) right center / cover no-repeat;
    background-color: var(--bg-secondary);
    transform: translateY(-2px);
    box-shadow: 0 8px 16px -8px rgba(0, 0, 0, 0.45);
}

.live-now-card,
.live-now-card * {
    cursor: pointer;
}

.live-now-card .live-now-odd {
    cursor: pointer;
}

.live-now-card .live-now-odd.locked {
    cursor: default;
}

.live-now-card-top {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 11px;
    color: var(--text-muted);
}

.live-now-badge {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 7px;
    /*background: linear-gradient(135deg, #ff3838, #d32f2f);*/
    color: #fff;
    border-radius: 0;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.6px;
    /*box-shadow: 0 0 0 1px rgba(255, 56, 56, 0.25);*/
}

.live-now-dot {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: #c23d5a;
    animation: live-pulse 1.4s infinite;
}

.live-now-sport-icon {
    width: 16px;
    height: 16px;
    flex-shrink: 0;
    filter: brightness(0) invert(0.65); /* turn the SVG into a muted-grey monochrome */
}

/* League on its own line, above the team names. */
.live-now-league-row {
    display: flex;
    align-items: center;
    min-width: 0;
    margin: 4px 0 2px;
    font-size: 11px;
}

.live-now-league {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
    color: var(--text-secondary);
    letter-spacing: 0.2px;
}

/* Country flag before the league name — keeps its intrinsic size and sits on
 * the text baseline; the name still ellipsis-truncates beside it. */
.live-now-league-flag {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    margin-right: 4px;
}
.live-now-league-flag img,
.live-now-league-flag svg {
    width: 14px;
    height: auto;
    border-radius: 0;
}

.live-now-minute {
    /* League no longer occupies the top row, so pin the minute to the right. */
    margin-left: auto;
    font-size: 12px;
    font-weight: 800;
    /*color: #ff5252;*/
    color: #fff;
    font-variant-numeric: tabular-nums;
    padding: 2px 6px;
    /*background: rgba(255, 82, 82, 0.12);*/
    border-radius: 0;
    letter-spacing: 0.3px;
    flex-shrink: 0;
}

.live-now-card-teams {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 6px 0;
}

.live-now-team {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

/* Kit + name grouped on the left so the score stays pinned right. min-width:0
   lets the name inside still truncate with an ellipsis. */
.live-now-team-left {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1;
    min-width: 0;
}

.live-now-team-name {
    font-weight: 600;
    font-size: 14px;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
}

.live-now-score {
    font-weight: 700;
    font-size: 18px;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    color: var(--text-secondary);
    min-width: 22px;
    text-align: right;
    transition: color 0.2s, transform 0.2s;
}

.live-now-score.winning {
    color: var(--accent-green);
    transform: scale(1.05);
}

/* Compact stats strip on Live Now cards (soccer only) */
.live-now-stats {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 6px 0 4px;
    border-top: 1px solid var(--border-color);
}

.lns-pos {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 6px;
}

.lns-pos-val {
    font-size: 10px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
    min-width: 22px;
}

.lns-pos-val.lns-pos-h { text-align: right; color: var(--accent-green); }
.lns-pos-val.lns-pos-a { text-align: left;  color: var(--text-secondary); }

.lns-pos-bar {
    display: flex;
    height: 4px;
    width: 100%;
    background: rgba(255, 255, 255, 0.06);
    border-radius: 2px;
    overflow: hidden;
}

.lns-pos-bar-h { background: var(--accent-green-grad); transition: width 0.4s ease; }
.lns-pos-bar-a { background: rgba(255, 255, 255, 0.18); transition: width 0.4s ease; }

.lns-counters {
    display: grid;
    /* Default 4-column grid (soccer). Sport-specific overrides below switch to 5 cols. */
    grid-template-columns: repeat(4, 1fr);
    gap: 4px;
    font-size: 10px;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}
.lns-counters.lns-counters-5 { grid-template-columns: repeat(5, 1fr); }
/* Tennis uses 4 cells; soccer also 4 — both covered by the base rule. */

/* Text label inside a counter (basketball / tennis sports use this instead of an SVG icon) */
.lns-counter-lbl {
    font-weight: 700;
    color: var(--text-muted);
    font-size: 9px;
    letter-spacing: 0.3px;
    text-transform: uppercase;
}

.lns-counter {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 3px 4px;
    background: rgba(255, 255, 255, 0.03);
    border-radius: 0;
    justify-content: center;
    color: var(--text-muted);
    font-weight: 600;
    min-width: 0;          /* allow the cell to shrink inside the narrow grid track */
    white-space: nowrap;   /* don't break "2-4" or "80%-44%" across lines */
    overflow: hidden;
    box-shadow: #0003 0 4px 6px -1px, #0000001f 0 2px 4px -1px;
}

/* Variant for cells with a text label (basketball/tennis): stack label above value so
   "1S% / 80%-44%" fits cleanly inside the ~60px grid cell instead of wrapping mid-value. */
.lns-counter:has(.lns-counter-lbl) {
    flex-direction: column;
    gap: 1px;
    line-height: 1.15;
    font-size: 11px;
}

.lns-counter svg { color: var(--text-muted); flex-shrink: 0; }

.lns-card {
    display: inline-block;
    width: 7px;
    height: 9px;
    border-radius: 0;
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
    flex-shrink: 0;
}

.lns-card-y { background: var(--gold); }
.lns-card-r { background: var(--accent-red); }

.live-now-card-odds {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: 5px;
    padding-top: 8px;
    border-top: 1px solid var(--border-color);
}

.live-now-odd {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    /* DENSITY (design review): 60px -> 44px. Labels are short market codes now,
       not repeated team names, so the price gets the room and the tap target
       still clears the 44px floor. */
    height: var(--odd-h, 44px);
    padding: 0 5px;
    background: var(--bg-odds);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    font-family: inherit;
    transition: background 0.15s, border-color 0.15s, transform 0.1s;
    /* Grid-item default `min-width: auto` is the content's intrinsic width.
       For a button containing an unbreakable team-name (white-space: nowrap),
       that's the full string length — so the column stretches and defeats
       the parent's `grid-auto-columns: 1fr` equal-width rule. Setting
       min-width: 0 lets the cell shrink below content and the label
       ellipsis kicks in. */
    min-width: 0;
}

.live-now-odd:hover {
    background: var(--bg-hover);
    border-color: var(--bg-hover);
}

.live-now-odd:active {
    transform: scale(0.97);
}

/* Selected state — applied by Betslip.syncButtonStates() when this odd is in the betslip */
.live-now-odd.selected {
    background: var(--blue-alt);
    border-color: var(--blue-alt);
}

.live-now-odd.selected .lno-label,
.live-now-odd.selected .lno-value {
    color: #fff;
}

.live-now-odd .lno-label {
    /* Short market code (1 / X / 2) — a quiet caption above the price, which is
       the thing being scanned. Was a truncated team name; see the JS comment. */
    font-size: 9px;
    font-weight: 700;
    color: var(--text-muted);
    letter-spacing: 0.6px;
    line-height: 1;
    width: 100%;
    min-width: 0;
    text-align: center;
}

.live-now-odd .lno-value {
    font-size: 14px;
    font-weight: 800;
    color: var(--accent-odds);
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}

.live-now-odd.locked {
    background:var(--bg-odds);
    pointer-events: none;
}

.live-now-odd.locked .lno-value {
    color: var(--text-muted);
}

.section-header-right {
    display: flex;
    align-items: center;
    gap: 12px;
}

.scroll-arrows {
    display: flex;
    gap: 4px;
}

.scroll-arrow {
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-tertiary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-secondary);
    cursor: pointer;
    transition: all 0.15s;
}

.scroll-arrow:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}

/* --- Bet Boost / Most-Played Markets cards --- */
.bet-boost-today {
    font-size: 13px;
    font-weight: 700;
    color: var(--text-primary);
    border: 1px solid var(--border-color);
    background: var(--bg-tertiary);
    padding: 6px 14px;
    border-radius: 999px;
    white-space: nowrap;
    transition: background 0.15s, border-color 0.15s;
}

.bet-boost-today:hover {
    background: var(--bg-hover);
}

/* 1a "boosts: grid, not rail" — but a pure grid was wrong at real volume: ~20
   boosts became SEVEN stacked rows that owned the whole page. This is the grid
   the review wanted (compact rows, not tall cards) capped at TWO rows, flowing
   into columns that scroll sideways. The section keeps a fixed, small footprint
   no matter how many boosts the feed sends.
   NOTE: no `scroll-snap-type: mandatory` here — it cancels programmatic smooth
   scrolls, and the arrows go through App.smoothScrollBy. */
.bet-boost-grid {
    display: grid;
    grid-auto-flow: column;
    /* ONE row. Was `repeat(2, auto)`, which stacked the strip two cards deep and
       made it read as a block of content rather than a rail — and the two rows
       scrolled as a unit, so an arrow press moved four cards at once. A single
       row also stops a card's height being set by whichever card it happened to
       share a column with. */
    grid-template-rows: auto;
    /* Capped, NOT 1fr. With `1fr` a light Bet Boost day (2-3 boosts) let each
       column stretch across the whole content width, so two small boosts
       rendered as two page-wide slabs. The cap keeps a card a card at any
       count; `justify-content: start` stops the track itself centring when the
       columns no longer fill the row. */
    grid-auto-columns: minmax(280px, 360px);
    justify-content: start;
    gap: 10px;
    overflow-x: auto;
    scrollbar-width: none;
    /* Must be BOTH axes: a bare `pan-x` swallows vertical swipes that start on
       the carousel and the page won't scroll on mobile. */
    touch-action: pan-x pan-y;
}

.bet-boost-grid::-webkit-scrollbar {
    display: none;
}

.bet-boost-card {
    position: relative;
    display: flex;
    /* Column: the fixture headlines the card across its FULL width, then a row
       of kits + selection + price beneath it. Previously the fixture shared a
       line with the price button, so it had ~60% of the card and truncated
       ("CA Paranaense PR v EC Vitori..."). Giving it the whole width also drops
       the price onto the second line, which is where it reads better anyway. */
    flex-direction: column;
    align-items: stretch;
    gap: 10px;
    /* Top padding is the strip the placed-count badge sits in — see .bb-placed. */
    padding: 24px 13px 11px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 0;
    min-width: 0;
    transition: border-color 0.18s ease;
    cursor: pointer;
}

.bet-boost-card:hover {
    border-color: var(--accent-green);
}

/* `.bb-top` / `.bb-badge*` are gone with the tall card — the per-card Bet Boost
   wordmark duplicated the section header on every single card. The header keeps
   the wordmark; see createBetBoostCard. */

/* Section heading is the wordmark itself. Sized off the heading's own font-size
   so it tracks the type scale instead of pinning a px height. */
.bb-wordmark {
    height: 1em;
    width: auto;
    display: block;
    padding-left: 5px;
}

.bb-placed {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
}

.bb-placed strong {
    color: var(--text-primary);
    font-weight: 800;
}

.bb-fire {
    width: 12px;      /* the compact 1a row can't carry a 17px icon on its meta line */
    height: 12px;
    color: #fb6308;
    flex-shrink: 0;
    filter: drop-shadow(0 0 5px rgba(251, 99, 8, 0.6));
}

/* Second line: kits, then selection + market, then the price. */
.bb-row {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}

.bb-body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    cursor: pointer;
}

.bb-teams-name {
    display: block;
    font-size: 15px;
    font-weight: 900;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
    font-stretch: condensed;
    font-weight: 700;
    line-height: 20px;
    text-transform: uppercase;
    margin-top:5px;
}

/* Kits overlap slightly so the pair reads as one match token. */
.bb-kits {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
}

.bb-kits img {
    width: 22px;
    height: 22px;
    object-fit: contain;
}

.bb-kits img + img {
    margin-left: -6px;
}

/* The pick itself — the one line that says what you're actually backing, so it
   gets white on its own row rather than being glued behind the market name. */
.bb-selection {
    display: block;
    font-size: 11.5px;
    font-weight: 700;
    color: var(--accent-odds);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* Now holds only the market name, so it gets the full width of the card. */
.bb-market {
    display: flex;
    align-items: center;
    font-size: 10.5px;
    font-weight: 600;
    color: var(--text-muted);
    min-width: 0;
}

.bb-market-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* Social proof as a top-left corner badge, OUT of the meta line entirely — while
   it shared that line the market name had ~40px left and ellipsised to "Matc…".
   The card reserves a 24px top strip for it (see .bet-boost-card padding). */
.bet-boost-card .bb-placed {
    position: absolute;
    top: 7px;
    left: 13px;
    gap: 3px;
    font-size: 10.5px;
    line-height: 1;
}

/* This IS a betslip price — the user taps it to add the selection — so it wears
   the same button surface as .live-odd-btn / .hero-odd rather than sitting as
   bare text. The old price stacks above the boosted one inside the button. */
.bb-odd {
    flex-shrink: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    min-width: 70px;
    padding: 5px 8px;
    background: var(--bg-odds);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    line-height: 1;
    cursor: pointer;
    font-family: inherit;
    font-variant-numeric: tabular-nums;
    transition: border-color 0.15s, background 0.15s;
}

.bb-odd:hover {
    border-color: var(--accent-green);
}

/* Selected state matches the rest of the site's prices (.live-odd-btn.selected):
   the BUTTON fills, not the card. */
.bb-odd.selected {
    background: var(--blue-alt);
    border-color: var(--blue-alt);
}

.bb-odd.selected .bb-odd-new {
    background: none;
    -webkit-text-fill-color: #fff;
    color: #fff;
}

.bb-odd-locked {
    cursor: default;
    opacity: 0.55;
    filter: grayscale(0.6);
}

.bb-odd-new {
    font-family: var(--font-display);
    font-size: 21px;
    letter-spacing: -0.01em;
    background: linear-gradient(to bottom, color(display-p3 .752941 .909804 .286275 / 1), #36f670);
    background-clip: text;
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
    font-weight: 700;
}

/* --- Match Cards (Stake-style Top Matches) --- */
.match-card {
    flex: 0 0 300px;
    min-width: 270px;
    scroll-snap-align: start;
    background: var(--bg-tertiary);
       /* background:
        linear-gradient(
160deg, #b2e90b -80%, var(--bg-secondary) 25%); */
    border-radius: var(--radius-dec);
    border: 1px solid var(--border-color);
    overflow: hidden;
    transition: border-color 0.2s;
    display: flex;
    flex-direction: column;
    box-shadow: #0003 0 4px 6px -1px, #0000001f 0 2px 4px -1px;
}

.match-card:hover {
    border-color: var(--bg-hover);
}

.mc-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px;
}

.mc-header-left,
.mc-header-right {
    display: flex;
    align-items: center;
    gap: 6px;
}

.mc-time-badge {
    font-size: 11px;
    font-weight: 700;
    color: var(--text-primary);
    background: var(--bg-tertiary);
    padding: 2px 8px;
    border-radius: var(--radius-sm);
}

.mc-flag {
    font-size: 14px;
}

.mc-markets {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-secondary);
}

.mc-teams {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: 24px;
    padding: 8px 14px 14px;
    flex: 1;
}

.mc-team {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    flex: 1;
    min-width: 0;
}

.mc-kit {
    width: 48px;
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.team-kit-lg {
    width: 48px;
    height: 48px;
    object-fit: contain;
}

.mc-team-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    text-align: center;
    line-height: 1.2;
    word-break: break-word;
}

.mc-odds {
    display: flex;
    gap: 4px;
    padding: 0 10px 10px;
}

.odd-btn-card {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 0px 5px;
    background: var(--bg-odds);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: all 0.15s;
    font-family: inherit;
    min-width: 0;
    height: 60px;
    gap:5px;
}

.odd-btn-card:hover {
    background: var(--bg-hover);
    border-color: var(--accent-green);
}

.odd-btn-card.selected {
    background: var(--blue-alt);
}

.odd-btn-card.selected .odd-btn-card-label {
    color: rgba(255, 255, 255, 0.8);
}

.odd-btn-card.selected .odd-btn-card-value {
    color: #fff;
}

.odd-btn-card-label {
    font-size: 10px;
    color: var(--text-muted);
    font-weight: 500;
    margin-bottom: 2px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

.odd-btn-card-value {
    font-size: 15px;
    font-weight: 900;
    color: var(--accent-odds);
}

/* Team kit shared sizes */
.team-kit-img {
    width: 32px;
    height: 32px;
    object-fit: contain;
}

.team-kit-sm {
    width: 20px;
    height: 20px;
    object-fit: contain;
    flex-shrink: 0;
}

.league-flag {
    font-size: 14px;
    margin-right: 2px;
}

/* ==========================================
   GROUPED LEAGUE MATCHES
   ========================================== */
.league-group {
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-dec);
    overflow: hidden;
    margin-bottom: 5px;
    scroll-margin-top: calc(var(--header-height) + 16px);
}

.league-group-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 5px 16px;
    background: var(--bg-tertiary);
}

.league-group-title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.03em;
}

.league-group-title .league-flag {
    font-size: 18px;
}

.league-date-group {
    border-top: 1px solid var(--border-color);
    border-radius: var(--radius-md);
}

.league-date-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 16px;
    background: rgba(var(--bg-tertiary-rgb), 0.3);
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted);
}

.odds-header-labels {
    display: flex;
    /* Match `.league-match-odds` gap so each header label centers over its
       odds column. */
    gap: 4px;
    /* FIXED width (not min-width): the odds row uses the same fixed width, so
       neither can grow past the other. With `min-width` the odds container
       could expand to fit its buttons while this header stayed pinned at the
       minimum, drifting the 1/X/2 labels off-center. Both fixed + identical =
       guaranteed column alignment. Keep this in lock-step with
       `.league-match-odds` width (and the ≤600px override). */
    width: 180px;
    flex-shrink: 0;
}

.odds-header-labels span {
    flex: 1;
    text-align: center;
    font-size: 12px;
    font-weight: 700;
    color: var(--text-muted);
}

.league-match-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 16px;
    background: var(--bg-secondary);
    border-top: 1px solid rgba(var(--bg-tertiary-rgb), 0.3);
    transition: background 0.1s;
}

@media (hover: hover) {
    .league-match-row:hover {
        background: rgba(var(--bg-tertiary-rgb), 0.2);
    }
}

.league-match-teams {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1;
    min-width: 0;
}

.league-match-team {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 13px;
    font-weight: 500;
}

.league-match-team span {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.team-kit-sm {
    width: 20px;
    height: 20px;
    object-fit: contain;
    flex-shrink: 0;
}

.league-match-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 2px;
}

.league-match-time {
    font-size: 11px;
    color: var(--text-muted);
    font-weight: 500;
}

.league-match-markets {
    font-size: 11px;
    color: var(--accent-green-neon);
    font-weight: 700;
    padding: 2px 8px;
    background: rgba(0, 231, 1, 0.12);
    border: 1px solid rgba(0, 231, 1, 0.22);
    border-radius: 0;
    line-height: 1;
    letter-spacing: 0.2px;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.league-match-row:hover .league-match-markets {
    background: rgba(0, 231, 1, 0.2);
    border-color: rgba(0, 231, 1, 0.45);
}

.league-match-odds {
    display: flex;
    gap: 4px;
    /* FIXED width — see `.odds-header-labels`. Keep both widths in lock-step. */
    width: 180px;
    flex-shrink: 0;
}

.odd-btn-inline {
    flex: 1;
    padding: 6px 4px;
    height: 65px;
    background: var(--bg-odds);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--accent-odds);
    font-size: 15px;
    font-weight: 900;
    text-align: center;
    cursor: pointer;
    transition: all 0.15s;
    font-family: inherit;
    /* No explicit `width` — it conflicts with `flex: 1` (flex-basis 0) and
       skewed the buttons' column sizing relative to the `.odds-header-labels`
       spans (which are pure flex:1), so the 1/X/2 header drifted off-center
       over the values. Both now size identically: flex:1 children in equal
       min-width + equal-gap containers. */
}

.odd-btn-inline:hover {
    background: var(--bg-hover);
    border-color: var(--accent-green);
}

.odd-btn-inline.selected {
    background: var(--blue-alt);
    color: white;
}

.odd-btn-inline.disabled {
    color: var(--text-muted);
    cursor: default;
    pointer-events: none;
}

/* Outright / single-selection league rows (e.g. Top Goalscorer): a compact row with
   one right-aligned odd button instead of the 3-column 1/X/2 grid. */
.league-match-outright {
    padding-top: 7px;
    padding-bottom: 7px;
}

.league-match-outright .league-match-odds {
    /* Override the fixed 180px width — outright rows have one right-aligned
       button sized to its own content. */
    width: auto;
    min-width: 0;
    flex: 0 0 auto;
}

.league-match-outright .odd-btn-inline {
    flex: 0 0 auto;
    width: 88px;
    height: 44px;
}

/* Lock icon shown in place of a 1.00 (suspended) odd, across all button styles */
.odd-lock-icon {
    vertical-align: middle;
    color: var(--text-muted);
    opacity: 0.85;
}

.odd-btn-inline.disabled .odd-lock-icon,
.odd-btn-card.disabled .odd-lock-icon,
.md-odd-btn.disabled .odd-lock-icon {
    color: var(--text-muted);
}

/* Suspended (locked) state for prematch card and match-detail buttons */
.odd-btn-card.disabled,
.md-odd-btn.disabled {
    cursor: default;
    pointer-events: none;
    background: var(--bg-tertiary);
    color: var(--text-muted);
}

.odd-btn-card.disabled .odd-btn-card-value,
.md-odd-btn.disabled .md-odd-value {
    color: var(--text-muted);
}

/* --- Leagues Grid (3-row horizontal scroll) --- */
.leagues-grid {
    display: grid;
    /* TWO rows, not three. At three rows the ~10 leagues the feed sends fill three
       full columns and leave a fourth holding one card above two empty cells — a
       visible hole at the end of a section that is otherwise a tidy block. Two rows
       divides the same 10 into five complete columns, and because five columns
       overflow the board the rail actually scrolls, which is what the chevrons in
       the header were promising all along. It also halves the vertical footprint of
       a secondary section that sits between the live board and featured matches. */
    /* 1fr, not auto: with auto each row took its own tallest card, so one card
       whose line wrapped ("Netherlands · 4 ngjarje") made its whole row 17px taller
       than the other. Equal rows, and the card lines stay on one line below. */
    grid-template-rows: repeat(2, 1fr);
    grid-auto-flow: column;
    grid-auto-columns: minmax(220px, 280px);
    gap: 10px;
    overflow-x: auto;
    /* `proximity`, not `mandatory` — mandatory snapping CANCELS a programmatic
       smooth scroll, so the arrows (App.smoothScrollBy) jumped instead of gliding.
       Same fix already documented on .bet-boost-grid; this rail had been missed. */
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 4px;
}

.leagues-grid::-webkit-scrollbar {
    display: none;
}

/* Capping .live-match-teams at 360px hands ~470px back to the row. Rather than
   leave it as gutter, the primary action takes it: on a desktop-width board the
   price buttons go from 58px to 88px, which is a materially better pointer target
   for the one control the page exists to offer. Because --odd-w also drives the
   `1 X 2` header spans and the O/U label, they follow automatically.
   Gated at 1100px — below that the row is genuinely tight and the narrow tokens
   in the mobile blocks are what keep team names legible. */
@media (min-width: 1100px) {
    :root {
        --odd-w: 88px;
    }
}

.league-card {
    scroll-snap-align: start;
}

.league-card {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 16px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-dec);
    cursor: pointer;
    transition: all 0.15s;
    min-width: 0;
    box-shadow: #0003 0 4px 6px -1px, #0000001f 0 2px 4px -1px;
}

.league-card:hover {
    border-color: var(--bg-hover);
    background: var(--bg-tertiary);
}

.league-icon {
    width: 36px;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-tertiary);
    border-radius: var(--radius-md);
    font-size: 18px;
    flex-shrink: 0;
}

.league-info {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;   /* or the ellipses below never engage */
}

.league-name {
    font-size: 15px;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* One line: a long country shortens, the event count always shows. */
.league-count {
    display: flex;
    min-width: 0;
    font-size: 11px;
    color: var(--text-muted);
    white-space: nowrap;
}
.league-count-country {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
.league-count-n {
    flex: none;
}

/* ==========================================
   BETSLIP PANEL
   ========================================== */
.betslip-panel {
    width: 0;
    min-width: 0;
    overflow: hidden;
    flex-shrink: 0;
    background: var(--bg-secondary);
    border-left: 1px solid transparent;
    height: calc(100vh - var(--header-height));
    position: sticky;
    top: var(--header-height);
    /* Prevent the flex `align-items: stretch` default from over-stretching
       the panel to match `.content`'s very tall height. Without this, the
       panel becomes as tall as the entire matches list and sticky has
       nothing to "stick" to (the element is already at the top of its
       allocated space) — net effect: panel scrolls with the page instead
       of staying pinned. */
    align-self: flex-start;
    flex-direction: column;
    display: flex;
    transition: width 0.3s ease, min-width 0.3s ease, border-color 0.3s ease;
}

.betslip-panel.open {
    width: var(--betslip-width);
    min-width: var(--betslip-width);
    border-left-color: var(--border-color);
    overflow-x: hidden;
    overflow-y: auto;
}

.betslip-header {
    padding: 0;
    border-bottom: 1px solid var(--border-color);
    position: relative;
}

.betslip-close-desktop {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    border-radius: 50%;
    transition: all 0.15s;
}

.betslip-close-desktop:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
}

.betslip-tabs {
    display: flex;
}

.betslip-tab {
    flex: 1;
    padding: 12px;
    background: transparent;
    color: var(--text-muted);
    font-size: 13px;
    font-weight: 600;
    text-align: center;
    border-bottom: 2px solid transparent;
    transition: all 0.15s;
    height: 50px;
    /* Icon + label + count sit on one centered row. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}

.betslip-tab-ico {
    flex: 0 0 auto;
    display: block;
    /* currentColor → follows the tab's muted/active text color for free. */
}

.betslip-tab:hover {
    color: var(--text-secondary);
}

.betslip-tab.active {
    color: var(--text-primary);
    border-bottom-color: var(--accent-green);
}

.betslip-body {
    flex: 1;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    overflow-y: auto;
    overflow-x: hidden;
}

/* Desktop slip: make .bs-content a full-height flex column so the selections list
   scrolls INTERNALLY and the footer (totals / stake / jackpot / place button) stays
   pinned and visible — regardless of selection count or the jackpot console height.
   (Mirrors the mobile overlay; replaces the fragile `max-height: calc(100dvh-380px)`
   reserve that pushed Place off-screen once the jackpot console was added.) */
#betslip-body > .bs-content {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}
#betslip-body .bs-selections-wrap {
    flex: 1;
    min-height: 0;
}
#betslip-body .bs-selections {
    flex: 1;
    max-height: none;
    min-height: 0;
    overflow-y: auto;
}
#betslip-body .bs-header-row,
#betslip-body .bs-totals,
#betslip-body .bs-stake,
#betslip-body .bs-jackpot,
#betslip-body .bs-result-area,
#betslip-body .bs-place-btn,
#betslip-body .bs-reoffer-msg,
#betslip-body .bs-reoffer-btns {
    flex-shrink: 0;
}

/* ===========================================================
   My Bets — list view (sibling of .betslip-body)
   =========================================================== */
.mybets-body {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding: 0;
    display: flex;
    flex-direction: column;
    min-height: 0;       /* allow inner scroll within a flex parent */
}

/* On the dedicated Filter Tickets page (#TF) the body sits inside a regular
 * .profile-page wrapper (not the betslip flex column), so the `flex: 1` rule
 * above resolves to height 0 and the list collapses. Force a sensible minimum
 * height so the date bar + tabs + tickets all render at full size. */
#mybets-page-body {
    min-height: calc(100dvh - 200px);
    overflow: visible;   /* let the parent page scroll instead of an inner scroll context */
}

/* The `hidden` attribute must beat the parent's `display: flex` rule.
   Without `!important`, the betslip body stays visible above MyBets. */
.betslip-body[hidden],
.betslip-overlay-body[hidden],
.mybets-body[hidden] {
    display: none !important;
}

/* Mobile overlay grows to (nearly) full screen when on the MyBets tab so the ticket list
   has room to breathe. Toggled by JS via .mybets-active. Subtracting the bottom-nav height
   keeps it from overlapping the nav (which now sits above the overlay at z-index: 300).
   `100dvh` (dynamic viewport height) is critical here — iOS Safari/Chrome's URL bar
   shrinks the visible area, but `100vh` stays fixed and pushes the last ticket /
   place button off-screen. `100dvh` updates as the toolbars show/hide. */
.betslip-overlay-panel.mybets-active {
    /* Also subtract the TOP safe-area inset so the (nearly full-height) panel
       starts BELOW the notch / Dynamic Island in the fullscreen home-screen app.
       Without this the panel reached y=0 and its header (tabs + ×) sat under the
       status bar. `env()` is 0 in the browser, so normal Safari is unaffected. */
    /* 100% of the overlay (which already accounts for the bottom nav where one
       exists) minus the top inset, so the header clears the notch in the
       fullscreen app and there's no phantom nav gap on tablets. */
    max-height: calc(95% - env(safe-area-inset-top, 0px));
    height:     calc(95% - env(safe-area-inset-top, 0px));
}

/* The #TF page: full width on a phone, a centred column on desktop (b3t's rows
   stretched across 1440px read as one long teal band). */
.mybets-page {
    max-width: 760px;
    margin: 0 auto;
}

/* Edge to edge below the column width, as on b3t: cancel .content's own padding
   (8px, or 10px at <=600px). */
@media (max-width: 776px) {
    .mybets-page { margin: -8px -8px 0; }
}
@media (max-width: 600px) {
    .mybets-page { margin: -10px -10px 0; }
}

/* My Bets head — "My Bets - (n)" with the status select on the right (b3t layout) */
.mybets-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    min-height: 48px;
    padding: 0 12px;
    background: var(--bg-tertiary);
}

.mybets-head-title {
    margin: 0;
    font-size: 17px;
    font-weight: 700;
    color: var(--text-primary);
}

.mybets-head-status {
    max-width: 50%;
    padding: 6px 4px;
    background: transparent;
    border: none;
    color: var(--text-primary);
    font: inherit;
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
}

.mybets-head-status option { background: var(--bg-tertiary); }

/* From / to / Filter, then the quick ranges as underlined tabs */
.mybets-date-bar {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 8px 12px 0;
    background: var(--bg-hover);
}

/* Horizontal scroller (used for date-presets and status-tabs).
   Wraps the scrollable element with overlaid left/right chevron buttons
   that fade in only on hover, so the row layout stays clean. */
.mybets-scroller {
    position: relative;
}

.mybets-scroll-arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 10;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    padding: 0;
    background: var(--bg-input);
    border: 1px solid var(--border-color);
    border-radius: 50%;
    color: var(--text-primary);
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.2s, background 0.15s, transform 0.15s;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
}

.mybets-scroll-arrow-l { left: 2px; }
.mybets-scroll-arrow-r { right: 2px; }

/* The fade-in is driven by hover on the WRAPPER, so the arrows feel like a peek-cue
   that surfaces while the user is interacting with the row. */
.mybets-scroller:hover .mybets-scroll-arrow {
    opacity: 1;
}

.mybets-scroll-arrow:hover {
    background: var(--bg-hover);
    transform: translateY(-50%) scale(1.08);
}

.mybets-scroll-arrow.disabled {
    opacity: 0 !important;
    pointer-events: none;
}

/* When the inner row doesn't overflow, hide the arrows so the row is centered */
.mybets-scroller.no-overflow .mybets-scroll-arrow {
    display: none;
}

/* Touch / narrow viewports use native swipe — arrows hidden */
@media (max-width: 1100px) {
    .mybets-scroll-arrow {
        display: none;
    }
}

.mybets-date-presets {
    display: flex;
    justify-content: safe center;
    gap: 4px;
    overflow-x: auto;
    scrollbar-width: none;
    scroll-behavior: smooth;
    -webkit-overflow-scrolling: touch;
}

.mybets-date-presets::-webkit-scrollbar { display: none; }

.mybets-preset {
    flex-shrink: 0;
    padding: 12px 10px 9px;
    background: none;
    border: none;
    border-bottom: 3px solid transparent;
    border-radius: 0;
    color: var(--text-secondary);
    font-size: 14px;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s;
    white-space: nowrap;
}

.mybets-preset:hover { color: var(--text-primary); }

.mybets-preset.active {
    color: var(--text-primary);
    border-bottom-color: var(--accent-teal);
}

.mybets-date-range {
    display: flex;
    justify-content: center;
    gap: 6px;
}

.mybets-date-range input[type="date"] {
    flex: 1 1 0;
    min-width: 0;
    max-width: 150px;
    height: 36px;
    padding: 0 8px;
    background: var(--text-primary);
    border: none;
    border-radius: 0;
    color: var(--bg-deep);
    font: inherit;
    font-size: 14px;
    color-scheme: light;
}

.mybets-date-range input[type="date"]:focus {
    outline: 2px solid var(--accent-teal);
    outline-offset: -2px;
}

.mybets-date-apply {
    flex: 0 0 auto;
    height: 36px;
    padding: 0 18px;
    background: var(--accent-teal);
    border: none;
    border-radius: 0;
    color: var(--text-primary);
    font: inherit;
    font-size: 14px;
    cursor: pointer;
}

.mybets-date-apply:hover { filter: brightness(1.1); }

/* Selection count on the Betslip tab — same visual treatment as the
 * My Bets tab count. Sits to the right of the "Betslip" label and tells
 * the user how many picks are queued while they're on the My Bets tab. */
.betslip-tab-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    padding: 0 5px;
    margin-left: 6px;
    background: var(--accent-green-grad);
    color: var(--bg-green-deep);
    border-radius: 999px;
    font-size: 10px;
    font-weight: 800;
}

/* Keep the green pill readable when the tab itself is active. */
.betslip-tab.active .betslip-tab-count {
    background: var(--accent-green-grad);
    color: var(--bg-green-deep);
}


/* Placing-state badge — the green count pill gets a soft pulse + a mini
   spinner replaces the number. Applied by Betslip._setTabPlacing so it
   appears identically on:
   - desktop "Betslip" tab count
   - mobile overlay's "Betslip" tab count
   - floating action button's count badge
   Even if the user navigates away from the slip while the network request
   is in flight, the pulse is visible from any header / nav location. */
.bs-tab-placing {
    background: var(--accent-green-grad) !important;
    animation: bs-tab-placing-pulse 1.2s ease-in-out infinite;
}
@keyframes bs-tab-placing-pulse {
    0%, 100% { box-shadow: 0 0 0 0   rgba(58, 165, 110, 0.55); }
    70%      { box-shadow: 0 0 0 8px rgba(58, 165, 110, 0);   }
}
.bs-tab-spinner {
    display: inline-block;
    width: 10px;
    height: 10px;
    border: 2px solid rgba(10, 29, 18, 0.25);
    border-top-color: var(--bg-green-deep);
    border-radius: 50%;
    animation: bs-tab-spinner-spin 0.7s linear infinite;
}
@keyframes bs-tab-spinner-spin {
    to { transform: rotate(360deg); }
}
/* Header betslip toggle pulses too while placing so users with the slip
   collapsed on desktop still see the activity. */
#header-betslip-toggle.is-placing {
    animation: bs-tab-placing-pulse 1.2s ease-in-out infinite;
}

/* Result toast — drops in from the top, colored by outcome. Stays out of
   the way (top-center) so it doesn't cover the slip itself; auto-hides
   after a few seconds. */
/* Sporty notification-style toast: dark card + colored left rail + icon badge +
   an auto-dismiss countdown bar. Slides down from the header with a little bounce. */
.bs-toast {
    position: fixed;
    top: 74px;            /* below the header */
    left: 50%;
    transform: translate(-50%, -170%);
    z-index: 1500;
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 240px;
    max-width: min(440px, 92vw);
    padding: 12px 20px 12px 13px;
    border-radius: 0;
    font-size: 14px;
    font-weight: 700;
    color: #fff;
    background: linear-gradient(180deg, var(--bg-secondary), var(--bg-secondary));
    border: 1px solid rgba(255, 255, 255, 0.07);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
    text-align: left;
    pointer-events: none;
    opacity: 0;
    overflow: hidden;
    transition: transform 0.34s cubic-bezier(0.22, 1.2, 0.36, 1), opacity 0.22s;
}
.bs-toast.bs-toast-show {
    transform: translate(-50%, 0);
    opacity: 1;
}
/* colored rail down the left edge */
.bs-toast::before {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 4px;
}
.bs-toast-icon {
    flex-shrink: 0;
    width: 32px; height: 32px;
    display: flex; align-items: center; justify-content: center;
    border-radius: 0;
}
.bs-toast-icon svg { width: 18px; height: 18px; }
.bs-toast-msg { flex: 1; min-width: 0; line-height: 1.3; }
/* auto-dismiss countdown */
.bs-toast-bar {
    position: absolute;
    left: 0; bottom: 0;
    height: 3px; width: 100%;
    transform-origin: left center;
    animation-name: bs-toast-countdown;
    animation-timing-function: linear;
    animation-fill-mode: forwards;
    opacity: 0.9;
}
@keyframes bs-toast-countdown { from { transform: scaleX(1); } to { transform: scaleX(0); } }

/* per-type accents (rail + icon badge + countdown) — brand-ish sporty colors */
.bs-toast-success::before        { background: var(--accent-green, #00e701); }
.bs-toast-success .bs-toast-icon { background: rgba(0, 231, 1, 0.16); color: #34e07a; }
.bs-toast-success .bs-toast-bar  { background: var(--accent-green, #00e701); }
.bs-toast-error::before          { background: #ff4d5e; }
.bs-toast-error .bs-toast-icon   { background: rgba(255, 77, 94, 0.18); color: #ff6b7a; }
.bs-toast-error .bs-toast-bar    { background: #ff4d5e; }
.bs-toast-warning::before        { background: var(--gold, #f5c518); }
.bs-toast-warning .bs-toast-icon { background: rgba(245, 197, 24, 0.18); color: #f5c518; }
.bs-toast-warning .bs-toast-bar  { background: var(--gold, #f5c518); }
.bs-toast-info::before           { background: var(--accent-teal); }
.bs-toast-info .bs-toast-icon    { background: rgba(var(--accent-teal-rgb), 0.18); color: var(--accent-teal-light); }
.bs-toast-info .bs-toast-bar     { background: var(--accent-teal); }

/* Ticket list — b3t layout: a date band, then one teal line per ticket
   (stake · time - Nr. · Cancel or result). A tap opens the grey panel with the
   selections, stake / payout, Repeat and Details. */
.mybets-list {
    display: flex;
    flex-direction: column;
}

.mybets-day {
    padding: 14px 12px;
    background: var(--bg-tertiary);
    color: var(--text-secondary);
    font-size: 16px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.mybets-card { display: flex; flex-direction: column; }

.mybets-row {
    display: grid;
    /* stake · time - Nr. · possible win (MyBets._ticketWin) · Cancel / result */
    grid-template-columns: minmax(64px, auto) minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 8px;
    min-height: 45px;
    padding: 0 12px;
    background: var(--ticket-row-bg);
    border-bottom: 1px solid var(--bg-hover);
    color: var(--header-ink);
    font-size: 14px;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
}

.mybets-row:hover { filter: brightness(1.06); }

/* One set of columns for the whole list: every ticket row lays out on the LIST's grid
   (subgrid through the card), so stake, time - Nr., the win chip and Cancel / result
   line up from row to row instead of each row sizing its own columns. Each column is
   as wide as its widest entry in the list; the time - Nr. column takes the rest and
   shortens first. The win chips stretch to their column, so they are all one width.
   Without subgrid (old browsers) each row keeps its own columns, as before. */
@supports (grid-template-columns: subgrid) {
    .mybets-list {
        display: grid;
        grid-template-columns: minmax(64px, auto) minmax(0, 1fr) auto auto;
        column-gap: 8px;
    }
    .mybets-list > * { grid-column: 1 / -1; }
    .mybets-card {
        display: grid;
        grid-template-columns: subgrid;
    }
    .mybets-card > * { grid-column: 1 / -1; }
    .mybets-row {
        grid-template-columns: subgrid;
        column-gap: 8px;
    }
}

.mybets-row-id {
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* The possible win, on the line with the rest. The amount never shortens — the time /
   number cell gives way first (ellipsis); on a phone the "Fitimi" word goes before that. */
.mybets-row-win {
    font-weight: 700;
    white-space: nowrap;
    text-align: right;
}
/* The amount sits on a chip so it reads as the ticket's figure, not loose text on the
   teal; a won ticket's chip is the bet-slip green with dark ink. Empty (cancelled) = no chip. */
.mybets-row-win:not(:empty) {
    padding: 3px 8px;
    border-radius: var(--radius-sm);
    background: rgba(var(--bg-deep-rgb), 0.28);
}
.mybets-row-win-lbl { font-weight: 400; opacity: 0.8; }
@media (max-width: 420px) {
    .mybets-row-win-lbl { display: none; }
}
.mybets-row-win-won:not(:empty) {
    background: var(--accent-green);
    color: var(--bg-input);
}
.mybets-row-win-won .mybets-row-win-lbl { opacity: 0.75; }
.mybets-row-win-lost { opacity: 0.65; }

.mybets-row-end { display: inline-flex; justify-content: flex-end; }

.mybets-row-cancel {
    height: 30px;
    padding: 0 14px;
    background: none;
    border: 1px solid var(--bg-primary);
    border-radius: 0;
    color: var(--bg-primary);
    font: inherit;
    font-size: 13px;
    cursor: pointer;
}

.mybets-row-cancel:hover { background: rgba(var(--bg-primary-rgb), 0.12); }

/* Result on the teal row: plain bold text, dark enough to read on teal */
.mybets-pill {
    display: inline-flex;
    align-items: center;
    flex-shrink: 0;
    padding: 2px 6px;
    border-radius: 0;
    font-size: 10px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.mybets-pill-pending    { background: rgba(var(--accent-teal-rgb), 0.15); color: var(--accent-odds); }
.mybets-pill-won        { background: rgba(0, 231, 1, 0.18);     color: var(--accent-green); }
.mybets-pill-lost       { background: rgba(237, 65, 99, 0.18);   color: var(--accent-red); }
.mybets-pill-cancel     { background: rgba(255, 255, 255, 0.08); color: var(--text-muted); }
.mybets-pill-cancelreq  { background: rgba(255, 140, 0, 0.18);   color: var(--accent-orange); }

.mybets-row-end .mybets-pill {
    padding: 0;
    background: none;
    font-size: 13px;
    text-transform: none;
    letter-spacing: 0;
}

.mybets-row-end .mybets-pill-lost      { color: var(--accent-red-ink); }
/* Won reads green, next to the green win chip (it was near-black on the teal). */
.mybets-row-end .mybets-pill-won       { color: var(--accent-green); }
/* Cancelled: the same dark ink as "cancel requested" (--bg-tertiary vanished on the
   row), a little faded — the ticket is void, its stake came back. */
.mybets-row-end .mybets-pill-cancel    { color: var(--bg-deep); opacity: 0.7; }
.mybets-row-end .mybets-pill-cancelreq { color: var(--bg-deep); }

.mybets-amount-win { color: var(--accent-green); }

/* The open panel */
.mybets-card-legs {
    background: var(--bg-ticket-open);
    color: var(--text-secondary);
    cursor: default;
}

.mybets-card-legs[hidden] { display: none; }

.mybets-leg {
    display: grid;
    grid-template-columns: 18px 1fr auto;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
}

.mybets-leg-status {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--text-muted);
}

.mybets-leg-won  { background: var(--accent-green); }
.mybets-leg-lost { background: var(--accent-red); }

.mybets-leg-body {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.mybets-leg-match,
.mybets-leg-pick {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.mybets-leg-match { font-size: 14px; color: var(--text-primary); }
/* Opens the match's statistics popup (MyBets._wireRowButtons), like Bet Details. */
.mybets-leg-match-clickable {
    cursor: pointer;
    text-decoration: underline;
    text-decoration-color: color-mix(in srgb, var(--text-muted) 45%, transparent);
    text-underline-offset: 2px;
}
.mybets-leg-match-clickable:hover { color: var(--accent-teal-light); }
.mybets-leg-match-clickable:focus-visible { outline: 2px solid var(--accent-odds); outline-offset: 2px; }
.mybets-leg-pick  { font-size: 13px; color: var(--text-secondary); }

.mybets-leg-odd {
    font-size: 15px;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.mybets-legs-msg {
    display: flex;
    justify-content: center;
    padding: 12px;
    font-size: 12px;
}

.mybets-legs-sum {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    padding: 10px 12px;
    border-top: 1px solid var(--bg-hover);
}

.mybets-legs-lbl {
    display: block;
    font-size: 12px;
    color: var(--text-secondary);
}

.mybets-legs-val {
    font-size: 20px;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.mybets-legs-val small { font-size: 11px; color: var(--text-secondary); }

.mybets-legs-actions {
    display: flex;
    border-top: 1px solid var(--bg-hover);
}

.mybets-legs-actions button {
    flex: 1;
    height: 38px;
    background: none;
    border: none;
    border-radius: 0;
    color: var(--text-primary);
    font: inherit;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
}

.mybets-legs-actions button + button { border-left: 1px solid var(--bg-hover); }
.mybets-legs-actions button:hover { background: rgba(var(--bg-deep-rgb), 0.15); }

/* Loading / empty / error states */
.mybets-loading,
.mybets-empty,
.mybets-error {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 48px 20px;
    color: var(--text-muted);
    text-align: center;
    flex: 1;
}

.mybets-error { color: var(--accent-red); }

.mybets-spinner {
    width: 22px;
    height: 22px;
    border: 2px solid rgba(255, 255, 255, 0.15);
    border-top-color: var(--accent-green);
    border-radius: 50%;
    animation: mybetsSpin 0.8s linear infinite;
}

@keyframes mybetsSpin {
    to { transform: rotate(360deg); }
}

/* Back arrow on the detail view */
.mybets-back {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 14px;
    background: transparent;
    border: none;
    color: var(--accent-green);
    font: inherit;
    font-weight: 700;
    cursor: pointer;
}

.mybets-back:hover { color: var(--text-primary); }

.mybets-detail-placeholder {
    padding: 24px 20px;
    color: var(--text-secondary);
    text-align: center;
}

/* ===========================================================
   My Bets — single-ticket detail view
   =========================================================== */
.mybets-detail {
    display: flex;
    flex-direction: column;
    padding: 0 0 16px;
}

.mybets-detail-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 12px 4px;
    border-bottom: 1px solid var(--border-color);
}

.mybets-detail-header .mybets-back { padding: 6px 0; }

.mybets-detail-id {
    padding: 10px 16px 8px;
    font-size: 12px;
    color: var(--text-muted);
}

.mybets-detail-id strong {
    color: var(--text-primary);
    margin-left: 4px;
    font-variant-numeric: tabular-nums;
}

.mybets-selections {
    display: flex;
    flex-direction: column;
    padding: 0 12px;
    gap: 2px;
}

.mybets-selection {
    background: var(--bg-input);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    padding: 10px 12px;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.mybets-sel-match {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.mybets-sel-match-name {
    font-weight: 700;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

.mybets-sel-date {
    font-size: 11px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.mybets-sel-market {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--text-muted);
}

.mybets-sel-row {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 10px;
    align-items: center;
    padding-top: 4px;
    border-top: 1px dashed var(--border-color);
}

.mybets-sel-status {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    color: #fff;
}

.mybets-sel-status-won     { background: var(--accent-green-grad); color: var(--bg-deep); }
.mybets-sel-status-lost    { background: var(--accent-red); }
.mybets-sel-status-pending { background: rgba(var(--accent-teal-rgb), 0.18); color: var(--accent-odds); }

.mybets-sel-pick {
    font-weight: 600;
    color: var(--text-primary);
}

.mybets-sel-odd {
    font-weight: 800;
    color: var(--accent-odds);
    font-variant-numeric: tabular-nums;
}

/* Summary footer */
.mybets-detail-summary {
    margin: 16px 12px 0;
    padding: 12px 14px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.mybets-summary-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 13px;
}

.mybets-summary-lbl { color: var(--text-muted); }
.mybets-summary-val {
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.mybets-summary-row-bold {
    padding-top: 8px;
    border-top: 1px solid var(--border-color);
    font-weight: 700;
}

.mybets-summary-row-bold .mybets-summary-lbl {
    color: var(--text-secondary);
    text-transform: uppercase;
    font-size: 11px;
    letter-spacing: 0.4px;
}

.mybets-summary-row-bold .mybets-summary-val {
    font-size: 15px;
}

.mybets-summary-row-win .mybets-summary-val { color: var(--accent-green); }
/* Potential (not actual) winnings on a lost or still-open ticket: same prominence as the
   payout row, but never the money-green that reads as "you were paid this". */
.mybets-summary-row-potential .mybets-summary-val { color: var(--text-secondary); }

.betslip-empty {
    text-align: center;
    padding: 32px 20px;
    /* #betslip-body is a flex column with align-items: flex-start, so this block
       child shrink-to-fits instead of filling the panel. That left the illustration
       resolving its width against a box barely wider than the longest line of copy
       — 93px inside a 400px panel. Claim the full track first, then centre inside it. */
    width: 100%;
}

.betslip-empty svg {
    margin-bottom: 12px;
}

/* Shared empty-state illustration (betslip + my bets). Intrinsic size is
   152x156; it is capped rather than fixed so the mobile overlay — which is
   narrower than the desktop aside and also has to hold the copy beneath —
   scales it down instead of overflowing. `height: auto` with the width/height
   attributes still on the tag keeps the aspect ratio reserved, so the copy
   below does not jump when the file lands. */
.empty-slip-art {
    display: block;
    /* 100% + a max, NOT min(152px, N%) — a percentage floor is only meaningful
       when the parent has a resolved width, and these empty states live inside
       shrink-to-fit flex children where it does not. */
    width: 100%;
    max-width: 152px;
    height: auto;
    margin: 0 auto 16px;
    /* The art is drawn at full strength for a light ground; on this dark panel
       it would out-shout the message it is introducing. An empty state should
       read as calm, not as an error. */
    opacity: 0.85;
}

.betslip-empty p {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-secondary);
    margin-bottom: 4px;
}

.betslip-empty span {
    font-size: 12px;
    color: var(--text-muted);
}

/* --- Sport SVG Icons --- */
.sport-svg-icon {
    width: 18px;
    height: 18px;
    flex-shrink: 0;
    transition: filter 0.15s;
}

.sidebar-item:hover .sport-svg-icon,
.sidebar-item.active .sport-svg-icon {
    filter: brightness(0) invert(1);
}

.sidebar-loading {
    padding: 12px 16px;
    font-size: 12px;
    color: var(--text-muted);
}

/* --- Language Selector (Login) --- */
.lang-selector {
    display: flex;
    justify-content: center;
    gap: 6px;
    margin-bottom: 24px;
}

.lang-flag-btn {
    width: 36px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-input);
    border: 2px solid transparent;
    border-radius: var(--radius-sm);
    font-size: 16px;
    cursor: pointer;
    transition: all 0.15s;
}

.lang-flag-btn:hover {
    background: var(--bg-hover);
}

.lang-flag-btn.active {
    border-color: var(--accent-green);
    background: var(--bg-tertiary);
}

/* --- Language Selector (Header) --- */
.lang-toggle {
    position: relative;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: var(--radius-sm);
    font-size: 18px;
    transition: background 0.15s;
}

/* Desktop betslip toggle in the header */
.header-betslip-toggle {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
    padding: 0;
}

.header-betslip-toggle:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}

.header-betslip-toggle.has-items {
    color: var(--accent-green);
}

.header-betslip-count {
    position: absolute;
    top: 2px;
    right: 2px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    background: var(--accent-green-grad);
    color: var(--bg-deep);
    border-radius: 999px;
    font-size: 10px;
    font-weight: 800;
    line-height: 16px;
    text-align: center;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}

@media (max-width: 1100px) {
    .header-betslip-toggle {
        display: none;
    }
}

.lang-toggle:hover {
    background: var(--bg-hover);
}

.lang-toggle.lang-toggle-pulse {
    animation: langTogglePulse 1.2s ease;
}

@keyframes langTogglePulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(0, 231, 1, 0); background: var(--bg-hover); }
    30%      { box-shadow: 0 0 0 4px rgba(0, 231, 1, 0.45); background: rgba(0, 231, 1, 0.15); }
    60%      { box-shadow: 0 0 0 8px rgba(0, 231, 1, 0); background: var(--bg-hover); }
}

.lang-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    width: 180px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
    overflow: hidden;
    z-index: 110;
}

.lang-option {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 14px;
    font-size: 13px;
    color: var(--text-secondary);
    transition: all 0.15s;
}

.lang-option:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}

.lang-option.active {
    color: var(--accent-green);
}

/* ==========================================
   BETSLIP CONTENT
   ========================================== */
.bs-content {
    padding: 12px;
    width: 100%;
    max-width: 100%;
    box-sizing: border-box;
    overflow: hidden;
}

.bs-header-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
}

/* .bs-multi-header removed (multi-leg label dropped from the betslip). */

/* ===== Jackpot777 (DEMO) ================================================= */
.bs-jackpot {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0px 0 0px;
    padding: 8px 12px;
    border-radius: var(--radius-dec);
    background: linear-gradient(120deg, var(--bg-green-deep), #103a26);
    border: 1px solid rgba(0, 231, 1, 0.18);
    transition: border-color 0.2s, box-shadow 0.2s;
}
.bs-jackpot.bs-jp-on {
    border-color: rgba(0, 231, 1, 0.55);
    box-shadow: 0 0 0 1px rgba(0, 231, 1, 0.25), 0 0 14px rgba(0, 231, 1, 0.15);
}
/* While a bet is placing / locked, the console can't be toggled or changed. */
.bs-locked .bs-jackpot {
    opacity: 0.55;
    pointer-events: none;
}
.bs-jp-brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 1;
    flex-shrink: 0;
}
.bs-jp-jack {
    font-family: var(--font-display);
    font-weight: 800;
    font-size: 14px;
    letter-spacing: 0.06em;
    color: #ffffff;
}
/* "777" is now three seven-icon PNGs. font-size drives the em-based height so
   each context (console 18px, win overlay 30px) scales automatically. */
.bs-jp-777 {
    display: inline-flex;
    align-items: center;
    font-size: 18px;
    line-height: 0;
}
.jp-7 {
    height: 1.6em;
    width: auto;
    margin: 0 -5px;   /* counter the PNG's transparent padding so the 7s sit close */
    filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.4));
}
/* Small inline sevens used INSIDE sentences ("Match 777 to Win", "777! …"). */
.jp-7.jp-7-inline {
    height: 1.5em;
    margin: 0 -2px;
    vertical-align: -0.42em;   /* sit on the text line */
    filter: none;
}
.bs-jp-info { flex: 1; min-width: 0; }
.bs-jp-line {
    display: flex; align-items: baseline; gap: 6px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bs-jp-tier   { font-size: 11px; font-weight: 700; color: #ffffff; }
.bs-jp-amount { font-size: 11px; font-weight: 700; color: #ffffff; }
.bs-jp-lastwon { font-size: 10px; color: var(--text-muted); margin-top: 1px; }
.bs-jp-i {
    width: 20px; height: 20px; flex-shrink: 0;
    border-radius: 50%; border: 1px solid var(--text-muted);
    background: none; color: var(--text-muted);
    font-style: italic; font-weight: 700; font-size: 12px;
    cursor: pointer; font-family: Georgia, serif;
}
.bs-jp-i:hover { color: #fff; border-color: #fff; }
.bs-jp-toggle {
    width: 42px; height: 23px; flex-shrink: 0;
    border-radius: 999px; background: rgba(255, 255, 255, 0.22);
    position: relative; cursor: pointer; transition: background 0.2s;
}
.bs-jp-toggle::after {
    content: ''; position: absolute; top: 2px; left: 2px;
    width: 19px; height: 19px; border-radius: 50%;
    background: #fff; transition: transform 0.2s;
}
.bs-jp-toggle.active { background: var(--accent-green-grad); }
.bs-jp-toggle.active::after { transform: translateX(19px); }

/* Entry-amount selector (dropdown opens upward — the console sits low in the slip) */
.bs-jp-entry { position: relative; flex-shrink: 0; }
.bs-jp-entry-btn {
    display: flex; align-items: center; gap: 4px;
    padding: 6px 8px; min-width: 62px; justify-content: space-between;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid var(--border-color); border-radius: var(--radius-sm);
    color: var(--text-primary); font-size: 13px; font-weight: 700;
    cursor: pointer; font-family: inherit;
}
.bs-jp-entry-val { white-space: nowrap; }
.bs-jp-entry-chev { transition: transform 0.2s; flex-shrink: 0; }
.bs-jp-entry.open .bs-jp-entry-chev { transform: rotate(180deg); }
.bs-jp-entry-menu {
    display: none; position: absolute; bottom: calc(100% + 4px); right: 0;
    min-width: 84px; z-index: 20;
    background: #1e3f2e; border: 1px solid var(--border-color);
    border-radius: 0; overflow: hidden;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
}
.bs-jp-entry.open .bs-jp-entry-menu { display: block; }
.bs-jp-entry-opt {
    display: block; width: 100%; text-align: left;
    padding: 9px 12px; background: none; border: none;
    color: var(--text-primary); font-size: 13px; font-weight: 600;
    cursor: pointer; font-family: inherit;
}
.bs-jp-entry-opt:hover { background: var(--bg-hover); }
.bs-jp-entry-opt.sel { color: var(--accent-green); }

/* --- 777 reveal (plays on an accepted ticket) --- */
.bs-jp-reveal {
    margin-top: 8px; padding: 10px 12px;
    border-radius: var(--radius-md);
    background: linear-gradient(120deg, var(--bg-green-deep), #0e4a2e);
    border: 1px solid rgba(0, 231, 1, 0.25);
    overflow: hidden;
}
.bs-jp-reveal-head {
    display: flex; justify-content: space-between; align-items: center;
    font-size: 11px; color: var(--text-light); margin-bottom: 8px;
}
.bs-jp-reveal-label b { color: var(--gold); font-family: var(--font-display); }
.bs-jp-reveal-spin {
    font-size: 10px; color: var(--text-muted);
    border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 0; padding: 2px 6px;
}
.bs-jp-reels { display: flex; gap: 8px; justify-content: center; }
.bs-jp-reel {
    --jp-sym-h: 62px;                       /* MUST match SYM_H in betslip.js */
    position: relative; overflow: hidden;
    width: 58px; height: var(--jp-sym-h);
    background: linear-gradient(180deg, #06180f, #0c3120 50%, #06180f);
    border: 1px solid rgba(0, 231, 1, 0.3);
    border-radius: 0;
    box-shadow: inset 0 14px 12px -10px rgba(0, 0, 0, 0.85), inset 0 -14px 12px -10px rgba(0, 0, 0, 0.85);
}
.bs-jp-reel-strip { display: flex; flex-direction: column; will-change: transform; }
.bs-jp-reel-strip.bs-jp-spinning { filter: blur(1.4px); }
.bs-jp-reel-strip.bs-jp-landed { animation: bs-jp-settle 0.28s ease; }
@keyframes bs-jp-settle { 0% { filter: brightness(1.5); } 100% { filter: brightness(1); } }
.bs-jp-sym {
    height: var(--jp-sym-h); flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
}
.bs-jp-sym img {
    width: 42px; height: 42px; object-fit: contain;
    user-select: none; -webkit-user-drag: none;
    filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.5));
}
.bs-jp-reveal-result {
    text-align: center; margin-top: 8px; min-height: 16px;
    font-size: 12px; font-weight: 600; color: var(--text-muted);
}
.bs-jp-reveal.bs-jp-won { border-color: var(--gold); box-shadow: 0 0 18px rgba(245, 197, 24, 0.35); margin-bottom: 5px; }
.bs-jp-reveal.bs-jp-won .bs-jp-reveal-result { color: var(--gold); font-size: 15px; font-weight: 700; }
.bs-jp-reveal.bs-jp-won .bs-jp-reel {
    border-color: var(--gold);
    box-shadow: inset 0 0 14px rgba(245, 197, 24, 0.4), 0 0 12px rgba(245, 197, 24, 0.5);
}

/* --- WIN celebration (user-closable, slot-style count-up) --- */
.bs-jp-win-overlay {
    position: fixed; inset: 0; z-index: 4000;
    display: flex; align-items: center; justify-content: center; padding: 20px;
    background: radial-gradient(circle at 50% 40%, rgba(12, 60, 36, 0.85), rgba(0, 0, 0, 0.9));
    animation: bs-jp-win-fade 0.35s ease;
}
@keyframes bs-jp-win-fade { from { opacity: 0; } to { opacity: 1; } }
.bs-jp-win-card {
    position: relative; overflow: hidden;
    width: min(340px, 90vw); padding: 30px 26px 26px;
    text-align: center; border-radius: 0;
    background: linear-gradient(160deg, #0e3a24, var(--bg-green-deep));
    border: 1px solid var(--gold);
    box-shadow: 0 0 0 1px rgba(245, 197, 24, 0.35), 0 0 60px rgba(245, 197, 24, 0.35), 0 20px 60px rgba(0, 0, 0, 0.6);
    animation: bs-jp-win-pop 0.5s cubic-bezier(0.18, 0.89, 0.32, 1.28);
}
@keyframes bs-jp-win-pop { 0% { transform: scale(0.7); opacity: 0; } 100% { transform: scale(1); opacity: 1; } }
.bs-jp-win-rays {
    position: absolute; top: 50%; left: 50%;
    width: 640px; height: 640px; margin: -320px 0 0 -320px; z-index: 0;
    background: repeating-conic-gradient(from 0deg, rgba(245, 197, 24, 0.14) 0deg 12deg, transparent 12deg 24deg);
    animation: bs-jp-win-spin 14s linear infinite;
    pointer-events: none;
}
@keyframes bs-jp-win-spin { to { transform: rotate(360deg); } }
.bs-jp-win-card > *:not(.bs-jp-win-rays) { position: relative; z-index: 1; }
.bs-jp-win-brand { margin-bottom: 14px; }
.bs-jp-win-brand .bs-jp-jack { font-size: 15px; }
.bs-jp-win-brand .bs-jp-777 { font-size: 30px; }
.bs-jp-win-title {
    font-size: 13px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
    color: var(--text-light); margin-bottom: 10px;
}
.bs-jp-win-amount {
    font-family: var(--font-display); font-weight: 800; font-size: 40px; line-height: 1.05;
    background: linear-gradient(180deg, #fff3bf, var(--gold) 45%, var(--amber));
    -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
    text-shadow: 0 0 24px rgba(245, 197, 24, 0.5);
    animation: bs-jp-win-glow 1.6s ease-in-out infinite;
}
@keyframes bs-jp-win-glow { 0%, 100% { filter: brightness(1); } 50% { filter: brightness(1.25); } }
.bs-jp-win-collect {
    margin-top: 22px; width: 100%; padding: 13px 0;
    border: none; border-radius: 0; cursor: pointer;
    font-family: var(--font-display); font-weight: 800; font-size: 16px; letter-spacing: 0.04em;
    color: #06210f;
    background: linear-gradient(180deg, var(--gold), var(--amber));
    box-shadow: 0 6px 18px rgba(245, 197, 24, 0.35);
}
.bs-jp-win-collect:hover { filter: brightness(1.08); }
.bs-jp-win-collect:active { transform: translateY(1px); }

/* --- T&C modal --- */
.bs-jp-terms-overlay {
    position: fixed; inset: 0; z-index: 3000;
    background: rgba(0, 0, 0, 0.6);
    display: flex; align-items: center; justify-content: center; padding: 20px;
}
.bs-jp-terms-modal {
    max-width: 480px; width: 100%; max-height: 85vh; overflow-y: auto;
    background: linear-gradient(160deg, #0e4a2e, var(--bg-green-deep));
    border: 1px solid rgba(0, 231, 1, 0.3); border-radius: var(--radius-lg);
    padding: 24px; color: var(--text-light); position: relative;
}
.bs-jp-terms-close {
    position: absolute; top: 12px; right: 14px;
    background: none; border: none; color: #fff; font-size: 26px; cursor: pointer; line-height: 1;
}
.bs-jp-terms-brand {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-bottom: 8px;
}
.bs-jp-terms-modal h3 { text-align: center; color: #fff; margin: 4px 0 14px; }
.bs-jp-terms-modal p { font-size: 13px; line-height: 1.5; margin: 0 0 12px; }
.bs-jp-terms-modal ol { font-size: 13px; line-height: 1.5; padding-left: 18px; margin: 0 0 12px; }
.bs-jp-terms-modal li { margin-bottom: 8px; }
.bs-jp-terms-demo { font-size: 11px; color: var(--gold); text-align: center; font-style: italic; }

.bs-clear-all {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 6px 10px;
    background: none;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    transition: all 0.15s;
}

.bs-clear-all:hover {
    color: var(--accent-red);
    border-color: var(--accent-red);
}

.bs-multi-icon {
    font-size: 16px;
}

/* Wrapper hosts the top/bottom scroll cues; the inner .bs-selections scrolls. */
.bs-selections-wrap {
    position: relative;
    display: flex;
    flex-direction: column;
    min-height: 0;
    margin-bottom: 12px;
}
.bs-selections {
    display: flex;
    flex-direction: column;
    gap: 3px;
    max-height: calc(100dvh - 380px);
    overflow-y: auto;
}

/* Fade + chevron shown at an edge only when there's more list in that direction.
   `--bg-secondary` matches the panel behind the cards so the fade blends. */
.bs-selections-wrap::before,
.bs-selections-wrap::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    height: 30px;
    z-index: 4;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s ease;
}
.bs-selections-wrap::before {
    top: 0;
    background:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='none' stroke='%23cfd8e2' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='18 15 12 9 6 15'/%3E%3C/svg%3E") no-repeat center top 3px,
        linear-gradient(to bottom, var(--bg-secondary) 35%, transparent);
}
.bs-selections-wrap::after {
    bottom: 0;
    background:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='none' stroke='%23cfd8e2' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") no-repeat center bottom 3px,
        linear-gradient(to top, var(--bg-secondary) 35%, transparent);
}
.bs-selections-wrap.can-scroll-up::before { opacity: 1; }
.bs-selections-wrap.can-scroll-down::after { opacity: 1; }

/* Swipe-to-delete: each selection sits on a row that clips the slide and hosts a
   red × panel behind it. The row shares the card background so a mid-scroll odds
   flash (which briefly makes .bs-selection semi-transparent) shows the card colour,
   not the red panel — which stays display:none until a swipe starts. */
.bs-sel-row {
    position: relative;
    overflow: hidden;
    border-radius: var(--radius-lg);
    background: var(--bg-tertiary);
    /* CRITICAL: overflow:hidden resolves this flex item's auto min-height to 0, so
       in the flex-column list the rows would SHRINK to fit (clipping each card's
       value/odds) instead of the container scrolling. Pin it so the list scrolls. */
    flex-shrink: 0;
    /* Vertical panning stays native (list scroll); horizontal is owned by the
       swipe-to-delete JS. Must be pan-y, not bare pan-x — see mobile-drift notes. */
    touch-action: pan-y;
}
.bs-sel-delete {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    display: none;
    align-items: center;
    justify-content: flex-end;
    padding-right: 30px;
    border: 0;
    background: var(--accent-red, #c0392b);
    color: #fff;
    cursor: pointer;
}
.bs-sel-row.bs-swipe-active .bs-sel-delete { display: flex; }

.bs-selection {
    position: relative;
    z-index: 1;
    padding: 10px 12px;
    background: var(--bg-tertiary);
    border-radius: var(--radius-lg);
    transition: transform 0.25s cubic-bezier(0.22, 0.61, 0.36, 1);
    will-change: transform;
    /* border-left: 3px solid var(--accent-blue); */
}

.bs-sel-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: -5px;
}

.bs-sel-match {
    font-size: 12px;
    color: var(--text-muted);
    line-height: 20px;
    /* Holds the live badge + the name; min-width:0 so the name can ellipsize instead of
       stretching the header (see the grid/flex min-width:0 rule elsewhere in this file). */
    display: flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
}

.bs-sel-match-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Clickable only when we know which match to open (origin captured at click time). */
.bs-sel-match-link {
    cursor: pointer;
    transition: color 0.15s;
}

.bs-sel-match-link:hover .bs-sel-match-name,
.bs-sel-match-link:focus-visible .bs-sel-match-name {
    color: var(--text-primary);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.bs-sel-match-link:focus-visible {
    /* --accent-green is a GRADIENT; use the solid neon token for color/outline values. */
    outline: 2px solid var(--accent-green-neon);
    outline-offset: 2px;
    border-radius: 0;
}

/* Live marker on a selection — distinguishes an in-play bet from a pre-match one.
   The shared .live-waves svg is 26x22 for the live pages; scale it to sit on a 12px
   line here (viewBox is 12x9, so keep roughly that ratio). Animation is inherited. */
.bs-sel-live {
    flex-shrink: 0;
    /* Solid token, NOT --accent-green (that one is a linear-gradient, invalid for `color`,
       which is why the shared .live-waves rule silently inherits its parent's colour). */
    color: var(--live-indicator-red);
}

.bs-sel-live svg {
    width: 15px;
    height: 11px;
}

.bs-sel-remove {
    flex-shrink: 0;
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    padding: 2px;
    transition: color 0.15s;
}

.bs-sel-remove:hover {
    color: var(--accent-red);
}

.bs-sel-market {
    font-size: 13px;
    font-weight: 700;
    color: var(--text-muted);
    margin-bottom: 0px;
}

.bs-sel-bottom {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.bs-sel-value {
    font-size: 15px;
    font-weight: 800;
    color: var(--text-primary);
}

.bs-sel-koefi {
    font-size: 15px;
    font-weight: 800;
    color: var(--accent-blue-ligth);
}

.bs-totals {
    padding: 5px 0;
    /* border-top: 1px solid var(--border-color); */
    margin-bottom: 0px;
}

.bs-total-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-muted);
}

.bs-total-odds {
    font-size: 16px;
    font-weight: 800;
    color: var(--accent-green);
}

/* ===== System bets (Doubles / Trebles / N-Folds) ======================== */
/* Offered as soon as three selections make a system possible. One row per k, each
   showing C(n,k) as an "Nx" badge; the row selects, its name button explains. */
/* Sits where the odd would be on a suspended pick — the teams, market and selection
   all stay legible so the punter can see which bet went down and decide about it. */
/* What the account will accept, stated under the stake box before anything is typed,
   and turned into the reason the Place button is off once it is breached. */
.bs-stake-limit {
    font-size: 11px;
    color: var(--text-muted);
    padding: 2px 4px 4px;
}

.bs-stake-limit-bad { color: var(--accent-red, #e9113c); font-weight: 600; }

/* A pick whose odd the feed no longer offers, but whose teams/market/pick we still
   know. It sits in the odds slot — narrow and right-aligned — so it is a padlock, not
   a sentence; the wording lives in the title. Red rather than the suspended-odd amber,
   to keep "this leg is gone" distinct from "this price is temporarily locked". */
.bs-sel-gone-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--accent-red, #ed4163);
    color: #fff;
    flex: 0 0 auto;
}

/* `.bs-sel-invalid` alone is a tombstone: half-opacity with the name struck through,
   which was right when the row said nothing but "no longer available". Now that it
   carries real content, that treatment made it look broken — the name is information,
   not something to cross out. Keep the red accent, drop the crossing-out, and dim the
   inner text instead of the whole card so it stays readable. */
.bs-selection.bs-sel-invalid.bs-sel-gone {
    opacity: 1;
    background: rgba(237, 65, 99, 0.06);
}

.bs-sel-invalid.bs-sel-gone .bs-sel-match {
    text-decoration: none;
}

.bs-sel-invalid.bs-sel-gone .bs-sel-match,
.bs-sel-invalid.bs-sel-gone .bs-sel-market,
.bs-sel-invalid.bs-sel-gone .bs-sel-value {
    opacity: 0.7;
}

.bs-systems {
    margin: 4px 0 10px;
    border-top: 1px solid var(--border-color);
    padding-top: 10px;
}

/* Collapsed until asked for, like the legacy slip. */
.bs-systems-toggle {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 0;
    background: none;
    border: none;
    font: inherit;
    cursor: pointer;
    text-align: left;
}

.bs-systems-title {
    font-size: 12px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--text-muted);
}

/* Names the staked system while the list is shut, so collapsing hides the rows
   but never the choice. */
.bs-systems-active {
    font-size: 12px;
    font-weight: 700;
    color: var(--accent-green);
}

.bs-systems-chev {
    margin-left: auto;
    color: var(--text-muted);
    flex-shrink: 0;
    transition: transform 0.2s;
}

.bs-systems.is-open .bs-systems-chev { transform: rotate(180deg); }

.bs-systems-list {
    display: none;
    flex-direction: column;
    gap: 4px;
    /* Twenty selections yield eighteen system rows — scroll rather than push the
       stake input and Place button off the panel. */
    max-height: 190px;
    overflow-y: auto;
    margin-top: 8px;
}

.bs-systems.is-open .bs-systems-list { display: flex; }

.bs-sys-row-pick {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 7px 10px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-dec);
    background: var(--bg-input);
    cursor: pointer;
    transition: border-color 0.15s, background-color 0.15s;
}

@media (hover: hover) {
    .bs-sys-row-pick:hover { border-color: var(--text-muted); }
}

.bs-sys-row-pick.bs-sys-active {
    border-color: var(--accent-green);
    background: color-mix(in srgb, var(--accent-green) 12%, var(--bg-input));
}

/* A button so it is reachable by keyboard and screen readers — the explainer is
   real content, not decoration. Styled flat so it reads as the row's label. */
.bs-sys-name {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    font-weight: 700;
    font-size: 13px;
    color: var(--text-primary);
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
    text-align: left;
    min-width: 0;
}

.bs-sys-combos {
    font-size: 12px;
    font-weight: 700;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}

/* "10x" sitting inside the stake field: the input holds the PER-COMBINATION stake,
   this is what it gets multiplied by. */
.bs-stake-multiplier {
    font-size: 12px;
    font-weight: 700;
    color: var(--accent-green);
    background: color-mix(in srgb, var(--accent-green) 15%, transparent);
    padding: 2px 6px;
    border-radius: 0;
    flex-shrink: 0;
    font-variant-numeric: tabular-nums;
}

/* Total-stake and min-return lines, shown only in system mode. */
.bs-payout-row.bs-sys-row {
    font-size: 12px;
    color: var(--text-muted);
}

/* ---- explainer modal ---- */
.bs-sysm-backdrop {
    position: fixed;
    inset: 0;
    z-index: 10000;
    background: rgba(0, 0, 0, 0.6);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
}

.bs-sysm {
    background: var(--bg-secondary, var(--bg-secondary));
    border: 1px solid var(--border-color);
    border-radius: var(--radius-dec);
    width: min(460px, 100%);
    /* dvh, not vh — the iOS URL bar doesn't shrink vh and the footer would clip. */
    max-height: min(80dvh, 640px);
    display: flex;
    flex-direction: column;
}

.bs-sysm-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 14px 16px 0;
}

.bs-sysm-head h3 {
    margin: 0;
    font-size: 17px;
    font-weight: 800;
    color: var(--text-primary);
}

.bs-sysm-close {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 26px;
    line-height: 1;
    cursor: pointer;
    padding: 0 4px;
}

.bs-sysm-lead {
    margin: 8px 16px 12px;
    font-size: 13px;
    color: var(--text-secondary);
}

.bs-sysm-scroll {
    overflow-y: auto;
    padding: 0 16px;
    flex: 1;
    min-height: 0;
}

.bs-sysm-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}

.bs-sysm-table th {
    text-align: right;
    font-weight: 600;
    color: var(--text-muted);
    padding: 6px 0;
    position: sticky;
    top: 0;
    background: var(--bg-secondary, var(--bg-secondary));
}

.bs-sysm-table td {
    text-align: right;
    padding: 5px 0;
    color: var(--text-primary);
    border-top: 1px solid var(--border-color);
}

.bs-sysm-table th:first-child,
.bs-sysm-table td.bs-sysm-ids { text-align: left; color: var(--text-secondary); }
.bs-sysm-table td.bs-sysm-ret { color: var(--accent-green); font-weight: 700; }

.bs-sysm-note,
.bs-sysm-foot {
    font-size: 11px;
    color: var(--text-muted);
    padding: 10px 0;
}

.bs-sysm-foot {
    padding: 10px 16px 14px;
    border-top: 1px solid var(--border-color);
}

.bs-stake {
    margin-bottom: 0px;
}

.bs-stake-input-wrap {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 5px 12px;
    background: var(--bg-input);
    border: 2px solid var(--border-color);
    border-radius: var(--radius-dec);
    margin-bottom: 8px;
    transition: border-color 0.2s;
}

.bs-stake-input-wrap:focus-within {
    border-color: var(--accent-green);
}

.bs-stake-currency {
    font-size: 20px;
    font-weight: 600;
    color: var(--text-muted);
}

.bs-stake-input {
    flex: 1;
    background: none;
    border: none;
    color: var(--text-primary);
    font-size: 20px;
    font-weight: 600;
    font-family: inherit;
    min-width: 0;
}

.bs-stake-input::placeholder {
    color: var(--text-muted);
}

/* Remove number input arrows */
.bs-stake-input::-webkit-outer-spin-button,
.bs-stake-input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* ===== Custom betslip numeric keyboard (touch devices only) =====
   Fixed-bottom panel that takes over from the native keyboard so the layout
   matches the rest of the app and includes quick-add pills + remember toggle
   + place-bet shortcut. Slides up on show. Markup lives once in index.html. */
.bs-keyboard {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    padding-bottom: env(safe-area-inset-bottom, 0px);   /* clear the home indicator */
    z-index: 1100;
    background: #1a1a1a;
    color: #fff;
    border-top-left-radius: 0;
    border-top-right-radius: 0;
    box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.5);
    user-select: none;
    -webkit-user-select: none;
    /* Native-keyboard-style slide. Transform-based (not a display-toggled
       keyframe) so it eases smoothly BOTH ways and repeated _kbShow() calls
       (touchstart + click + focus all fire on one tap) don't restart it —
       that re-trigger was the "fap fap" jank. Docked state is set by
       body.bs-keyboard-open; JS toggles display for a11y/layout only. */
    transform: translateY(100%);
    transition: transform 0.3s cubic-bezier(0.22, 0.61, 0.36, 1);
    will-change: transform;
    /* iOS home-bar gap. Without this, the bottom row sits under the indicator. */
    padding-bottom: env(safe-area-inset-bottom, 0);
}
body.bs-keyboard-open .bs-keyboard { transform: translateY(0); }

/* Header: full-width green Place-bet shortcut. The current stake lives in
   the slip body above (its stake input stays visible while the keyboard is
   open and updates live as the user types).
   The 10px dark strip above the button is a deliberate DEAD ZONE: the Place
   button docks flush under the slip's stake input, so this buffer absorbs
   taps that land on the input/keyboard boundary instead of placing a bet. */
.bs-kb-header {
    display: flex;
    align-items: stretch;
    height: 60px;
    margin-top: 5px;
}
.bs-kb-place {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    background: var(--accent-green-grad);
    color: var(--bg-green-deep);
    border: 0;
    font-size: 15px;
    font-weight: 800;
    text-transform: capitalize;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, opacity 0.15s;
}
/* Stake sum shown next to the label; hidden (removed from flow) when there's no stake. */
.bs-kb-place-amount:empty { display: none; }
/* Jackpot777 entry (the "+777" addition) — the 777 mark STACKED over "+<entry>", matching
   the stake-row badge. Shown only when opted in (:empty hides it otherwise). The sevens keep
   their red; "+entry" inherits the button's dark text for contrast on the green. */
.bs-kb-place-jp {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    line-height: 1;
    gap: 2px;
}
.bs-kb-place-jp:empty { display: none; }
.bs-kb-place-jp-777 { display: inline-flex; align-items: center; line-height: 0; }
.bs-kb-place-jp .jp-7.jp-7-inline { height: 1em; margin: 0 -3px; vertical-align: middle; filter: none; }
.bs-kb-place-jp-add { font-weight: 800; font-size: 0.8em; line-height: 1; text-transform: none; }
.bs-kb-place:not(:disabled):hover,
.bs-kb-place:not(:disabled):active {
    background:var(--accent-green-neon);
}
.bs-kb-place:disabled,
.bs-kb-place.bs-place-disabled {
    background: #555;
    color: #aaa;
    opacity: 0.85;
    cursor: not-allowed;
}

/* Quick-add pills — preset stake amounts. */
.bs-kb-quick {
    display: flex;
    background: #fff;
    border-top: 1px solid #ddd;
}
.bs-kb-quick button {
    flex: 1;
    padding: 14px 0;
    background: #fff;
    color: #000;
    border: 0;
    border-right: 1px solid #e5e5e5;
    font-weight: 700;
    font-size: 14px;
    cursor: pointer;
}
.bs-kb-quick button:last-child { border-right: 0; }
.bs-kb-quick button:active { background: #ededed; }

/* 3x4 numpad. */
.bs-kb-numpad {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    background: #fff;
}
.bs-kb-numpad button {
    padding: 18px 0;
    background: #fff;
    color: #000;
    border: 0;
    border-right: 1px solid #eee;
    border-top: 1px solid #eee;
    font-weight: 700;
    font-size: 24px;
    cursor: pointer;
    /* `data-key=backspace` shows the SVG; centre it. */
    display: flex;
    align-items: center;
    justify-content: center;
}
.bs-kb-numpad button:nth-child(3n) { border-right: 0; }
.bs-kb-numpad button:active { background: #ededed; }
.bs-kb-back { color: #444; }

/* Footer: remember-bet toggle on left, Done on right. */
.bs-kb-footer {
    display: flex;
    background: #fff;
    border-top: 1px solid #eee;
}
.bs-kb-remember,
.bs-kb-clear,
.bs-kb-done {
    flex: 1;
    padding: 15px 15px;
    background: transparent;
    border: 0;
    color: #000;
    font-weight: 600;
    font-size: 14px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-width: 0;
}
/* Equal thirds (like the numpad cells), with light dividers between them. */
.bs-kb-clear,
.bs-kb-done {
    border-left: 1px solid #eee;
}
.bs-kb-clear {
    color: #c0392b;   /* muted red — signals it wipes the amount */
    font-weight: 700;
}
.bs-kb-clear:active {
    background: #f6eceb;
}
.bs-kb-done {
    font-weight: 800;
}
.bs-kb-remember .bs-kb-toggle {
    width: 30px;
    height: 18px;
    border-radius: 9px;
    background: #ccc;
    position: relative;
    transition: background 0.15s;
}
.bs-kb-remember .bs-kb-toggle::after {
    content: '';
    position: absolute;
    top: 2px;
    left: 2px;
    width: 14px;
    height: 14px;
    background: #fff;
    border-radius: 50%;
    transition: transform 0.15s;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.bs-kb-remember.active .bs-kb-toggle {
    background: var(--accent-green-grad);
}
.bs-kb-remember.active .bs-kb-toggle::after {
    transform: translateX(12px);
}

/* Approximate keyboard height — header 52 + quick 46 + numpad 60×4 + footer
   46 + safe-area ≈ 384–420 px. Tuned for iPhone landscape/portrait. Tweakable
   from one place if button paddings change. */
:root {
    /* Includes the 10px dead-zone strip above the Place button (.bs-kb-header margin-top). */
    --bs-keyboard-height: calc(355px + env(safe-area-inset-bottom, 0px));
}
@media (max-height: 700px) {
    :root { --bs-keyboard-height: calc(370px + env(safe-area-inset-bottom, 0px)); }
}

/* When the keyboard is open, treat the slip + keyboard as a single connected
   block. We do this by SHRINKING the overlay container so its `align-items:
   flex-end` naturally docks the panel right above the keyboard, instead of
   stretching the panel and pushing its top off-screen. The internal scroll
   stays inside `.bs-selections` only — overlay-body keeps overflow:hidden. */
body.bs-keyboard-open .betslip-overlay {
    height: calc(100dvh - var(--header-bar) - var(--bs-keyboard-height));
}
body.bs-keyboard-open .betslip-overlay-panel {
    /* Fill the now-shorter overlay; selections list inside still scrolls. */
    max-height: 100%;
    /* Square the bottom corners so the slip "docks" onto the keyboard. */
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
}
/* Stretch the overlay-body child so .bs-content gets a definite height. The
   default `align-items: flex-start` collapses bs-content to its content
   height, which means `flex: 1` on .bs-selections has nothing to push
   against — the selections list grows past the panel, shoving Kuota Totale
   and the stake row off the bottom behind the keyboard. With stretch, the
   selections list scrolls inside a fixed-height bs-content and the totals
   + stake row stay pinned at the bottom. */
body.bs-keyboard-open .betslip-overlay-body {
    align-items: stretch;
    min-height: 0;
}
body.bs-keyboard-open .betslip-overlay-body .bs-content {
    /* Compute against the actual viewport space available: the overlay was
       shrunk by header + keyboard, the panel header eats another 50px. */
    max-height: calc(100dvh - var(--header-bar) - var(--bs-keyboard-height) - 50px);
    height: 100%;
}

/* While the keyboard is open, the keyboard handles place-bet + remember-bet,
   so hide those duplicates in the slip body. The stake INPUT stays visible —
   it's the live readout of what the user is typing on the keyboard. */
body.bs-keyboard-open .betslip-overlay-body .bs-remember-toggle,
body.bs-keyboard-open .betslip-overlay-body .bs-place-btn,
body.bs-keyboard-open .betslip-overlay-body .bs-stake-limit,
body.bs-keyboard-open .betslip-overlay-body .bs-reoffer-btns {
    display: none;
}
/* Stake input now spans the full row (no Remember toggle next to it). */
body.bs-keyboard-open .betslip-overlay-body .bs-stake-input-wrap {
    flex: 1;
    width: 100%;
}

/* Square the keyboard's TOP corners when it's docked under the betslip so
   slip + keyboard look like one continuous panel (slip bottom is already
   squared by the rule above). The standalone keyboard (no slip open above)
   keeps its rounded top corners. */
body.betslip-open.bs-keyboard-open .bs-keyboard {
    border-top-left-radius: 0;
    border-top-right-radius: 0;
}

.bs-stake-input[type=number] {
    /* Hide the number-input spinners. Firefox uses `-moz-appearance: textfield`;
       Chromium/Safari read the standard `appearance` (84+) and also strip spinners via the
       webkit pseudo-element below. */
    -moz-appearance: textfield;
    appearance: textfield;
}
.bs-stake-input[type=number]::-webkit-outer-spin-button,
.bs-stake-input[type=number]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

.bs-stake-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}

.bs-stake-row .bs-stake-input-wrap {
    flex: 1;
    margin-bottom: 0;
}

/* Jackpot entry badge in the stake row — "777 +€0.10", the extra charged on top
   of the stake when the jackpot is opted in. Hidden until active (`.on`). */
.bs-stake-jp {
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    flex-shrink: 0;
}
.bs-stake-jp.on {
    display: flex;
}
/* The Place button now carries the stacked 777 "+entry" everywhere — the on-screen keyboard's
   button on mobile-keyboard-open, and the slip's own button on desktop + mobile-keyboard-closed
   — so the stake-row badge is redundant. Hide it (kept in the render for easy revert). */
.bs-stake-jp,
.bs-stake-jp.on { display: none !important; }
.bs-stake-jp-badge {
    display: inline-flex;
    align-items: center;
    line-height: 0;
}
.bs-stake-jp-badge .jp-7 {
    height: 20px;
    width: auto;
    margin: 0 -5px;
}
.bs-stake-jp-add {
    font-size: 12px;
    font-weight: 700;
    line-height: 1;
    white-space: nowrap;
    color: var(--accent-green);
}

.bs-remember-toggle {
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
}

.bs-remember-label {
    font-size: 10px;
    color: var(--text-muted);
    white-space: nowrap;
}

.bs-toggle-pill {
    width: 34px;
    height: 18px;
    background: var(--bg-hover);
    border-radius: 9px;
    position: relative;
    transition: background 0.2s;
}

.bs-toggle-pill::after {
    content: '';
    position: absolute;
    top: 2px;
    left: 2px;
    width: 14px;
    height: 14px;
    background: var(--text-muted);
    border-radius: 50%;
    transition: all 0.2s;
}

.bs-toggle-pill.active {
    background: var(--accent-green-grad);
}

.bs-toggle-pill.active::after {
    left: 18px;
    background: var(--bg-deep);
}

.bs-payout-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 13px;
    color: var(--text-muted);
    padding: 0 4px;
    font-weight: 700;
    margin-bottom: 8px;
}

.bs-payout-value {
    font-weight: 700;
    color: var(--accent-green);
}

.bs-place-btn {
    width: 100%;
    padding: 14px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    background: var(--accent-green-grad);
    color: var(--bg-deep);
    font-size: 15px;
    font-weight: 700;
    border: none;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: opacity 0.2s;
    font-family: inherit;
}
/* Slip Place button content — stake sum + stacked 777 "+entry", mirroring the on-screen
   keyboard's Place button so DESKTOP (no keyboard) shows the same. */
.bs-pb-jp { display: inline-flex; flex-direction: column; align-items: center; justify-content: center; line-height: 1; gap: 2px; }
.bs-pb-jp-777 { display: inline-flex; align-items: center; line-height: 0; }
.bs-pb-jp .jp-7.jp-7-inline { height: 1em; margin: 0 -3px; vertical-align: middle; filter: none; }
.bs-pb-jp-add { font-weight: 800; font-size: 0.8em; line-height: 1; }

.bs-place-btn:hover {
    opacity: 0.9;
}

/* Bet result message — inline above button */
.bs-result-area {
    min-height: 0;
}

.bs-result {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    border-radius: var(--radius-md);
    margin-bottom: 8px;
    animation: bsResultIn 0.3s ease;
}

.bs-result svg {
    flex-shrink: 0;
}

.bs-result p {
    font-size: 13px;
    font-weight: 600;
    line-height: 1.3;
}

.bs-result-success {
    background: rgba(0, 231, 1, 0.1);
    border: 1px solid var(--accent-green);
    color: var(--accent-green);
}

.bs-result-success svg {
    stroke: var(--accent-green);
}

.bs-result-error {
    background: rgba(237, 65, 99, 0.1);
    border: 1px solid var(--accent-red);
    color: var(--accent-red);
}

.bs-result-error svg {
    stroke: var(--accent-red);
}

@keyframes bsResultIn {
    from {
        opacity: 0;
        transform: translateY(-10px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

/* Place bet pending state — neon-green shimmer (matches the new --accent-green-neon
   used across the greenish accents: jackpot console, toggles, win amounts, etc.). */
.bs-place-btn.bs-placing {
    background: linear-gradient(90deg, var(--accent-green-neon) 0%, #eafcc9 50%, var(--accent-green-neon) 100%);
    background-size: 200% 100%;
    animation: bsPlacingSlide 1.5s ease-in-out infinite;
    color: var(--bg-deep);
    pointer-events: none;
}

@keyframes bsPlacingSlide {
    0% {
        background-position: 100% 0;
    }

    100% {
        background-position: -100% 0;
    }
}

/* Pending spinner overlay on betslip */
.bs-pending-overlay {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    padding: 16px;
    background: rgba(0, 231, 1, 0.06);
    border: 1px solid rgba(0, 231, 1, 0.2);
    border-radius: var(--radius-md);
    margin-bottom: 12px;
}

.bs-btn-spinner {
    display: inline-block;
    width: 18px;
    height: 18px;
    border: 2px solid rgba(var(--bg-deep-rgb), 0.3);
    border-top-color: var(--bg-deep);
    border-radius: 50%;
    vertical-align: middle;
    margin-right: 6px;
    -webkit-animation: bsSpin 0.8s linear infinite;
    animation: bsSpin 0.8s linear infinite;
}

.bs-pending-spinner {
    width: 24px;
    height: 24px;
    border: 3px solid var(--border-color);
    border-top-color: var(--accent-green);
    border-radius: 50%;
    -webkit-animation: bsSpin 0.8s linear infinite;
    animation: bsSpin 0.8s linear infinite;
    flex-shrink: 0;
}

@-webkit-keyframes bsSpin {
    to {
        -webkit-transform: rotate(360deg);
        transform: rotate(360deg);
    }
}

@keyframes bsSpin {
    to {
        transform: rotate(360deg);
    }
}

.bs-pending-text {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-secondary);
}

/* Full-screen "still confirming your bet" overlay shown after a reload that
   happened mid-placement (the waiting state is restored + long-polled). */
.bs-resume-overlay {
    position: fixed;
    inset: 0;
    z-index: 3500;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(var(--bg-primary-rgb), 0.72);
    -webkit-backdrop-filter: blur(3px);
    backdrop-filter: blur(3px);
}
.bs-resume-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 16px;
    padding: 28px 34px;
    border-radius: 0;
    background: linear-gradient(180deg, var(--bg-secondary), var(--bg-secondary));
    border: 1px solid rgba(255, 255, 255, 0.08);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
    max-width: 88vw;
}
.bs-resume-text {
    color: #fff;
    font-weight: 700;
    font-size: 15px;
    text-align: center;
}

/* Re-offer UI */
.bs-reoffer-msg {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    background: rgba(255, 140, 0, 0.1);
    border: 1px solid var(--accent-orange);
    border-radius: var(--radius-md);
    margin-bottom: 8px;
    color: var(--accent-orange);
    font-size: 13px;
    font-weight: 600;
}

.bs-reoffer-msg svg {
    stroke: var(--accent-orange);
    flex-shrink: 0;
}

.bs-reoffer-btns {
    display: flex;
    gap: 8px;
}

.bs-reoffer-decline {
    flex: 1;
    padding: 12px;
    background: var(--bg-tertiary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-secondary);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    transition: all 0.15s;
}

.bs-reoffer-decline:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}

.bs-reoffer-accept {
    flex: 2;
    padding: 12px;
    background: var(--accent-green-grad);
    border: none;
    border-radius: var(--radius-md);
    color: var(--bg-deep);
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    font-family: inherit;
    transition: opacity 0.15s;
}

.bs-reoffer-accept:hover {
    opacity: 0.9;
}

/* Re-offered odds display */
.bs-sel-koefi-old {
    font-size: 12px;
    color: var(--text-muted);
    text-decoration: line-through;
    margin-right: 6px;
}

.bs-koefi-changed {
    color: var(--accent-orange);
    animation: koefiPulseReoffer 2s ease infinite;
}

@keyframes koefiPulseReoffer {

    0%,
    100% {
        color: var(--accent-orange);
    }

    50% {
        color: #ffb84d;
    }
}

.bs-selection.bs-sel-reoffered {
    border-left-color: var(--accent-orange);
    background: rgba(255, 140, 0, 0.05);
}

/* `:not(.bs-placing)` so a button that is BOTH placing and disabled (a selection
   went invalid mid-confirmation) keeps the green placing shimmer instead of this
   grey overriding it — that made the Place button look broken while waiting. */
.bs-place-btn.bs-place-disabled:not(.bs-placing) {
    background: var(--bg-hover);
    color: var(--text-muted);
    cursor: not-allowed;
}

/* Invalid selection (odd no longer available) */
.bs-selection.bs-sel-invalid {
    border-left-color: var(--accent-red);
    opacity: 0.5;
    background: rgba(237, 65, 99, 0.05);
}

.bs-sel-invalid .bs-sel-match {
    text-decoration: line-through;
}

/* Odds change animations — card background */
.bs-selection.odds-up {
    animation: oddsFlashUp 2s ease;
}

.bs-selection.odds-down {
    animation: oddsFlashDown 2s ease;
}

@keyframes oddsFlashUp {
    0% {
        background: var(--bg-tertiary);
    }

    15% {
        background: rgba(0, 231, 1, 0.2);
        border-left-color: var(--accent-green);
    }

    50% {
        background: rgba(0, 231, 1, 0.1);
    }

    100% {
        background: var(--bg-tertiary);
    }
}

@keyframes oddsFlashDown {
    0% {
        background: var(--bg-tertiary);
    }

    15% {
        background: rgba(237, 65, 99, 0.2);
        border-left-color: var(--accent-red);
    }

    50% {
        background: rgba(237, 65, 99, 0.1);
    }

    100% {
        background: var(--bg-tertiary);
    }
}

/* Odds value flash — the number itself */
.bs-sel-koefi.koefi-flash-up {
    animation: koefiPulseUp 2.5s ease;
}

.bs-sel-koefi.koefi-flash-down {
    animation: koefiPulseDown 2.5s ease;
}

@keyframes koefiPulseUp {
    0% {
        color: var(--accent-blue);
    }

    10% {
        color: var(--bg-deep);
        background: var(--accent-green-grad);
        border-radius: 0;
        padding: 2px 6px;
    }

    40% {
        color: var(--bg-deep);
        background: var(--accent-green-grad);
        border-radius: 0;
        padding: 2px 6px;
    }

    100% {
        color: var(--accent-blue);
        background: transparent;
        padding: 0;
    }
}

@keyframes koefiPulseDown {
    0% {
        color: var(--accent-blue);
    }

    10% {
        color: #fff;
        background: var(--accent-red);
        border-radius: 0;
        padding: 2px 6px;
    }

    40% {
        color: #fff;
        background: var(--accent-red);
        border-radius: 0;
        padding: 2px 6px;
    }

    100% {
        color: var(--accent-blue);
        background: transparent;
        padding: 0;
    }
}

/* --- Page Placeholder --- */
.page-placeholder {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 80px 20px;
    text-align: center;
}

.page-placeholder svg {
    margin-bottom: 16px;
    opacity: 0.5;
}

.page-placeholder h2 {
    font-size: 22px;
    font-weight: 700;
    margin-bottom: 8px;
    color: var(--text-primary);
}

.page-placeholder p {
    font-size: 14px;
    color: var(--text-muted);
}

/* ==========================================
   BETTING EXCHANGE — coming-soon advertisement
   ========================================== */
.exchange-hero {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 56px 20px;
    min-height: 60vh;
}

.exchange-hero-inner {
    position: relative;
    width: 100%;
    max-width: 620px;
    padding: 48px 40px;
    text-align: center;
    border-radius: 0;
    border: 1px solid rgba(255, 255, 255, 0.08);
    /* Dark green-tinted panel with a subtle floodlight glow at the top. */
    background:
        radial-gradient(120% 90% at 50% 0%, rgba(0, 231, 1, 0.14) 0%, rgba(0, 231, 1, 0) 55%),
        linear-gradient(160deg, #123127 0%, #0a1f18 55%, var(--bg-primary) 100%);
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
    overflow: hidden;
}

.exchange-hero-inner::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: linear-gradient(90deg, transparent, var(--accent-green) 50%, transparent);
}

.exchange-badge {
    display: inline-block;
    padding: 5px 14px;
    background: var(--accent-green-grad);
    color: #06210b;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.12em;
    border-radius: 999px;
    margin-bottom: 22px;
}

.exchange-hero-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 76px;
    height: 76px;
    margin: 0 auto 20px;
    border-radius: 50%;
    color: var(--accent-green);
    background: rgba(0, 231, 1, 0.1);
    border: 1px solid rgba(0, 231, 1, 0.25);
}

.exchange-title {
    font-size: 16px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin: 0 0 10px;
}

.exchange-slogan {
    font-size: 30px;
    line-height: 1.15;
    font-weight: 800;
    letter-spacing: -0.5px;
    color: var(--text-primary);
    margin: 0 0 16px;
}

.exchange-desc {
    font-size: 15px;
    line-height: 1.6;
    color: var(--text-secondary);
    max-width: 460px;
    margin: 0 auto 28px;
}

.exchange-features {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px;
}

.exchange-feature {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
    font-size: 13px;
    font-weight: 600;
    color: var(--text-secondary);
}

.exchange-feature svg {
    color: var(--accent-green);
    flex-shrink: 0;
}

@media (max-width: 520px) {
    .exchange-hero-inner {
        padding: 36px 22px;
    }
    .exchange-slogan {
        font-size: 24px;
    }
    .exchange-features {
        flex-direction: column;
        align-items: stretch;
    }
    .exchange-feature {
        justify-content: center;
    }
}

/* ==========================================
   SLOTS / CASINO PAGE
   ========================================== */
.slots-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 16px;
}

.slots-header h2 {
    font-size: 24px;
    font-weight: 800;
}

/* Search row — search is the primary way into a 300-game catalog, so it takes
   the full width; the provider list sits beside it as a dropdown. */
.slots-toolbar {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 18px;
}

.slots-search-bar {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 13px 16px;
    background: var(--bg-secondary-search);
    border: 1px solid var(--border-color);
    border-radius: 0;
    flex: 1;
    min-width: 0;   /* let the input shrink instead of pushing the dropdown out */
}

.slots-search-bar svg {
    color: var(--text-muted);
    flex-shrink: 0;
}

.slots-search-bar input {
    flex: 1;
    min-width: 0;
    background: none;
    border: none;
    color: var(--text-primary);
    font-size: 14.5px;
    font-family: inherit;
}

.slots-search-bar input::placeholder {
    color: var(--text-muted);
}

/* "/" focus hint — desktop affordance, meaningless on touch. */
.slots-search-kbd {
    flex-shrink: 0;
    padding: 2px 6px;
    border: 1px solid var(--border-color);
    border-radius: 0;
    color: var(--text-muted);
    font: 700 10px ui-monospace, Menlo, monospace;
}

.slots-provider-wrap {
    position: relative;
    flex-shrink: 0;
}

.slots-provider {
    appearance: none;
    -webkit-appearance: none;
    height: 48px;
    max-width: 210px;
    padding: 0 34px 0 15px;
    background: var(--bg-secondary-search);
    border: 1px solid var(--border-color);
    border-radius: 0;
    color: var(--text-primary);
    font: 700 12.5px inherit;
    font-family: inherit;
    cursor: pointer;
    text-overflow: ellipsis;
}

.slots-provider-chevron {
    position: absolute;
    top: 50%;
    right: 13px;
    transform: translateY(-50%);
    color: var(--text-muted);
    pointer-events: none;
}

.slots-categories {
    display: flex;
    gap: 7px;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 4px 0;
    margin-bottom: 18px;
}

.slots-categories::-webkit-scrollbar {
    display: none;
}

.slots-cat-btn {
    height: 38px;
    padding: 0 16px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 19px;
    color: var(--text-secondary);
    font-size: 12.5px;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
    font-family: inherit;
    transition: all 0.15s;
}

.slots-cat-btn:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}

.slots-cat-btn.active {
    background: var(--accent-green-grad);
    border-color: transparent;
    color: var(--bg-deep);
    font-weight: 800;
}

/* Small badge inside a chip (used on Favorites to show the saved count).
   Matches the .mybets-tab-count / .betslip-tab-count style. */
.slots-cat-btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}
/* The count is a quiet suffix, not a badge — every chip carries one now, and
   eight loud pills in a row would out-shout the labels. */
.slots-cat-count {
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    color: var(--text-muted);
    opacity: 0.75;
}
.slots-cat-btn.active .slots-cat-count {
    color: var(--bg-green-deep);
    opacity: 0.6;
}

.slots-grid {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 11px;
}
@media (max-width: 1500px) { .slots-grid { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
@media (max-width: 1240px) { .slots-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 900px)  { .slots-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* Grid section heading — names the block after the active facet. Mostly for
   the mobile 3-up layout, where an unlabelled wall of art has no anchor. */
.slots-grid-head {
    display: flex;
    align-items: baseline;
    gap: 9px;
    margin: 0 0 11px;
}
.slots-grid-head[hidden] { display: none; }
.slots-grid-title {
    margin: 0;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 19px;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--text-primary);
}
.slots-grid-count {
    font-size: 11px;
    color: var(--text-muted);
}

/* ── Live tables teaser (TAVOLINA LIVE) ────────────────────────────────
   Only ever rendered when the Live Casino catalog actually has open tables. */
.slots-live-strip {
    display: block;
    margin: 0 0 22px;
    padding: 14px 15px;
    border-radius: 0;
    text-decoration: none;
    color: inherit;
    background: linear-gradient(120deg, #123024, var(--bg-secondary));
    border: 1px solid #2a4a3a;
    transition: border-color 0.15s ease, transform 0.15s ease;
}
.slots-live-strip[hidden] { display: none; }
.slots-live-strip:hover { border-color: rgba(0, 231, 112, 0.55); transform: translateY(-1px); }
.sls-head {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 10px;
}
.sls-title {
    margin: 0;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 19px;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--text-primary);
}
.sls-sub { font-size: 10.5px; color: var(--text-muted); }
.sls-sub.is-accent { color: var(--accent-green-neon); font-weight: 700; }
.sls-row {
    display: flex;
    align-items: center;
    gap: 11px;
    min-width: 0;
}
.sls-art {
    flex-shrink: 0;
    width: 46px;
    height: 46px;
    border-radius: 0;
    background: linear-gradient(150deg, #15803d, #052e16);
    display: grid;
    place-items: center;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 12px;
    color: #fff;
}
.sls-body { flex: 1; min-width: 0; }
.sls-name {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 13px;
    font-weight: 700;
    color: var(--text-primary);
    min-width: 0;
}
.sls-name .lc-live { padding: 2px 6px; font-size: 8px; }
.sls-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 5px;
    min-width: 0;
    flex-wrap: wrap;
}
/* Reuse the Live Casino result discs at a smaller size. */
.sls-meta .lc-results { margin-bottom: 0; gap: 5px; }
.sls-meta .lc-results-label { display: none; }
.sls-meta .lc-res { width: 19px; height: 19px; font-size: 9px; }
.sls-dealer {
    font-size: 10px;
    color: var(--text-muted);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.sls-cta {
    flex-shrink: 0;
    height: 34px;
    padding: 0 14px;
    display: inline-flex;
    align-items: center;
    background: var(--accent-green-grad);
    color: var(--bg-green-deep);
    border-radius: 0;
    font-size: 11.5px;
    font-weight: 800;
}

/* While a search is running the page is a results list: the feature card, the
   shelf and the Top 10 collapse so matches sit directly under the search box
   instead of a full screen below the fold. */
.slots-searching .slots-showcase,
.slots-searching .slots-topten {
    display: none;
}
.slots-results-head {
    margin: 0 0 12px;
}
.slots-results-head[hidden] { display: none; }
.slots-results-count {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--text-muted);
}

/* Paging control under the grid — 298 cards in one paint is ~300 image
   requests nobody scrolls to the end of. */
.slots-more {
    display: flex;
    justify-content: center;
    margin-top: 18px;
}
.slots-more[hidden] { display: none; }
.slots-more-btn {
    height: 42px;
    padding: 0 26px;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 0;
    color: var(--text-secondary);
    font: 700 12.5px inherit;
    font-family: inherit;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}
.slots-more-btn:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}
.slots-more-count { color: var(--text-muted); }
.slots-more-count::before { content: '('; }
.slots-more-count::after  { content: ')'; }

/* ================================================
   SLOTS TOP 10 — bet365-style numbered promo row
   ================================================
   Big webp numerals (assets 1..10) overlap each card's
   bottom-left corner; the row scrolls horizontally with
   the numeral hanging outside the thumb so the layout
   reads "chart position", not "badge". */
.slots-topten {
    margin: 0 0 26px;
    padding: 18px 16px 8px;
    border-radius: var(--radius-lg, 14px);
    /* Near-black band like the reference — makes the green numerals pop
       against the page's blue-grey surfaces. */
    background: linear-gradient(180deg, var(--bg-primary) 0%, var(--bg-primary) 100%);
    border: 1px solid rgba(255, 255, 255, 0.05);
    overflow: hidden;
}

.slots-topten-head {
    margin-bottom: 12px;
}
/* Text lockup replaces the TopTenEnglish.webp raster — that art was
   English-only and this app ships six languages. */
.slots-topten-title {
    margin: 0 0 3px;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 30px;
    line-height: 1;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--text-primary);
}
.slots-topten-sub {
    margin: 0;
    font-size: 12.5px;
    color: var(--text-muted);
}

.slots-topten-scroll {
    display: flex;
    gap: 18px;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x proximity;
    padding: 6px 4px 14px 2px;
    /* x-pannable, but vertical pans MUST fall through to page scroll —
       bare `pan-x` blocks them (see the global scroller rule's comment). */
    touch-action: pan-x pan-y;
    scrollbar-width: none;
    -ms-overflow-style: none;
}
.slots-topten-scroll::-webkit-scrollbar { display: none; }

/* Numeral in its own gutter column. It used to be absolutely positioned over
   the thumb, which put the "1" on top of the name label ("1" covering "Tur…").
   A grid column can't overlap its sibling, so the collision is structural. */
.tt-card {
    position: relative;
    flex: 0 0 auto;
    display: grid;
    grid-template-columns: auto 1fr;
    align-items: center;
    gap: 6px;
    scroll-snap-align: start;
    cursor: pointer;
}

.tt-num {
    grid-column: 1;
    height: 62px;
    width: auto;
    align-self: center;
    pointer-events: none;
    filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.6));
}

.tt-body {
    grid-column: 2;
    min-width: 0;
}

.tt-thumb-wrap {
    position: relative;
    /* Narrowed with the flip to 3:4 so the Top-10 row doesn't grow ~90px taller
       (152px wide at 3:4 would be 202px tall, against 114px at 4:3). */
    width: 124px;
    aspect-ratio: 3 / 4;
    border-radius: 0;
    overflow: hidden;
    border: 1px solid rgba(0, 231, 112, 0.35);
    background: var(--bg-tertiary);
    transition: transform 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease;
}
.tt-card:hover .tt-thumb-wrap,
.tt-card:focus-visible .tt-thumb-wrap {
    transform: translateY(-3px);
    border-color: rgba(0, 231, 112, 0.75);
    box-shadow: 0 8px 22px rgba(0, 231, 112, 0.16);
}
.tt-card:focus-visible { outline: none; }

/* `contain`, not `cover` — see .slot-card-thumb for why. */
.tt-thumb {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

/* Name sits below the art now, so nothing can crop or cover it. */
.tt-name {
    margin-top: 6px;
    padding: 0 2px;
    font-size: 12px;
    font-weight: 700;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

@media (max-width: 600px) {
    .slots-topten { padding: 14px 12px 10px; }
    .slots-topten-title { font-size: 24px; }
    .slots-topten-sub { font-size: 11.5px; }
    .tt-thumb-wrap { width: 128px; }
    .tt-num { height: 46px; }
    .slots-topten-scroll { gap: 12px; }
}

/* ================================================
   SLOTS SHOWCASE — feature card + the user's shelf
   ================================================
   Replaces the "Epic Titles" mosaic. That grid mixed 2x2 tiles with 1x1s
   under grid-auto-flow:column, so a large tile's blur bleed washed over its
   neighbours and the row read as a mistake. One deliberate feature card
   instead, beside the games the user actually has a relationship with. */
.slots-showcase {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 340px;
    gap: 14px;
    margin-bottom: 22px;
}
.slots-showcase:empty { display: none; }

.slots-feature {
    position: relative;
    min-height: 214px;
    border-radius: 0;
    overflow: hidden;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
}
.slots-feature[hidden] { display: none; }

/* The feature card's own art, blurred and dimmed, is the backdrop — the panel
   picks up the game's palette without needing per-game colour data. */
.slots-feature-wash {
    position: absolute;
    inset: -40px;
    background: var(--tile-art) center / cover no-repeat;
    filter: blur(38px) saturate(1.3);
    opacity: 0.42;
    pointer-events: none;
}
.slots-feature-inner,
.slots-feature > .slots-feature-art,
.slots-feature > .slots-feature-body { position: relative; }

.slots-feature {
    display: flex;
    align-items: center;
    gap: 26px;
    padding: 20px 26px;
}
.slots-feature::after {
    /* Readability floor over the wash — heavy behind the text, thinning out to
       the right so the game's own colours carry the empty half of the card. */
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(100deg, rgba(var(--bg-deep-rgb), 0.95) 34%, rgba(var(--bg-deep-rgb), 0.35) 100%);
    pointer-events: none;
}
.slots-feature-art {
    position: relative;
    z-index: 1;
    flex-shrink: 0;
    /* Same reasoning as .tt-thumb-wrap — narrowed to keep the feature card's
       height close to what it was before the portrait flip. */
    width: 158px;
    aspect-ratio: 3 / 4;
    border-radius: 0;
    overflow: hidden;
    background: rgba(0, 0, 0, 0.35);
    box-shadow: 0 16px 34px rgba(0, 0, 0, 0.45);
}
.slots-feature-art img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}
.slots-feature-body {
    position: relative;
    z-index: 1;
    min-width: 0;
}
.slots-feature-kicker {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 9px;
}
.slots-feature-tag {
    padding: 4px 8px;
    border-radius: var(--radius-sm);
    background: var(--accent-green-grad);
    color: var(--bg-green-deep);
    font-size: 9.5px;
    font-weight: 800;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.slots-feature-prov {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
}
.slots-feature-title {
    margin: 0 0 14px;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 38px;
    line-height: 1;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.slots-feature-tags {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    margin: -6px 0 14px;
}
.slots-feature-tags span {
    padding: 4px 9px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-secondary);
    font-size: 10.5px;
    font-weight: 700;
}

.slots-feature-play {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    height: 42px;
    padding: 0 22px;
    background: var(--accent-green-grad);
    color: var(--bg-green-deep);
    border: none;
    border-radius: 0;
    font:13.5px;
    font-weight: 800;
    font-family: inherit;
    cursor: pointer;
    transition: transform 0.15s ease;
}
.slots-feature-play:hover { transform: translateY(-1px); }

/* Facts row — RTP / volatility / max win, from /slots/game-meta.json. Absent
   whenever the figure isn't known, so nothing here is ever a placeholder. */
.slots-feature-facts {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin: -4px 0 15px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted);
}
.slots-feature-facts b { color: var(--text-primary); font-weight: 700; }
.slots-feature-sep { color: var(--border-color); }

/* --- Continue playing / Favorites shelf --- */
.slots-rail {
    padding: 15px 16px;
    border-radius: 0;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    min-width: 0;
}
.slots-rail[hidden] { display: none; }
/* --- Game providers rail (under the live-tables strip) --------------------
   Wordmark cards, not logos: the catalog stores `categoria` as a bare string and
   ships no provider artwork, so the name IS the mark. Sized and spaced like the
   other slots rails so it reads as one of them rather than a bolted-on band. */
.slots-providers {
    margin: 18px 0;
}

.slots-providers-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 11px;
}

.slots-providers-title {
    margin: 0;
    display: flex;
    align-items: center;
    gap: 9px;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 19px;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--text-primary);
}

.slots-providers-icon {
    display: inline-flex;
    width: 20px;
    height: 20px;
    color: var(--text-muted, #7c8798);
}

.slots-providers-icon svg {
    width: 100%;
    height: 100%;
    display: block;
}

.slots-providers-track {
    display: flex;
    align-items: stretch;
    gap: 9px;
    overflow-x: auto;
    scrollbar-width: none;
    /* Vertical pans must fall through to the page — bare `pan-x` swallows them. */
    touch-action: pan-x pan-y;
    overscroll-behavior-x: contain;
    padding-bottom: 2px;
}

.slots-providers-track::-webkit-scrollbar { display: none; }

.slots-provider-card {
    flex: 0 0 152px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    height: 65px;
    padding: 10px 12px;
    border: 1px solid transparent;
    border-radius: 0;
    background: var(--bg-card, var(--bg-secondary));
    color: var(--text-secondary, #c4d6e2);
    cursor: pointer;
    font-family: inherit;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.slots-provider-mark {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 16px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    line-height: 1.1;
    text-align: center;
    /* Provider names run from "EGT" to "InbetFreeSpin" on one row of fixed-width
       cards — clip the long tail rather than let one name set the card height. */
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.slots-provider-n {
    font-size: 11px;
    font-variant-numeric: tabular-nums;
    color: var(--text-muted, #7c8798);
}

.slots-provider-card:hover {
    background: var(--bg-hover, var(--live-row-hover));
    color: var(--text-primary, #fff);
}

/* Selected provider. Border + text, not a filled accent block: this rail sits a
   few hundred pixels above the grid it filters, and a solid accent card that far
   from its effect competes with the game art it is supposed to be introducing. */
.slots-provider-card.active {
    border-color: var(--accent-green-neon, #c0e849);
    color: var(--text-primary, #fff);
}

.slots-provider-card.active .slots-provider-n {
    color: var(--accent-green-neon, #c0e849);
}

.slots-rail-head {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 11px;
}
.slots-rail-count {
    font-size: 10.5px;
    color: var(--text-muted);
}
.slots-rail-title {
    margin: 0;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 19px;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--text-primary);
}
.slots-rail-track {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    overflow-x: auto;
    scrollbar-width: none;
    /* Vertical pans must fall through to the page — bare `pan-x` swallows them. */
    touch-action: pan-x pan-y;
    overscroll-behavior-x: contain;
    padding-bottom: 2px;
}
.slots-rail-track::-webkit-scrollbar { display: none; }
.slots-rail-card {
    flex: 0 0 104px;
    width: 104px;
    /* flex-basis does NOT cap this on its own: default `min-width: auto` is the
       content's min-content width, so a long title stretches the card past its
       basis and defeats the ellipsis below. Both declarations are required. */
    min-width: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: 0;
    background: none;
    border: none;
    color: inherit;
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}
.slots-rail-card:focus-visible {
    outline: 2px solid var(--accent-green-neon);
    outline-offset: 2px;
    border-radius: 0;
}

/* Un-favorite without leaving the shelf. Always visible on touch (no hover to
   reveal it); fades in on pointer devices so the art stays clean. */
.slots-rail-fav {
    position: absolute;
    top: 4px;
    right: 4px;
    z-index: 2;
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    background: rgba(0, 0, 0, 0.6);
    border: none;
    border-radius: 999px;
    color: rgba(255, 255, 255, 0.85);
    cursor: pointer;
    transition: background 0.15s, color 0.15s, opacity 0.15s;
}
.slots-rail-fav.is-fav { color: #ff5b6a; }
.slots-rail-fav:hover { background: rgba(0, 0, 0, 0.8); }
@media (hover: hover) and (pointer: fine) {
    .slots-rail-fav { opacity: 0; }
    .slots-rail-card:hover .slots-rail-fav,
    .slots-rail-card:focus-within .slots-rail-fav,
    .slots-rail-fav:focus-visible,
    .slots-rail-fav.is-fav { opacity: 1; }
}
.slots-rail-art {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 3 / 4;
    border-radius: 0;
    overflow: hidden;
    background: var(--bg-deep);
    transition: transform 0.16s ease;
}
.slots-rail-card:hover .slots-rail-art { transform: translateY(-2px); }
.slots-rail-art img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
}
.slots-rail-name {
    max-width: 100%;
    font-size: 10.5px;
    font-weight: 700;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: center;
}

@media (max-width: 1100px) {
    .slots-showcase { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 700px) {
    .slots-feature {
        gap: 14px;
        padding: 14px;
        min-height: 0;
    }
    .slots-feature-art { width: 108px; }
    .slots-feature-title { font-size: 26px; margin-bottom: 10px; }
    .slots-feature-play { height: 38px; padding: 0 16px; font-size: 12.5px; }
}

.slots-empty {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 60px 20px;
    text-align: center;
}

/* The empty-state is toggled via the `hidden` attribute in JS (_renderGrid).
   Author `display: flex` above would otherwise override the UA `[hidden]`
   rule, leaving the "No games match your search" message permanently visible
   on top of the grid — so re-assert hiding for the attribute. */
.slots-empty[hidden] {
    display: none;
}

.slots-empty p {
    font-size: 16px;
    font-weight: 600;
    color: var(--text-secondary);
    margin-top: 16px;
    margin-bottom: 6px;
}

.slots-empty span {
    font-size: 13px;
    color: var(--text-muted);
}

@media (max-width: 600px) {
    .slots-header {
        flex-direction: column;
        align-items: flex-start;
        gap: 12px;
    }

    /* One row, not two: a full-width dropdown under a full-width search reads
       as a second search bar and costs a whole screen-row before any game is
       visible. Search takes the space, the provider shrinks to a pill. */
    .slots-toolbar { gap: 8px; }
    .slots-search-bar {
        padding: 11px 12px;
        gap: 8px;
        border-radius: 0;
    }
    .slots-search-bar input { font-size: 13.5px; }
    .slots-search-kbd { display: none; }
    .slots-provider {
        max-width: 116px;
        height: 44px;
        padding: 0 26px 0 11px;
        font-size: 11.5px;
        border-radius: 0;
    }
    .slots-provider-chevron { right: 9px; }

    /* The shelf is a rail here, not a panel — drop the card chrome so the
       artwork starts at the screen edge like the rest of the page. */
    .slots-showcase { gap: 16px; margin-bottom: 18px; }
    .slots-rail {
        padding: 0;
        background: none;
        border: none;
    }
    .slots-rail-head { margin-bottom: 9px; }
    .slots-rail-title { font-size: 17px; }
    .slots-rail-card { flex: 0 0 108px; }

    .slots-live-strip { padding: 12px 13px; margin-bottom: 18px; }
    .sls-title { font-size: 17px; }
    .sls-cta { height: 32px; padding: 0 12px; }

    .slots-grid-head { margin-bottom: 9px; }
    .slots-grid-title { font-size: 17px; }

    /* The facts row wraps at this width; a separator stranded at the start of
       the second line reads as a bullet. Drop them and let the gap separate. */
    .slots-feature-facts { gap: 4px 12px; font-size: 11.5px; }
    .slots-feature-sep { display: none; }
    .slots-rail-card { flex-basis: 108px; width: 108px; }

    .slots-cat-btn { height: 34px; padding: 0 14px; font-size: 12.5px; }

    /* 3-up — the phone layout the design calls for. */
    .slots-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 9px;
    }
    .slot-card-meta { padding: 6px 7px 7px; }
    .slot-card-name { font-size: 10.5px; }
    /* Art + name only at 3-up: provider and RTP don't fit a ~108px card, and
       showing RTP on only the games that have it left ragged row heights. */
    .slot-card-sub { display: none; }
}

/* --- Search clear (X) button inside the slots search bar --- */
.slots-search-clear {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    background: rgba(255, 255, 255, 0.08);
    border: none;
    border-radius: 999px;
    color: var(--text-secondary);
    cursor: pointer;
    flex-shrink: 0;
}
.slots-search-clear:hover {
    background: rgba(255, 255, 255, 0.16);
    color: var(--text-primary);
}

/* --- Error state when the JSON fetch fails --- */
.slots-error {
    grid-column: 1 / -1;
    padding: 40px 20px;
    text-align: center;
    color: var(--text-muted);
    font-size: 14px;
}

/* --- Game cards --- */
.slot-card {
    position: relative;
    display: flex;
    flex-direction: column;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    overflow: hidden;
    cursor: pointer;
    transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}
.slot-card:hover {
    transform: translateY(-2px);
    border-color: rgba(58, 165, 110, 0.55);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.35);
}

/* Fixed 4:3 tile.
   The art comes from two hosts at two aspect ratios and much of it has the
   title baked into the image, so `cover` sliced words mid-letter — "RING 7 HO",
   "G BASS" — and then the real title was repeated underneath. `contain` keeps
   every thumbnail whole; the letterbox is filled by a blurred, over-scaled copy
   of the same art, so the tile picks up the artwork's own colours instead of a
   grey bar. */
.slot-card-thumb-wrap {
    position: relative;
    width: 100%;
    aspect-ratio: 3 / 4;
    background: linear-gradient(135deg, var(--bg-secondary), var(--bg-primary));
    overflow: hidden;
}
.slot-card-blur {
    position: absolute;
    inset: -12%;
    background: var(--tile-art) center / cover no-repeat;
    filter: blur(16px) saturate(1.25) brightness(0.62);
    pointer-events: none;
}
.slot-card-thumb {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
}

/* ── Live Casino / Arcade: category-icon watermark ─────────────────────────
   Those two catalogs ship 300x150 (2:1) provider banners, which `contain`
   into a 3:4 portrait tile at only ~38% height — leaving ~62% blurred filler
   that reads as a broken image rather than a design.
   `.slot-card--wide-art` moves the banner up and drops the category icon
   (roulette / card / slots svg) into the space underneath, so the empty band
   becomes deliberate. Games that DO have real 5:7 portrait art don't get the
   class, so they stay full-bleed exactly like a slot tile. */
.slot-card--wide-art .slot-card-thumb {
    object-position: center 32%;
}
/* Rendered as an <img>, not a CSS mask: these are full-colour illustrations
   (card.svg is 170KB of artwork), and masking would flatten them to a solid
   silhouette. Each file is one cached request no matter how many cards use it. */
.slot-card-cat {
    position: absolute;
    left: 50%;
    bottom: 7%;
    transform: translateX(-50%);
    width: 38%;
    max-width: 84px;
    opacity: 0.75;
    pointer-events: none;
    filter: drop-shadow(0 4px 10px rgba(0, 0, 0, 0.55));
    transition: opacity 0.16s ease, transform 0.16s ease;
}
.slot-card:hover .slot-card-cat {
    opacity: 0.95;
    transform: translateX(-50%) translateY(-2px);
}
/* If the thumbnail fails (404, mixed-content block, etc.) the JS strips src
   and adds this class — the gradient bg becomes the visible placeholder. */
.slot-card-thumb-fallback {
    background:
        radial-gradient(circle at 30% 30%, rgba(58, 165, 110, 0.18), transparent 60%),
        linear-gradient(135deg, var(--bg-secondary), var(--bg-primary));
}

/* Hover overlay with Play button — also appears on tap because mobile maps
   :hover to first tap; the second tap (which actually navigates) is the
   click handler on .slot-card. */
.slot-card-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(180deg, rgba(0,0,0,0.0) 30%, rgba(0,0,0,0.65) 100%);
    opacity: 0;
    transition: opacity 0.15s ease;
}
.slot-card:hover .slot-card-overlay,
.slot-card:focus-within .slot-card-overlay {
    opacity: 1;
}

/* The play / join badge is the card's keyboard control (Tab reaches it, Enter
   and Space press it, and :focus-within above shows the overlay it sits in).
   It was a span: Slots and Arcade cards took no focus at all, and Live Casino
   cards took it but ignored Enter and Space. */
button.slot-card-play {
    border: 0;
    cursor: pointer;
    font-family: inherit;
    line-height: inherit;
}
.slot-card-play:focus-visible,
.slot-card-name-btn:focus-visible {
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* Home's promo cards have no badge — their name is the button, drawn as text. */
.slot-card-name-btn {
    display: block;
    width: 100%;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: inherit;
    cursor: pointer;
}
.slot-card-play {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 16px;
    background: var(--accent-green-grad);
    color: var(--bg-green-deep);
    border-radius: 999px;
    font-size: 13px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    box-shadow: 0 6px 14px rgba(0, 0, 0, 0.4);
}

/* Heart toggle — top-right, always visible. */
.slot-card-heart {
    position: absolute;
    top: 6px;
    right: 6px;
    z-index: 2;
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    background: rgba(0, 0, 0, 0.55);
    border: none;
    border-radius: 999px;
    color: rgba(255, 255, 255, 0.85);
    cursor: pointer;
    transition: background 0.15s, color 0.15s, transform 0.15s;
}
.slot-card-heart:hover {
    background: rgba(0, 0, 0, 0.75);
    transform: scale(1.05);
}
.slot-card.slot-card-fav .slot-card-heart {
    color: #ff5b6a;
}

/* Name + provider live OUTSIDE the art, so neither can ever be cropped by the
   thumbnail or covered by a badge. Titles arrive pre-normalised from
   Slots.prettyName() — no `text-transform: capitalize` hack needed. */
.slot-card-meta {
    padding: 8px 9px 9px;
    min-width: 0;
}
.slot-card-name {
    font-size: 11.5px;
    font-weight: 700;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.slot-card-sub {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 3px;
    min-width: 0;
}
.slot-card-provider {
    font-size: 10px;
    font-weight: 600;
    color: var(--text-muted);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.slot-card-rtp {
    margin-left: auto;
    flex-shrink: 0;
    font-size: 10px;
    font-weight: 700;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}

/* ================================================
   LIVE CASINO — tables as live objects
   ================================================
   A live table isn't a thumbnail, it's a room with a clock. Every card carries
   the four things that decide whether you join: is a seat free, what are the
   limits, what language is the dealer, and what just happened. */
.lc-toolbar {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}
.lc-toolbar[hidden] { display: none; }

.lc-chips {
    display: flex;
    align-items: center;
    gap: 7px;
    flex: 1;
    min-width: 0;
    overflow-x: auto;
    scrollbar-width: none;
    touch-action: pan-x pan-y;
    overscroll-behavior-x: contain;
    padding: 2px 0;
}
.lc-chips::-webkit-scrollbar { display: none; }

.lc-chip {
    flex-shrink: 0;
    height: 36px;
    padding: 0 15px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 18px;
    color: var(--text-secondary);
    font: 700 12px inherit;
    font-family: inherit;
    cursor: pointer;
    white-space: nowrap;
    transition: all 0.15s;
}
.lc-chip:hover { background: var(--bg-hover); color: var(--text-primary); }
.lc-chip.active {
    background: var(--accent-green-grad);
    border-color: transparent;
    color: var(--bg-green-deep);
    font-weight: 800;
}
.lc-chip-n { color: var(--text-muted); opacity: 0.75; font-size: 11px; }
.lc-chip.active .lc-chip-n { color: var(--bg-green-deep); opacity: 0.6; }

/* Free-seats switch. */
.lc-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
    color: var(--text-muted);
    font-size: 11.5px;
    font-weight: 600;
    cursor: pointer;
}
.lc-toggle input { position: absolute; opacity: 0; pointer-events: none; }
.lc-toggle-track {
    position: relative;
    width: 32px;
    height: 18px;
    border-radius: 9px;
    background: var(--bg-tertiary);
    transition: background 0.15s;
    flex-shrink: 0;
}
.lc-toggle-knob {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--bg-deep);
    transition: transform 0.15s;
}
.lc-toggle input:checked + .lc-toggle-track { background: var(--accent-green-neon); }
.lc-toggle input:checked + .lc-toggle-track .lc-toggle-knob { transform: translateX(14px); }
.lc-toggle input:focus-visible + .lc-toggle-track { outline: 2px solid var(--accent-green-neon); outline-offset: 2px; }

/* Shared LIVE badge. */
.lc-live {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 4px 8px;
    border-radius: var(--radius-sm);
    background: var(--accent-red);
    color: #fff;
    font-size: 9.5px;
    font-weight: 800;
    letter-spacing: 0.1em;
}
.lc-live-dot {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: #fff;
    animation: lcPulse 1.4s infinite;
}
@keyframes lcPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) {
    .lc-live-dot { animation: none; }
}

/* Dev-only notice: the tables on screen are the sample placeholders because
   livecasino.json is empty and this is localhost. Deliberately loud. */
.lc-sample-banner {
    margin: 0 0 14px;
    padding: 9px 13px;
    border-radius: 0;
    background: rgba(255, 140, 0, 0.12);
    border: 1px solid rgba(255, 140, 0, 0.45);
    color: var(--accent-orange);
    font-size: 11.5px;
    font-weight: 600;
    line-height: 1.5;
}

/* --- Featured table --- */
.lc-featured {
    margin-bottom: 20px;
}
.lc-featured[hidden] { display: none; }
.lc-featured-inner {
    position: relative;
    min-height: 230px;
    padding: 18px 22px;
    border-radius: 0;
    overflow: hidden;
    border: 1px solid var(--border-color);
    background:
        linear-gradient(90deg, var(--bg-deep) 12%, rgba(var(--bg-deep-rgb), 0.72) 55%, rgba(var(--bg-deep-rgb), 0.2) 100%),
        var(--lc-art, linear-gradient(120deg, #123024, var(--bg-odds))) right center / cover no-repeat;
    display: flex;
    align-items: flex-end;
}
.lc-featured-kicker {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
}
.lc-lang-tag {
    padding: 4px 8px;
    border-radius: var(--radius-sm);
    background: rgba(0, 231, 112, 0.13);
    color: var(--accent-green-neon);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.lc-featured-title {
    margin: 0 0 6px;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 34px;
    line-height: 1;
    color: var(--text-primary);
}
.lc-featured-meta {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-bottom: 13px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted);
}
.lc-featured-meta b { color: var(--text-primary); }
.lc-dot { color: var(--border-color); }
.lc-featured-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}
.lc-join {
    height: 42px;
    padding: 0 22px;
    background: var(--accent-green-grad);
    color: var(--bg-green-deep);
    border: none;
    border-radius: 0;
    font: 800 13.5px inherit;
    font-family: inherit;
    cursor: pointer;
    transition: transform 0.15s ease;
}
.lc-join:hover { transform: translateY(-1px); }
.lc-limits {
    font-size: 11.5px;
    font-weight: 600;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

/* Recent results — roulette numbers as discs, everything else as pills. */
.lc-results {
    display: flex;
    align-items: center;
    gap: 7px;
    flex-wrap: wrap;
    margin-bottom: 14px;
}
.lc-results-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.lc-res {
    width: 26px;
    height: 26px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    font-size: 11px;
    font-weight: 800;
    color: #fff;
    font-variant-numeric: tabular-nums;
}
.lc-res-red { background: #c0392b; }
.lc-res-black { background: #1c1c1c; border: 1px solid #3a3a3a; }
.lc-res-green { background: #15803d; }
.lc-res-neutral { background: var(--bg-tertiary); }
.lc-pill {
    padding: 3px 7px;
    border-radius: 0;
    background: rgba(255, 255, 255, 0.06);
    color: var(--text-secondary);
    font-size: 10.5px;
    font-weight: 800;
}
.lc-pill-hot {
    background: rgba(0, 231, 112, 0.14);
    color: var(--accent-green-neon);
}

/* --- Section head + grid --- */
.lc-section-head {
    display: flex;
    align-items: baseline;
    gap: 11px;
    margin-bottom: 12px;
}
.lc-section-head[hidden] { display: none; }
.lc-section-head h3 {
    margin: 0;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 23px;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--text-primary);
}
.lc-open-count {
    font-size: 11.5px;
    color: var(--text-muted);
}

.lc-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 12px;
}
@media (max-width: 1240px) { .lc-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 900px)  { .lc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.lc-card {
    border-radius: 0;
    overflow: hidden;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    cursor: pointer;
    transition: transform 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
}
.lc-card:hover,
.lc-card:focus-visible {
    transform: translateY(-2px);
    border-color: rgba(0, 231, 112, 0.55);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.35);
    outline: none;
}
.lc-card-art {
    position: relative;
    height: 147px;
    display: grid;
    place-items: center;
    padding: 8px;
    background: var(--lc-art, linear-gradient(150deg, var(--bg-secondary), var(--bg-odds))) center / cover no-repeat;
}
.lc-card-art .lc-live {
    position: absolute;
    top: 7px;
    left: 7px;
    padding: 3px 6px;
    background: rgba(var(--bg-primary-rgb), 0.66);
    font-size: 8.5px;
}
.lc-card-art .lc-live-dot { background: var(--accent-red); }
.lc-card-kind {
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 15px;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.9);
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
    text-align: center;
}
.lc-card-lang {
    position: absolute;
    bottom: 7px;
    left: 7px;
    padding: 3px 6px;
    border-radius: 0;
    background: rgba(var(--bg-primary-rgb), 0.66);
    color: #fff;
    font-size: 9.5px;
    font-weight: 700;
}
.lc-seats {
    position: absolute;
    bottom: 7px;
    right: 7px;
    padding: 3px 6px;
    border-radius: 0;
    font-size: 9.5px;
    font-weight: 800;
}
.lc-seats.is-free { background: var(--accent-green-neon); color: var(--bg-green-deep); }
.lc-seats.is-full { background: rgba(var(--bg-primary-rgb), 0.66); color: var(--text-muted); }
/* On the featured card the badge sits inline with the CTA, not over art. */
.lc-featured-actions .lc-seats { position: static; }

.lc-card-body { padding: 9px 11px 11px; }
.lc-card-name {
    font-size: 12px;
    font-weight: 700;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.lc-card-meta {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 4px;
    min-width: 0;
}
.lc-card-dealer {
    font-size: 10.5px;
    font-weight: 600;
    color: var(--text-muted);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.lc-card-limits {
    margin-left: auto;
    flex-shrink: 0;
    font-size: 10.5px;
    font-weight: 700;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}

/* Empty state — shown whenever the table catalog has nothing open. Never
   replaced with placeholder tables. */
.lc-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 64px 20px;
    color: var(--text-muted);
}
.lc-empty[hidden] { display: none; }
.lc-empty svg { opacity: 0.35; margin-bottom: 16px; }
.lc-empty h3 {
    margin: 0 0 8px;
    font-size: 18px;
    font-weight: 700;
    color: var(--text-secondary);
}
.lc-empty p {
    margin: 0 0 18px;
    font-size: 13px;
    max-width: 420px;
}
.lc-empty-cta {
    height: 40px;
    padding: 0 20px;
    display: inline-flex;
    align-items: center;
    background: var(--accent-green-grad);
    color: var(--bg-green-deep);
    border-radius: 0;
    font-size: 12.5px;
    font-weight: 800;
    text-decoration: none;
}

@media (max-width: 700px) {
    .lc-featured-inner { min-height: 190px; padding: 14px 16px; }
    .lc-featured-title { font-size: 26px; }
    /* The toggle was stealing half the row and squeezing the chip scroller to
       a stub. Give the chips the full width and drop the toggle beneath. */
    .lc-toolbar {
        flex-wrap: wrap;
        gap: 10px;
    }
    .lc-chips { flex: 1 1 100%; }
    .lc-toggle { flex: 1 1 100%; }
    .lc-grid { gap: 9px; }
    .lc-card-art { height: 103px; }
}

/* --- Fullscreen launch overlay --- */
.slots-launch-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    flex-direction: column;
    background: #000;
    /* establishes the containing block for `.slots-launch-message` */
}

/* Desktop: shrink the overlay itself to a centered windowed card and draw a
   dimmed backdrop behind it via the `::before` pseudo. Toggling `.fullscreen`
   on the overlay collapses both rules back to the default inset:0 layout.
   Mobile (<1200px) stays fullscreen — `.fullscreen` is essentially the
   default behaviour there. */
@media (min-width: 1200px) {
    /* Full-bleed dim backdrop, sits BEHIND the overlay window. */
    .slots-launch-overlay:not(.fullscreen)::before {
        content: '';
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.78);
        backdrop-filter: blur(2px);
        -webkit-backdrop-filter: blur(2px);
        z-index: -1;
    }
    /* The overlay itself becomes a centered windowed card. */
    .slots-launch-overlay:not(.fullscreen) {
        inset: auto;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: min(85vw, 1200px);
        height: min(80vh, 800px);
        border-radius: var(--radius-md);
        overflow: hidden;
        box-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);
    }
}
.slots-launch-header {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 16px;
    /* The INSTALLED app (standalone) opts into viewport-fit=cover, so this
       `position: fixed; inset: 0` overlay is laid out edge-to-edge and the
       header lands UNDERNEATH the status bar — the title sits behind the clock
       and the close X behind the battery, unreachable. iOS has no Fullscreen
       API, so the :fullscreen rules that hide this bar never fire there.
       env() is 0 in regular Safari (viewport-fit=cover is only added for
       standalone), so this is a no-op in the browser.
       `.minimized` overrides the shorthand below with its own compact padding
       and floats clear of the notch, so it is deliberately left alone. */
    padding-top: calc(10px + env(safe-area-inset-top, 0px));
    background: var(--bg-deep);
    border-bottom: 1px solid var(--border-color);
    color: var(--text-primary);
}
.slots-launch-title {
    flex: 1;
    font-size: 14px;
    font-weight: 700;
    text-transform: capitalize;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.slots-launch-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    background: rgba(255, 255, 255, 0.06);
    border: none;
    border-radius: 999px;
    color: var(--text-primary);
    cursor: pointer;
    flex-shrink: 0;
}
.slots-launch-close:hover {
    background: rgba(255, 91, 106, 0.15);
    color: #ff5b6a;
}
/* Action group on the right of the launch header — "Open in tab" link,
   fullscreen toggle, close X. */
.slots-launch-actions {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
}

/* Fullscreen toggle: same shape/size as the close X. Shown only on desktop
   (mobile is always fullscreen — no useful state to toggle). The two SVG
   icons live in the same button; we show one or the other based on the
   overlay's `.fullscreen` class so we don't need a JS class swap. */
.slots-launch-fullscreen {
    display: none;            /* hidden by default; @media below enables on desktop */
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    background: rgba(255, 255, 255, 0.06);
    border: none;
    border-radius: 999px;
    color: var(--text-primary);
    cursor: pointer;
}
.slots-launch-fullscreen:hover {
    background: rgba(58, 165, 110, 0.18);
    color: var(--accent-green);
}
.slots-launch-fullscreen .lsfs-icon-collapse { display: none; }
.slots-launch-fullscreen .lsfs-icon-expand   { display: block; }
.slots-launch-overlay.fullscreen .slots-launch-fullscreen .lsfs-icon-expand   { display: none; }
.slots-launch-overlay.fullscreen .slots-launch-fullscreen .lsfs-icon-collapse { display: block; }
@media (min-width: 1200px) {
    .slots-launch-fullscreen { display: inline-flex; }
}

/* Minimize button — same shape as the fullscreen one, also desktop-only.
   The two SVGs ("minimize" ↓-style vs "restore" ↗-style) swap visibility
   based on the overlay's `.minimized` class. */
.slots-launch-minimize {
    display: none;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    background: rgba(255, 255, 255, 0.06);
    border: none;
    border-radius: 999px;
    color: var(--text-primary);
    cursor: pointer;
}
.slots-launch-minimize:hover {
    background: rgba(58, 165, 110, 0.18);
    color: var(--accent-green);
}
.slots-launch-minimize .lsmin-icon-restore  { display: none; }
.slots-launch-minimize .lsmin-icon-minimize { display: block; }
.slots-launch-overlay.minimized .slots-launch-minimize .lsmin-icon-minimize { display: none; }
.slots-launch-overlay.minimized .slots-launch-minimize .lsmin-icon-restore  { display: block; }
@media (min-width: 1200px) {
    .slots-launch-minimize { display: inline-flex; }
}

/* Minimized state — shrink overlay to a floating window in the bottom-right.
   No backdrop, body underneath is interactive again. Game keeps running
   because we only change CSS, never touch iframe.src. */
.slots-launch-overlay.minimized {
    /* Float in the bottom-right corner; cap dimensions so it stays compact
       on any viewport. min() falls back gracefully on small screens. */
    inset: auto;
    top: auto;
    left: auto;
    bottom: 16px;
    right: 16px;
    transform: none;
    width: min(380px, calc(100vw - 32px));
    height: min(280px, calc(100vh - 32px));
    border-radius: var(--radius-md);
    overflow: hidden;
    box-shadow: 0 14px 36px rgba(0, 0, 0, 0.55);
    z-index: 1000;
}
/* Kill the dim backdrop when minimized — the rest of the page must be visible
   AND clickable. */
.slots-launch-overlay.minimized::before {
    display: none;
}
/* Trim the header for the smaller width: hide bulky buttons, shrink padding
   and title font. The minimize-button (now showing the restore icon) and the
   close X stay so the user can pop back out or close. */
.slots-launch-overlay.minimized .slots-launch-header {
    padding: 6px 10px;
}
.slots-launch-overlay.minimized .slots-launch-title {
    font-size: 12px;
}
.slots-launch-overlay.minimized .slots-launch-newtab,
.slots-launch-overlay.minimized .slots-launch-fullscreen {
    display: none;
}
.slots-launch-overlay.minimized .slots-launch-close {
    width: 28px;
    height: 28px;
}
.slots-launch-overlay.minimized .slots-launch-minimize {
    width: 28px;
    height: 28px;
}

/* Drag handle — the entire header is grabbable when minimized. `user-select:
   none` stops text selection from kicking in when the user drags through the
   title. Buttons inside still work normally (mouse events on them don't
   bubble up to the header in a useful way, and the JS guards against
   starting a drag when the target is a button/link). */
.slots-launch-overlay.minimized .slots-launch-header {
    cursor: grab;
    user-select: none;
    -webkit-user-select: none;
}
.slots-launch-overlay.minimized.dragging .slots-launch-header {
    cursor: grabbing;
}
/* Critical: kill the iframe's pointer-events while a drag is in progress,
   otherwise the iframe captures mousemove events the moment the cursor
   crosses it (cross-origin iframes don't bubble events to the parent).
   The class lives only for the duration of the drag, so gameplay is
   unaffected the rest of the time. */
.slots-launch-overlay.dragging .slots-launch-iframe {
    pointer-events: none;
}

/* Floating close button — visible only when the launch-header is hidden
   (currently: mobile landscape). Stays on top of the iframe so the user
   can always exit even without the header chrome. */
.slots-launch-floating-close {
    position: absolute;
    /* Same safe-area story as .slots-launch-header. This button replaces the
       header in landscape, where a notched iPhone puts the inset on the SIDE
       rather than the top — so both axes matter here. */
    top: calc(8px + env(safe-area-inset-top, 0px));
    right: calc(8px + env(safe-area-inset-right, 0px));
    z-index: 10;
    display: none;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    padding: 0;
    background: rgba(0, 0, 0, 0.55);
    border: none;
    border-radius: 999px;
    color: #fff;
    cursor: pointer;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}
.slots-launch-floating-close:hover {
    background: rgba(255, 91, 106, 0.85);
}

/* Mobile landscape: drop the header bar so the game iframe gets the entire
   viewport. The floating close button replaces the header's X. Combined with
   the JS-triggered Fullscreen API (when supported) the user gets a truly
   immersive game view — no header chrome AND no browser URL bar. */
@media (max-width: 1199px) and (orientation: landscape) {
    .slots-launch-overlay:not(.minimized) .slots-launch-header {
        display: none;
    }
    .slots-launch-overlay:not(.minimized) .slots-launch-floating-close {
        display: inline-flex;
    }
}

/* When the overlay is in the browser's true fullscreen (Fullscreen API),
   reuse the same "hide chrome" treatment on every viewport — there's no
   browser frame to share space with, so the iframe should fill everything.
   The :fullscreen selector targets whichever element entered fullscreen. */
.slots-launch-overlay:fullscreen,
.slots-launch-overlay:-webkit-full-screen {
    /* Explicit sizing — without this, iOS Safari sometimes leaves the
       overlay at its pre-fullscreen `inset: 0` box and renders the iframe
       at a smaller logical size, which makes game-canvas text blurry.
       100dvw/dvh first (modern), 100vw/vh fallback. */
    width: 100vw;
    width: 100dvw;
    height: 100vh;
    height: 100dvh;
    max-width: 100vw;
    max-height: 100vh;
}
.slots-launch-overlay:fullscreen .slots-launch-iframe,
.slots-launch-overlay:-webkit-full-screen .slots-launch-iframe {
    width: 100%;
    height: 100%;
}
.slots-launch-overlay:fullscreen .slots-launch-header,
.slots-launch-overlay:-webkit-full-screen .slots-launch-header {
    display: none;
}
.slots-launch-overlay:fullscreen .slots-launch-floating-close,
.slots-launch-overlay:-webkit-full-screen .slots-launch-floating-close {
    display: inline-flex;
}
/* Icon-only at every width, matching the round close / fullscreen / minimize
   buttons beside it. The label is .sr-only in the markup and the tooltip is on
   the title attribute, so nothing here needs to hide text. */
.slots-launch-newtab {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    padding: 0;
    background: rgba(255, 255, 255, 0.06);
    border-radius: 999px;
    color: var(--text-primary);
    text-decoration: none;
    flex-shrink: 0;
}
.slots-launch-newtab:hover {
    background: rgba(58, 165, 110, 0.18);
    color: var(--accent-green);
}
.slots-launch-iframe {
    flex: 1;
    width: 100%;
    border: 0;
    background: #000;
}
/* Centered loading / error overlay shown while waiting for /api/slots/session.
   Sits ON TOP of the iframe so we don't have to swap visibility. */
.slots-launch-message {
    position: absolute;
    inset: 56px 0 0 0;   /* below the header bar */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: #000;
    color: var(--text-secondary);
    font-size: 14px;
    text-align: center;
    pointer-events: none;
}
/* Author `display: flex` above beats the browser's UA `[hidden]` rule —
   without this the spinner panel stays painted on top of the iframe even
   after JS sets `hidden = true`, masking the loaded game. */
.slots-launch-message[hidden] {
    display: none;
}
.slots-launch-spinner {
    width: 32px;
    height: 32px;
    border: 3px solid rgba(255, 255, 255, 0.15);
    border-top-color: var(--accent-green);
    border-radius: 50%;
    animation: slots-launch-spin 0.9s linear infinite;
}
@keyframes slots-launch-spin {
    to { transform: rotate(360deg); }
}
/* Lock the page underneath so it can't scroll while the launch overlay is up.
   Removed when the overlay is minimized — the user MUST be able to scroll and
   click the page again, that's the whole point of the picture-in-picture mode. */
body.slots-launch-open:not(.slots-launch-minimized) {
    overflow: hidden;
}

/* ==========================================
   LIVE PAGE
   ========================================== */
.live-top-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 8px;
}

/* The live page's list keeps some height, so switching to a sport with a few
   matches (or to an empty Favourites) doesn't pull the footer up under the tabs.
   It read "560x", which isn't a length, so browsers dropped it. Scoped to the
   live page: Home's "Live Tani" board shares the class and would grow an empty
   band inside its frame whenever fewer than ~5 matches are live. */
#page-live .live-matches {
    min-height: 560px;
}

.live-view-toggle {
    /* 2×2 grid. DOM order is: search · sort · view-extended · view-compact.
       Row 1 = "what to look at" (filter/sort), Row 2 = "how to display it" (view modes). */
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-auto-rows: 34px;
    gap: 2px;
    flex-shrink: 0;
    align-content: center;
    background: var(--bg-secondary);
    border-radius: var(--radius-sm);
    padding: 2px;
    height: 80px;
}

.live-view-btn {
    width: 34px;
    height: 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    color: var(--text-muted);
    cursor: pointer;
    transition: all 0.15s;
}

.live-view-btn:hover {
    color: var(--text-primary);
}

.live-view-btn.active {
    background: var(--bg-tertiary);
    color: var(--text-primary);
}

/* Wrap-forcing item for the mobile extended row — inert everywhere else. The
   desktop row is a single non-wrapping line of columns, so it must not appear
   there at all. Switched on in the mobile block. */
.live-match-linebreak { display: none; }

/* Over/Under column in extended view */
.live-match-ou,
.live-match-cou {
    display: flex;
    gap: 2px;
    align-items: center;
    flex-shrink: 0;
    padding: 4px 4px 4px 0;
    /* Sit on the same centre line as the 1X2 prices.
       .live-match-oddscol is a grid whose price row EXCLUDES the bottom band
       (the momentum bar lives there), so its buttons centre at (rowH - band)/2.
       These cells are plain flex items stretched over the FULL row height, so
       without this they centred 13px lower and the board showed two different
       price baselines across one row. Reserving the same band height — rather
       than nudging by 13px — keeps them locked together if --lm-band-h changes.
       Cancelled on mobile, where these blocks WRAP onto their own lines and a
       reserved band would just be dead space. */
    margin-bottom: var(--lm-band-h, 26px);
}

/* Same treatment for the market-count column, for the same reason. */
.live-match-mkt-count {
    margin-bottom: var(--lm-band-h, 26px);
}

.live-ou-line {
    font-size: 10px;
    font-weight: 600;
    color: var(--text-muted);
    width: 28px;
    text-align: center;
}

/* Inline market tag for the wrapped O/U rows. Hidden by default: on desktop the
   league header's O/U columns already name these markets, and repeating the
   label per row would be noise. The mobile block below switches it on, where
   those headers are display:none. */
.live-ou-tag {
    display: none;
    align-items: center;
    gap: 3px;
    margin-right: auto;      /* pushes the tag left, odds stay right-aligned */
    padding-left: 4px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.3px;
    color: var(--text-muted);
    white-space: nowrap;
}
.live-ou-tag svg {
    flex-shrink: 0;
    opacity: 0.85;
}

/* The sports bar's host (js/live.js _renderSportTabs): bet365's In-Play classification bar,
   vendor/live-scout/inplay-bar - its own sheets draw it (70px, its grey, the line in the
   selected sport's colour). The host holds the bar's height and grey while its files load. */
.live-sport-tabs {
    flex: 1;
    min-width: 0;
    min-height: 70px;
    background: var(--color-grey3);
}
/* Each sport's live match count under its name (js/live.js _paintBarCounts), in the bar's
   own count pill (its Favourites count): the buttons' top and bottom padding (14 / 13px)
   give it the room, so the bar keeps its 70px and every icon its row. */
#live-page-sport-tabs .ovm-ClassificationBarButton_Container,
#live-page-sport-tabs .ovm-PseudoClassificationBarButton_Container {
    padding-top: 7px;
    padding-bottom: 4px;
}
#live-page-sport-tabs .live-bar-count {
    display: table;
    min-width: 14px;
    height: 14px;
    margin: 2px auto 0;
    padding: 0 3px;
    border-radius: 28px;
    background: var(--color-grey5);
    color: var(--color-grey3);
    font-size: 11px;
    font-weight: 700;
    line-height: 14px;
    text-align: center;
}
#live-page-sport-tabs.allow-hover .ovm-ClassificationBarButton:hover .live-bar-count { background: var(--color-grey6); }
#live-page-sport-tabs .ovm-ClassificationBarButton-active .live-bar-count { background: var(--color-grey8); }
/* Favourites' own count keeps its place on the icon, raised with it. */
#live-page-sport-tabs .ovm-FavouriteButtonCount { top: 0; }

/* A phone: the bar the page's whole width, pinned under the site's header while the list
   scrolls (bet365's), the toolbox a row of its own under it. The top bar's box steps aside
   (display: contents) so the bar pins against the page, not against that short row; the
   latest-goals strip and the league headers pin under it (--live-bar-pin). */
@media (max-width: 600px) {
    #page-live { --live-bar-pin: 70px; }
    #page-live .live-top-bar { display: contents; }
    #page-live .live-sport-tabs {
        position: sticky;
        top: var(--header-height);
        z-index: 46;
    }
    #page-live .live-view-toggle {
        width: auto;
        height: auto;
        margin: 8px 0;
        grid-template-columns: repeat(3, 34px) minmax(0, 1fr);
    }
    #page-live .live-view-toggle .lmx-rows-btn { grid-column: auto; }
}
#page-live .live-goals-strip { top: calc(var(--header-height) + var(--live-bar-pin, 0px)); }

/* Live match row — 1a "dense board".
   Was ~98px: two team lines PLUS a third `.live-match-meta` line holding the
   minute, and a 5px separator between every row. The minute now sits in the 34px
   `.live-match-clock` column at the left, the stats/bell buttons moved to
   `.live-match-actions` on the right, and the separator is a 1px rule — so a
   football row is two lines tall and roughly 1.8x more matches fit per screen.
   `align-items: center` (was `stretch`) is what lets the columns sit on the row's
   centre line now that the row is short. */
.live-match-row {
    display: flex;
    /* `stretch`, not `center`: the two columns must both be full row height or the
       bottom band (clock+buttons on the left, momentum on the right) can't line up
       — see .live-match-metaline. */
    align-items: stretch;
    /* min-height, NOT height: in extended mode on mobile the O/U + corner blocks
       wrap onto their own lines (.live-match-linebreak forces it), and a fixed
       height would clip them. */
    min-height: var(--lm-row-h, 90px);
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border-subtle, var(--border-subtle));
    cursor: pointer;
    transition: background 0.1s;
    margin-top: 5px;
    border-radius: var(--radius-sm);
}

/* Height of the bottom band. BOTH columns declare it as their last grid row, which
   is what puts the clock/buttons and the momentum bar on one centre line. Change it
   here and both sides move together — the alternative (nudging one side by a fixed
   offset) silently breaks the moment the icon size or row height changes. */
:root { --lm-band-h: 26px; }

.live-match-row:hover {
    background: var(--live-row-hover, var(--live-row-hover));
}

/* Starred match (long-press a row). An inset edge rather than an inserted icon:
   it costs no layout, so toggling can't reflow the board or shift the odds
   under a finger that's about to tap them. */
.live-match-row.is-fav {
    box-shadow: inset 3px 0 0 var(--accent-green);
}

/* Long-press is invisible until it fires, so the toggle needs a beat of
   feedback at the moment it lands. */
.live-match-row.fav-pulse {
    animation: live-fav-pulse 0.45s ease-out;
}

@keyframes live-fav-pulse {
    0%   { background: rgba(200, 239, 74, 0.22); }
    100% { background: transparent; }
}

/* A long press on mobile otherwise starts a text selection / iOS callout, which
   fights the gesture and looks broken mid-press. */
.live-match-row {
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    user-select: none;
}

.live-fav-toast {
    position: fixed;
    left: 50%;
    bottom: calc(env(safe-area-inset-bottom, 0px) + 78px);
    transform: translateX(-50%) translateY(8px);
    z-index: 400;
    padding: 9px 16px;
    border-radius: 999px;
    background: var(--bg-tertiary, var(--bg-tertiary));
    border: 1px solid var(--border-color, var(--border-color));
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.45);
    color: #fff;
    font-size: 12.5px;
    font-weight: 700;
    white-space: nowrap;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.18s ease, transform 0.18s ease;
}

.live-fav-toast.show {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
}

@media (prefers-reduced-motion: reduce) {
    .live-match-row.fav-pulse { animation: none; }
    .live-fav-toast { transition: none; }
}

/* Match cell — the flexible column: clock + teams, side by side. */
/* Left column: team lines on top, the meta band underneath.
   GRID, not flex-column, and that is deliberate. As a flex column the inherited
   `align-items: center` centres every child HORIZONTALLY, which pushed the meta
   line ~50px in from the left. In a grid `align-items` is the block axis
   (vertical, which is what we want) and `justify-items` defaults to stretch, so
   the band starts flush left without fighting anything.
   The `1fr var(--lm-band-h)` row template is shared with .live-match-oddscol —
   that shared template IS the alignment mechanism. */
.live-match-info {
    flex: 1;
    display: grid;
    grid-template-rows: 1fr var(--lm-band-h, 26px);
    align-items: center;
    padding: var(--live-row-pad, 9px) 12px;
    min-width: 0;
    overflow: hidden;
}

/* Bottom band, left half. */
.live-match-metaline {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

/* Clock. It used to be a fixed 40px column at the far left of the row, sized for
   the longest translated "LIVE" string so the team names all started on the same
   x. It now sits inline on the meta band, so it is content-width and horizontal —
   the team names start at the row's padding edge instead, which is what actually
   made the left edge plumb. */
.live-match-clock {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}

/* Redundant on the live board — every row on it is live, and the band reads
   cleaner as "43:59'  [stats] [bell]". Kept in the DOM rather than removed from
   live.js so the delta patcher and the non-clock sports keep their element. */
.live-match-metaline .live-match-live-tag {
    display: none;
}

.live-match-live-tag {
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.06em;
    line-height: 1;
    white-space: nowrap;
    color: var(--accent-red, #ed4163);
}

.live-match-teams {
    display: flex;
    flex-direction: column;
    gap: 10px;
    /* Grid/flex children holding ellipsised text need `min-width: 0` or they
       refuse to shrink below their content's intrinsic width — but 0 lets them
       vanish ENTIRELY when the fixed columns to the right outgrow the row, which
       is exactly what happened between 600px and 1100px once Momenti, Tregje and
       the actions rail were added (~200px of new columns against a 600px mobile
       breakpoint). The floor guarantees the match is always legible; the columns
       drop out at the breakpoints below instead. */
    min-width: 110px;
    flex: 1;
    /* Ceiling on the match block. Without it this stretches to whatever the row
       has spare — 800px on a 1440px screen — and because .live-match-team-name is
       `flex: 1`, the name box inflates with it and shoves the score to the far
       right edge. Measured on the live board: the longest of 20 team names was
       190px of text, yet the score sat 565px past the end of it — 53% of the row
       was empty, and the eye had to cross the whole screen to pair a team with
       its score.
       Capping here rather than un-stretching the name is deliberate: equal-width
       name boxes are what keep the HOME and AWAY scores on the same x-position.
       Shrink the name to its text and the two scores stagger by the difference in
       name length. So the names still stretch — just not past 360px.
       360 clears the widest name comfortably (190 + 17 kit + gaps + cards + score
       ~= 245), so nothing truncates that did not truncate before; anything longer
       still ellipsises and reveals itself on hover via .lmn-scroll. */
    max-width: 360px;
}

.live-match-team {
    display: flex;
    align-items: center;
    gap: 7px;
    font-size: 13px;
    font-weight: 600;
    min-width: 0;
}

.live-match-team img {
    width: 17px;
    height: 17px;
    object-fit: contain;
    flex-shrink: 0;
}

.live-match-team-name {
    flex: 1;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    /* A long name simply ends in "…", drawn by the browser. It used to slide to
       reveal its tail, which needed JS to measure every name after each render of
       the board (Live._markTruncatedNames): ~600 forced layouts, half a second on
       a desktop CPU and over a second on a phone, on Back to the list and on the
       first push after it. The full name is on the match page. */
    text-overflow: ellipsis;
}

/* Inline, so the parent's text-overflow applies to it (an inline-block child is
   clipped as one box and never gets the "…"). */
.lmn-scroll {
    display: inline;
    white-space: nowrap;
}

/* "GOAL" chip — injected next to the scoring team's name for a few seconds
 * when the overview detects a score change (football). Yellow on black, per
 * the classic scoreboard treatment; pulses so it catches the eye mid-list. */
.live-goal-chip {
    flex-shrink: 0;
    padding: 1px 6px;
    border-radius: 0;
    background: #ffd000;
    color: #111;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    animation: live-goal-chip-in 0.35s ease-out, live-goal-chip-pulse 1.1s ease-in-out 0.35s infinite;
}

@keyframes live-goal-chip-in {
    0%   { transform: scale(0.4); opacity: 0; }
    60%  { transform: scale(1.15); opacity: 1; }
    100% { transform: scale(1); opacity: 1; }
}

@keyframes live-goal-chip-pulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.55; }
}

/* The scoring team's row briefly brightens so the eye lands on it. */
.live-match-team.live-team-scored .live-match-team-name,
.live-match-team.live-team-scored .live-match-score {
    color: #ffd000;
    font-weight: 700;
}

/* Chalked-off goal: same chip slot, red instead of gold, and no infinite pulse
   (a retraction is a one-off statement, not an ongoing "look here"). */
.live-goal-chip.is-disallowed {
    background: var(--accent-red, #e5484d);
    color: #fff;
    animation: live-goal-chip-in 0.35s ease-out;
}
.live-match-team.live-team-disallowed .live-match-team-name,
.live-match-team.live-team-disallowed .live-match-score {
    color: var(--accent-red, #e5484d);
    font-weight: 700;
}

@media (prefers-reduced-motion: reduce) {
    .live-goal-chip { animation: none; }
    .live-goal-chip.is-disallowed { animation: none; }
}

/* Score sits hard right of its own team line, so the two scores stack into a
   readable mini-scoreboard column. `margin-left: auto` (not a fixed column) keeps
   long team names ellipsising against it. */
.live-match-score {
    margin-left: auto;
    padding-left: 0px;
    /* font-family comes from the DISPLAY TYPE block at the end of this file —
       .live-match-score is already listed there. */
    font-size: 13px;
    font-weight: 700;
    line-height: 20px;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
    text-align: center;
    background-color: var(--color-white10p);
    /* A floor, not a fixed width: cricket scores run to "355/7", which a
       20px box cut to "355,". Single digits still sit in the same square. */
    min-width: 20px;
    padding: 0 3px;
    box-sizing: border-box;
    height: 20px;
    white-space: nowrap;
}

/* Third line — now ONLY for sports that carry period scores (tennis sets,
   cricket overs). Football rows never emit it, which is what makes them 2 lines.
   The minute moved to .live-match-clock and the buttons to .live-match-actions. */
.live-match-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 2px;
}

/* Inline red-card indicators next to the team name on each live row */
.live-match-rcards {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    margin-left: 4px;
    vertical-align: middle;
}

.lm-rc {
    display: inline-block;
    width: 7px;
    height: 10px;
    border-radius: 0;
    background: var(--accent-red);
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
}

.lm-rc-more {
    font-size: 10px;
    font-weight: 800;
    color: var(--accent-red);
    margin-left: 2px;
}

/* Stats trigger button on each live row */
.live-match-stats-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    padding: 0;
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    color: var(--accent-green-neon);
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, transform 0.1s;
}

.live-match-stats-btn:hover {
    background: rgba(0, 231, 1, 0.1);
    border-color: var(--accent-green);
}

.live-match-stats-btn:active {
    transform: scale(0.94);
}

/* Floating stats popover (single, repositioned per-click) */
.live-stats-popover {
    /* fixed, not absolute — it's positioned from getBoundingClientRect()'s
       viewport coords. See _showStatsPopover: absolute + window.scrollY only
       works when the WINDOW scrolls, and here an inner container does. */
    position: fixed;
    display: none;
    z-index: 200;
    min-width: 320px;
    max-width: 90vw;
    padding: 10px 12px;
    background: var(--bg-secondary);
    border: 1px solid var(--accent-green-grad);
    border-radius: var(--radius-md);
    box-shadow: 0 10px 24px -8px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.3);
    color: var(--text-primary);
    font-size: 13px;
}

.live-stats-popover.open {
    display: block;
    animation: lspFadeIn 0.15s ease;
}

@keyframes lspFadeIn {
    from { opacity: 0; transform: translateY(2px); }
    to   { opacity: 1; transform: translateY(0); }
}

.lsp-table {
    display: grid;
    column-gap: 6px;
    row-gap: 6px;
    align-items: center;
}

.lsp-corner {
    /* empty cell aligned with team-swatch column above icon headers */
}

.lsp-head,
.lsp-cell {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 22px;
    padding: 2px 4px;
    font-variant-numeric: tabular-nums;
    font-weight: 700;
}

.lsp-head {
    color: var(--text-muted);
    border-bottom: 1px solid var(--border-color);
    padding-bottom: 6px;
}

/* Text-label header (used for basketball / tennis stat columns). Word labels
 * ("Double faults", "1st serve %") wrap over 2–3 centred lines like the
 * reference design — max-width forces the break, the grid row grows to fit. */
.lsp-head-txt {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: var(--text-secondary);
    max-width: 64px;
    white-space: normal;
    text-align: center;
    line-height: 1.25;
}

/* Tennis rows — player names instead of kit swatches (a colour block says
 * nothing about a doubles pair). Ellipsized against the fixed first column. */
.lsp-team-name {
    display: block;
    align-self: center;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-primary);
    text-align: left;
    padding-right: 4px;
}

/* Small raised % suffix on percentage values (FT%, serve %, break points %). */
.lsp-pct {
    font-size: 9px;
    opacity: 0.8;
    margin-left: 1px;
    vertical-align: 1px;
}

.lsp-cell {
    color: var(--text-primary);
    font-size: 13px;
}

.lsp-team-swatch {
    display: block;
    justify-self: center;
    width: 18px;
    height: 18px;
    border-radius: 0;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.15) inset;
}

/* Arrow pointing at the trigger button */
.lsp-arrow {
    position: absolute;
    width: 10px;
    height: 10px;
    background: var(--bg-secondary);
    border: 1px solid var(--accent-green-grad);
    transform: rotate(45deg);
    z-index: -1;
}

.live-stats-popover[data-placement="top"] .lsp-arrow {
    bottom: -6px;
    border-top: none;
    border-left: none;
}

.live-stats-popover[data-placement="bottom"] .lsp-arrow {
    top: -6px;
    border-bottom: none;
    border-right: none;
}

/* Mini cards inside the popover (yellow / red columns) */
.lsp-card {
    display: inline-block;
    width: 9px;
    height: 12px;
    border-radius: 0;
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3);
}
.lsp-card-y { background: var(--gold); }
.lsp-card-r { background: var(--accent-red); }

/* Shared statistics icons — the /img/statistics_icon/ set (22×22, pre-coloured),
 * used by the stats popover, the match-detail Statistics panel and the homepage
 * live-now strip (emitted by Live.statIcon; size comes from width/height attrs). */
.stat-ico {
    display: block;
    flex-shrink: 0;
}
/* The pure-gray glyphs (attacks / dangerous attacks / possession) were drawn
 * for a light background — brighten them on our dark surfaces. The coloured
 * icons (targets / corner / cards) render exactly as exported. Also applies to
 * the SVG <image> gauge-centre icons in the detail Statistics panel. */
.stat-ico-dim {
    filter: brightness(2.1);
}

/* Minute now heads its own column instead of sitting inline in a meta line, so
   it can carry the display face at score weight — it reads as the row's clock. */
.live-match-minute {
    font-size: 13px;
    font-weight: 700;
    line-height: 1.1;
    color: #ffffff;
    font-variant-numeric: tabular-nums;
    margin-top: 5px;
}

.live-match-minute.halftime {
    color: var(--text-muted);
}

.live-match-periods {
    font-size: 10px;
    color: var(--text-muted);
    font-weight: 500;
    letter-spacing: 0.5px;
}

/* In the clock column (tennis/cricket, which have no minute) the period score
   IS the row's clock — so it takes the minute's weight and size, not the muted
   footnote styling it had when it sat on a third line. */
.live-match-periods--clock {
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 700;
    line-height: 1.1;
    color: #ffffff;
    letter-spacing: 0.2px;
    font-variant-numeric: tabular-nums;
    margin-top:5px;
}

/* Basketball is the one sport with BOTH a running clock and a period score in this
   column. The adjacent-sibling selector matches only "periods that follow a minute",
   which no other sport produces — tennis/cricket have no .live-match-minute, so their
   full-size treatment above is untouched. Demoted to a secondary line so the minute
   stays the primary read, and sized to fit the 40px column ("25:20" ≈ 30px at 11px). */
.live-match-minute + .live-match-periods--clock {
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    margin-top: 1px;
}

.live-match-stats-icon {
    color: var(--text-muted);
    font-size: 12px;
    cursor: pointer;
}



.live-odd-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    /* Width is a token because THREE things must agree: this button, the
       `1 X 2` header spans above it, and the O/U header's label span. The mobile
       block narrows the token rather than any one of them. */
    width: var(--odd-w, 58px);
    flex-shrink: 0;
    /* 1a "dense board": 65px -> 44px. The 1/X/2 column header already labels
       these, so the button only carries the price; 44px keeps a comfortable tap
       target while fitting ~2.4x the matches per screen. */
    height: var(--odd-h, 44px);
    padding: 4px;
    background: var(--bg-odds);
    /* Transparent, not none: the hover rule below only sets border-color, and
       with no border there was nothing to colour — the live prices never got
       the green edge every other price shows. Fixed height + border-box, so
       the button stays 44px. */
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--accent-odds);
    font-size: 15px;
    font-weight: 900;
    cursor: pointer;
    font-family: inherit;
    transition: all 0.15s;
}

@media (hover: hover) {
    .live-odd-btn:hover {
        background: var(--bg-hover);
        border-color: var(--accent-green);
    }
}

.live-odd-btn.selected {
    background: var(--blue-alt);
    border-color: var(--blue-alt);
    color: white;
}

.live-odd-btn.locked {
    background: var(--bg-tertiary);
    color: var(--text-muted);
    cursor: default;
}

/* Odds change animations — live list & match-detail buttons */
.live-odd-btn.odds-up,
.md-odd-btn.odds-up {
    animation: oddBtnFlashUp 2s ease;
    position: relative;
}

.live-odd-btn.odds-down,
.md-odd-btn.odds-down {
    animation: oddBtnFlashDown 2s ease;
    position: relative;
}

.live-odd-btn.odds-up::after,
.md-odd-btn.odds-up::after,
.live-odd-btn.odds-down::after,
.md-odd-btn.odds-down::after {
    content: '';
    position: absolute;
    top: 3px;
    right: 4px;
    width: 0;
    height: 0;
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    animation: oddArrowFade 2s ease forwards;
    pointer-events: none;
}

.live-odd-btn.odds-up::after,
.md-odd-btn.odds-up::after {
    border-bottom: 5px solid var(--accent-green);
}

.live-odd-btn.odds-down::after,
.md-odd-btn.odds-down::after {
    border-top: 5px solid var(--accent-red);
}

@keyframes oddBtnFlashUp {
    0% {
        background: var(--bg-primary);
        color: var(--accent-odds);
        box-shadow: inset 0 0 0 0 var(--accent-green);
    }
    15% {
        background: rgba(0, 231, 1, 0.22);
        color: var(--accent-green);
        box-shadow: inset 0 0 0 1px var(--accent-green);
    }
    50% {
        background: rgba(0, 231, 1, 0.1);
        color: var(--accent-green);
        box-shadow: inset 0 0 0 1px rgba(0, 231, 1, 0.4);
    }
    100% {
        background: var(--bg-primary);
        color: var(--accent-odds);
        box-shadow: inset 0 0 0 0 var(--accent-green);
    }
}

@keyframes oddBtnFlashDown {
    0% {
        background: var(--bg-primary);
        color: var(--accent-odds);
        box-shadow: inset 0 0 0 0 var(--accent-red);
    }
    15% {
        background: rgba(237, 65, 99, 0.22);
        color: var(--accent-red);
        box-shadow: inset 0 0 0 1px var(--accent-red);
    }
    50% {
        background: rgba(237, 65, 99, 0.1);
        color: var(--accent-red);
        box-shadow: inset 0 0 0 1px rgba(237, 65, 99, 0.4);
    }
    100% {
        background: var(--bg-primary);
        color: var(--accent-odds);
        box-shadow: inset 0 0 0 0 var(--accent-red);
    }
}

@keyframes oddArrowFade {
    0%   { opacity: 0; transform: translateY(2px); }
    15%  { opacity: 1; transform: translateY(0); }
    80%  { opacity: 1; transform: translateY(0); }
    100% { opacity: 0; transform: translateY(-2px); }
}

/* Color the inner value span on the match-detail button during the flash */
.md-odd-btn.odds-up .md-odd-value {
    animation: oddValueColorUp 2s ease;
}

.md-odd-btn.odds-down .md-odd-value {
    animation: oddValueColorDown 2s ease;
}

@keyframes oddValueColorUp {
    0%   { color: var(--accent-odds); }
    15%  { color: var(--accent-green); }
    50%  { color: var(--accent-green); }
    100% { color: var(--accent-odds); }
}

@keyframes oddValueColorDown {
    0%   { color: var(--accent-odds); }
    15%  { color: var(--accent-red); }
    50%  { color: var(--accent-red); }
    100% { color: var(--accent-odds); }
}

/* Keep the up/down treatment readable when the button is also selected */
.live-odd-btn.selected.odds-up,
.live-odd-btn.selected.odds-down,
.md-odd-btn.selected.odds-up,
.md-odd-btn.selected.odds-down {
    animation: none;
}

.md-odd-btn.selected.odds-up .md-odd-value,
.md-odd-btn.selected.odds-down .md-odd-value {
    animation: none;
}

/* ---- Live odds change: new value + directional chevron ----
   Applied by OddsFormat.flashChange() to the value element on every live-odds
   surface (live list buttons, Live Now strip, match-detail markets). Transient
   (~3.5s) then reverts to the plain value. The struck-through old value was
   dropped by request — arrow direction + color tell the story. */
.odd-chg {
    white-space: nowrap;
}

.odd-chg .oc-new {
    font-weight: 800;
}

.odd-chg .oc-chev {
    display: inline-flex;
    align-items: center;
    vertical-align: middle;
    margin-left: 2px;
}

.odd-chg-up .oc-new,
.odd-chg-up .oc-chev {
    color: var(--accent-green-neon);
}

.odd-chg-down .oc-new,
.odd-chg-down .oc-chev {
    color: var(--accent-red);
}

/* Narrow live-list 1X2 / O-U columns (55-88 x 60px) and the pre-match inline
   rows: center the value and flash the whole button background green/red. (Was
   a 2-row grid stacking the struck-through old value below — removed with the
   old-value display.) */
.live-odd-btn.odd-chg,
.odd-btn-inline.odd-chg {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 3px;
    overflow: hidden;
}

/* The rise arrows can't sit BESIDE the price in these columns: they take ~17px
   of a 45px usable width on a phone, so not even "2.28" fits, and `overflow:
   hidden` CLIPS the digits ("100.00" silently read "100.0" — why they were
   hidden here once). Above/below the price they read as a thin stalk next to a
   15px/900 number. So they go BEHIND it, big and faint — a filigree, the button
   itself becomes the arrow: nothing moves, any price length fits, and the
   "No Goal" caption sits over it like the price does. Fades in to its 38%
   rather than sliding sideways like the side-by-side ones. */
.live-odd-btn.odd-chg .oc-chev.oc-rise,
.odd-btn-inline.odd-chg .oc-chev.oc-rise {
    position: absolute;
    inset: 0;
    width: 26px;
    height: 36px;
    margin: auto;
    opacity: 0.38;
    animation-name: ocFiligreeIn;
}
.live-odd-btn.odd-chg .oc-chev.oc-rise svg,
.odd-btn-inline.odd-chg .oc-chev.oc-rise svg {
    width: 26px;
    height: 12px;
    margin: -0.5px 0;
}
/* The wide desktop prices (88px): the filigree grows with the button, to about
   the same share of it as on a 55px phone button. At 26px it was narrower than
   the price, so it read as a small cap and beard around the number instead of
   an arrow behind it. */
@media (min-width: 1100px) {
    .live-odd-btn.odd-chg .oc-chev.oc-rise,
    .odd-btn-inline.odd-chg .oc-chev.oc-rise {
        width: 40px;
        height: 54px;
    }
    .live-odd-btn.odd-chg .oc-chev.oc-rise svg,
    .odd-btn-inline.odd-chg .oc-chev.oc-rise svg {
        width: 40px;
        height: 18.5px;
        margin: -0.75px 0;
    }
}
.live-odd-btn.odd-chg .oc-new,
.live-odd-btn.odd-chg .live-odd-cap,
.odd-btn-inline.odd-chg .oc-new {
    position: relative;
    z-index: 1;
}
/* On a selected (blue) price the resting arrows go white, like the price. */
.live-odd-btn.selected.odd-chg .oc-chev.oc-rise,
.odd-btn-inline.selected.odd-chg .oc-chev.oc-rise {
    --rise-rgb: 255 255 255;
}
@keyframes ocFiligreeIn {
    from { opacity: 0; }
    to   { opacity: 0.38; }
}

.live-odd-btn.odd-chg-up,
.odd-btn-inline.odd-chg-up {
    background: rgba(0, 202, 81, 0.16);
    animation: oddBtnBgPulseUp 0.55s ease;
}

.live-odd-btn.odd-chg-down,
.odd-btn-inline.odd-chg-down {
    background: rgba(237, 65, 99, 0.16);
    animation: oddBtnBgPulseDown 0.55s ease;
}

/* A selected price stays blue while it flashes. The two tints above tie with
   .live-odd-btn.selected on specificity and come later, so every price move
   (~3.5s each, constant on a live board) painted a picked odd green or red
   instead of the blue that says it is in the slip. The direction moves to a
   ring, and the price stays white: red or neon green on that blue is barely
   legible. The match-detail button already keeps its blue (its flash
   animations are switched off when selected), so it only needs the text. */
.live-odd-btn.selected.odd-chg-up,
.live-odd-btn.selected.odd-chg-down,
.odd-btn-inline.selected.odd-chg-up,
.odd-btn-inline.selected.odd-chg-down {
    background: var(--blue-alt);
    animation: none;
}
.live-odd-btn.selected.odd-chg-up,
.odd-btn-inline.selected.odd-chg-up   { box-shadow: inset 0 0 0 2px var(--accent-green-neon); }
.live-odd-btn.selected.odd-chg-down,
.odd-btn-inline.selected.odd-chg-down { box-shadow: inset 0 0 0 2px var(--accent-red); }
.live-odd-btn.selected.odd-chg .oc-new,
.odd-btn-inline.selected.odd-chg .oc-new,
.odd-btn-card.selected .odd-chg .oc-new,
.odd-btn-card.selected .odd-chg .oc-chev,
.md-odd-btn.selected .odd-chg .oc-new,
.md-odd-btn.selected .odd-chg .oc-chev {
    color: #fff;
}

@keyframes oddBtnBgPulseUp {
    0%   { background: rgba(0, 202, 81, 0.42); }
    100% { background: rgba(0, 202, 81, 0.16); }
}

@keyframes oddBtnBgPulseDown {
    0%   { background: rgba(237, 65, 99, 0.42); }
    100% { background: rgba(237, 65, 99, 0.16); }
}

/* A flash restored onto a rebuilt element (OddsFormat.restoreFlashes) carries on
   where it was: no second entrance fade and no second background pulse. The
   markets rebuild mid-flash, and replayed, those two read as the arrows blinking
   out and back in. After the pulse and filigree rules on purpose (same weight). */
.odd-chg.oc-restored,
.odd-chg.oc-restored .oc-chev,
.odd-chg.oc-restored .oc-chev.oc-rise {
    animation: none;
}

/* Bet Boost fills its price with a gradient through transparent text, which
   would swallow the flash colour; while it flashes the price takes the colour.
   A selected one stays white on its blue. */
.bb-odd-new.odd-chg {
    background: none;
    -webkit-text-fill-color: currentColor;
}
.bb-odd.selected .bb-odd-new.odd-chg .oc-new,
.bb-odd.selected .bb-odd-new.odd-chg .oc-chev {
    color: #fff;
}

/* ---- Rise arrows: three bold chevrons in a column, on a 5s loop ----
   After the price-boost arrows we were shown: 13x6 chevrons overlapping by half
   a pixel, resting as a gradient (top lit, middle at a third, bottom faint) so
   the column reads as "up" even standing still. Twice a loop a wave goes
   through it: a chevron dims, flashes yellow, fades out through a darker yellow
   and comes back by way of a green flash. The three keyframe sets are that
   reference's timing, measured frame by frame from a screen recording (each 2%
   step is 100ms).
   Levels are the colour at an alpha, not opacity: a colour with alpha
   interpolates premultiplied, so a dim green brightening into yellow passes
   through olive the way the reference does (opacity on top of a changing colour
   went through green instead).
   --rise-rgb is the resting colour, --flash-rgb the flash, as "r g b":
   - .bb-rise, beside the Bet Boost wordmark: the wordmark's mint, always on;
   - .oc-rise, beside a price that moved (OddsFormat._paintFlash): mint for a
     rise; for a fall the column turns over, red with an amber flash. */
.oc-rise,
.bb-rise {
    --rise-rgb: 40 255 187;
    --flash-rgb: 230 250 14;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 1em;            /* the 17px column never grows the line it sits in */
    line-height: 0;
}
.odd-chg .oc-chev.oc-rise {
    margin-left: 4px;
}
.odd-chg-down .oc-chev.oc-rise {
    --rise-rgb: 237 65 99;  /* --accent-red */
    --flash-rgb: 255 177 61;
    flex-direction: column-reverse;
}
.odd-chg .oc-chev.oc-rise svg,
.bb-rise svg {
    display: block;
    flex: none;
    width: 13px;
    height: 6px;
    margin: -0.25px 0;
    fill: currentColor;
    animation: 5s ease-in-out infinite both;
}
.odd-chg-down .oc-chev.oc-rise svg { transform: rotate(180deg); }
/* A price flash lasts 3.5s, not a loop. It starts 0.3s in, so the wave runs
   through the arrows right after the price moves (0.4-1.4s) and they rest after,
   until they go. (Started 3.4s in, the flash sat still for two seconds and the
   pair's wave came as the arrows were leaving — a burst, a dark moment, gone.) */
.odd-chg .oc-chev.oc-rise svg {
    animation-delay: calc(-0.3s - var(--rise-t, 0ms));
}
/* Resting levels, which reduced motion shows standing still. */
.odd-chg .oc-chev.oc-rise svg:nth-child(1),
.bb-rise svg:nth-child(1) { color: rgb(var(--rise-rgb));        animation-name: rise1; }
.odd-chg .oc-chev.oc-rise svg:nth-child(2),
.bb-rise svg:nth-child(2) { color: rgb(var(--rise-rgb) / 0.35); animation-name: rise2; }
.odd-chg .oc-chev.oc-rise svg:nth-child(3),
.bb-rise svg:nth-child(3) { color: rgb(var(--rise-rgb) / 0.15); animation-name: rise3; }

@keyframes rise1 {      /* top: lit; dims, then flashes just after the bottom */
    0%, 14%, 34%, 100% { color: rgb(var(--rise-rgb)); }
    16%      { color: rgb(var(--rise-rgb) / 0.35); }
    18%, 20% { color: rgb(var(--rise-rgb) / 0.15); }
    22%      { color: rgb(var(--rise-rgb) / 0.35); }
    24%      { color: rgb(var(--flash-rgb)); }
    26%      { color: rgb(var(--flash-rgb) / 0.33); }
    28%, 32% { color: rgb(var(--flash-rgb) / 0.15); }
}
@keyframes rise2 {      /* middle: a third; has the late wave to itself */
    0%, 73%, 93%, 100% { color: rgb(var(--rise-rgb) / 0.35); }
    75%, 79% { color: rgb(var(--rise-rgb) / 0.15); }
    81%      { color: rgb(var(--flash-rgb)); }
    83%      { color: rgb(var(--flash-rgb) / 0.33); }
    85%, 89% { color: rgb(var(--flash-rgb) / 0.15); }
    91%      { color: rgb(var(--rise-rgb)); }
}
@keyframes rise3 {      /* bottom: faint; flashes first */
    0%, 18%, 34%, 100% { color: rgb(var(--rise-rgb) / 0.15); }
    20%      { color: rgb(var(--flash-rgb)); }
    22%      { color: rgb(var(--flash-rgb) / 0.33); }
    24%, 28% { color: rgb(var(--flash-rgb) / 0.15); }
    30%      { color: rgb(var(--rise-rgb)); }
    32%      { color: rgb(var(--rise-rgb) / 0.35); }
}

/* On a selected (blue) button the resting arrows go white, like the price. */
.odd-btn-card.selected .odd-chg .oc-rise,
.md-odd-btn.selected .odd-chg .oc-rise,
.bb-odd.selected .bb-odd-new.odd-chg .oc-rise {
    --rise-rgb: 255 255 255;
}

/* Match-detail prices sit right-aligned in a row (label left, price right, 6px
   of padding). Beside the price there is no room, so the arrows pushed it 17px
   left for the flash and back after. They take the price's LEFT instead, in
   padding the value grows into: the price itself never moves, and a long label
   gives way (ellipsis) rather than being covered. */
.md-odd-value.odd-chg {
    position: relative;
    padding-left: 21px;
}
.md-odd-value.odd-chg .oc-chev.oc-rise {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    height: 17px;
    margin: auto 0;
}

.section-header h3.bb-heading {
    gap: 6px;
}

/* Chevron eases in so the change reads as motion, not a hard swap. */
.odd-chg .oc-chev {
    animation: ocChgIn 0.22s ease both;
}

@keyframes ocChgIn {
    from { opacity: 0; transform: translateX(-3px); }
    to   { opacity: 1; transform: none; }
}

/* Keyboard focus rings on odds controls (skill UX pass: focus-states / keyboard-nav).
   The global reset drops default outlines, so re-assert a visible one for :focus-visible. */
.live-odd-btn:focus-visible,
.live-now-odd:focus-visible,
.md-odd-btn:focus-visible {
    outline: 2px solid var(--accent-odds);
    outline-offset: -2px;
}

.bb-odd:focus-visible {
    outline: 2px solid var(--accent-green);
    outline-offset: -2px;
}

@media (prefers-reduced-motion: reduce) {
    .odd-chg .oc-chev.oc-rise svg:nth-child(n),
    .bb-rise svg:nth-child(n) {
        animation: none;
    }

    .odd-chg .oc-chev,
    .live-odd-btn.odd-chg-up,
    .live-odd-btn.odd-chg-down,
    .odd-btn-inline.odd-chg-up,
    .odd-btn-inline.odd-chg-down {
        animation: none;
    }

    /* No hover-lift / slide when the user asked for reduced motion. */
    .bet-boost-card,
    .bet-boost-card:hover {
        transition: none;
        transform: none;
    }
}

/* Live league favourite */
.live-league-fav {
    color: var(--text-muted);
    cursor: pointer;
    transition: color 0.15s;
    display: flex;
    align-items: center;
}

.live-league-fav:hover {
    color: var(--accent-orange);
}

.live-league-fav.fav-active {
    color: var(--accent-orange);
}

/* Live league header */
/* 1a dense board: the group header was 45px tall with a 5px slab under it — as
   much vertical weight as a match row, so a league holding one match read as
   mostly chrome. 34px + a hairline keeps it clearly a header without competing
   with the rows it labels. */
/* Sticky league headers: the league name stays under the top chrome while its
   own matches scroll past, and the next league pushes it out when it arrives.
   Two things have to be true for that to work here.

   1. .live-league-group must use `overflow: clip`, not `hidden` — see the note on
      that rule further down. `hidden` makes the group a scroll container and
      pinning silently does nothing.

   2. The offset is the app header PLUS --live-list-pin, which Live._syncListPin
      keeps equal to the height of the goals strip whenever that strip is on
      screen. The strip is itself sticky at the header's edge with a higher
      z-index, so a header pinned at the plain header height slid underneath and
      disappeared. The strip's height is not a constant — it collapses, expands,
      and is absent for non-football — so this cannot be a hardcoded number. */
.live-league-header {
    position: sticky;
    top: calc(var(--header-height, 60px) + var(--live-bar-pin, 0px) + var(--live-list-pin, 0px));
    /* Under the goals strip (45), the sports bar (46) and the app header (100), over the rows. */
    z-index: 40;
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* NO right padding: the header's column cells must end exactly where the
       row's do, and the row has none. 12px here put every 1/X/2 label 12px left
       of the buttons it labels. The trailing actions-header cell supplies the
       gutter instead, matching .live-match-actions. */
    padding: 6px 0 6px 12px;
    /* OPAQUE BASE, required now that the header is sticky. The sport tint below
       is a gradient of 60%/20% alpha — fine while the header scrolled with its
       rows, but pinned it let the rows underneath show straight through it. The
       gradient composites over this instead of over the page. */
    background-color: var(--bg-tertiary, var(--bg-tertiary));
    font-size: 13px;
    font-weight: 700;
    color: #ffffff;
    height: 30px;
    border-bottom: 1px solid var(--border-subtle, var(--border-subtle));
    border-radius: var(--radius-sm);
    /* Tinted per sport — the hue comes from --lg-tint on the enclosing
       .live-league-group (see the data-sport-id block below). Football keeps the
       original green; everything else gets its own so the sport is readable from
       the header colour alone. Same two stops as before (60% then 20% alpha),
       just driven by a variable instead of a literal. */
    background-image: linear-gradient(90deg,
        color-mix(in srgb, var(--lg-tint, #448238) 60%, transparent) 0%,
        color-mix(in srgb, var(--lg-tint, #448238) 20%, transparent) 95%);
}

/* ---- Per-sport league-header tint -------------------------------------------
   Keyed on the DOMAIN sport id (the same ids VideoStreamService.SportKeyMap
   uses), set on .live-league-group by Live's group builder. A league group is
   single-sport, so one value per group is correct.
   Football is deliberately unchanged. The rest are picked to read as the sport
   rather than as decoration — leather, court, ice, clay. Where two sports share
   an obvious colour (cricket, rugby and golf are all "grass" like football) the
   later ones are pushed off the green so the header still tells you which board
   you are on; distinguishability beats literalism here.
   Unknown / missing id falls through to the football green via the var default,
   so a new sport is never left with an unstyled header. */
.live-league-group[data-sport-id="1"]  { --lg-tint: #448238; }  /* Football — pitch green (unchanged) */
.live-league-group[data-sport-id="2"]  { --lg-tint: #B4632B; }  /* Basketball — operator-chosen */
.live-league-group[data-sport-id="3"]  { --lg-tint: #3C679E; }  /* Tennis — operator-chosen */
.live-league-group[data-sport-id="7"]  { --lg-tint: #b02a2a; }  /* Formula 1 — racing red */
.live-league-group[data-sport-id="8"]  { --lg-tint: #a83c1c; }  /* Superbike */
.live-league-group[data-sport-id="9"]  { --lg-tint: #7a4a24; }  /* American football — pigskin brown */
/* Ice hockey and volleyball were both mid-blue (#2f7fa8 / #2f5f9e) back when
   tennis was yellow. Tennis is #3C679E now, and #2f5f9e in particular was almost
   the same colour — which defeats the point of tinting by sport. Hockey moves to
   a colder cyan (still reads as ice, further from tennis) and volleyball off the
   blue lane entirely. Change either back if you prefer; the tennis/volleyball
   pair is the one that genuinely collided. */
.live-league-group[data-sport-id="10"] { --lg-tint: #2f9cb8; }  /* Ice hockey — rink cyan */
.live-league-group[data-sport-id="11"] { --lg-tint: #6b52a8; }  /* Volleyball — off the blue lane */
.live-league-group[data-sport-id="12"] { --lg-tint: #1f6f7a; }  /* Table tennis — table teal */
.live-league-group[data-sport-id="14"] { --lg-tint: #a8457a; }  /* Handball — was #4a63b0, 23 away from tennis */
.live-league-group[data-sport-id="16"] { --lg-tint: #9c2b2b; }  /* Boxing — glove red */
.live-league-group[data-sport-id="17"] { --lg-tint: #6f7f8c; }  /* Baseball — was navy #3f5f8a, 22 away from tennis */
.live-league-group[data-sport-id="18"] { --lg-tint: #2f7a5c; }  /* Cricket — deeper, bluer green */
.live-league-group[data-sport-id="19"] { --lg-tint: #2f7a70; }  /* Aussie rules */
.live-league-group[data-sport-id="20"] { --lg-tint: #5a6b2f; }  /* Rugby — olive */
.live-league-group[data-sport-id="21"] { --lg-tint: #6b8a3a; }  /* Golf — fairway */
.live-league-group[data-sport-id="22"] { --lg-tint: #a8552a; }  /* Rally */
.live-league-group[data-sport-id="23"] { --lg-tint: #a8452a; }  /* MotoGP */
.live-league-group[data-sport-id="24"] { --lg-tint: #1f6b47; }  /* Snooker — baize */
.live-league-group[data-sport-id="25"] { --lg-tint: #97851f; }  /* Cycling — maillot jaune */
.live-league-group[data-sport-id="26"] { --lg-tint: #6b4a8a; }  /* Speciale — outrights, no sport to echo */
.live-league-group[data-sport-id="31"] { --lg-tint: #8a2f45; }  /* MMA — cage red */

/* Tennis: the court the tournament is played on (Live._courtOf, from the feed's
   "Court=" stat) overrides the sport tint, so a clay event reads as clay at a
   glance — surface is half of a tennis price. Hard keeps the tennis blue it already
   is (the colour of a hard court); after the sport block so it wins the tie. */
.live-league-group[data-court="clay"]   { --lg-tint: var(--court-clay); }
.live-league-group[data-court="grass"]  { --lg-tint: var(--court-grass); }
.live-league-group[data-court="indoor"] { --lg-tint: var(--court-indoor); }
.live-league-court {
    flex-shrink: 0;
    padding: 2px 6px;
    border-radius: var(--radius-sm);
    background: color-mix(in srgb, var(--bg-primary) 40%, transparent);
    color: var(--text-primary);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    line-height: 1.3;
}
/* A phone header has room for the league name or the label, rarely both. Hard is
   the everyday surface and already the plain tennis blue, so only the exceptions
   (clay, grass, indoor) are named there — and the label gives way before the name. */
@media (max-width: 600px) {
    .live-league-group[data-court="hard"] .live-league-court { display: none; }
    .live-league-court {
        flex-shrink: 10;
        min-width: 0;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
    }
}

.live-league-header-left {
    display: flex;
    align-items: center;
    gap: 6px;
    flex: 1;
    min-width: 0;
}

.live-league-name {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

/* Deliberately NO wide-viewport override here. There used to be one letting the
   name wrap above 901px, which turned a long league ("UEFA Women s Champions
   League Qualifying") into two lines and made that one header taller than every
   other — the board's rhythm broke wherever a verbose league appeared. One line
   with an ellipsis at every width; the full name is on the title attribute. */

/* Horizontal padding MUST mirror `.live-match-odds` (4px) — the header cells are
   centred over the buttons, so any padding the row has and the header doesn't
   shifts every label off its column. */
.live-league-odds-header {
    display: flex;
    gap: 2px;
    padding: 0 4px;
}

.live-league-odds-header span {
    width: var(--odd-w, 58px);
    flex-shrink: 0;
    text-align: center;
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
}

/* O/U + Corner O/U header cells. Width MUST match their data columns
   (.live-match-ou / .live-match-cou = 28px line slot + 2× 58px buttons), so the
   right-aligned header stays in line with the odds. */
.live-league-ou-header,
.live-league-cou-header {
    display: flex;
    gap: 2px;
    align-items: center;
    /* MIRROR .live-match-ou's box, don't approximate it. That rule is
       `padding: 4px 4px 4px 0`, so its buttons are inset 4px from the right.
       This used to carry `margin-left: 4px` instead — which pushes the cell the
       WRONG WAY, so the two 4px offsets added up and the "O/U" label sat 4px
       right of the two buttons it labels. Both cells right-align their contents,
       so matching the right inset is what puts the label over the buttons.
       Measured after: label 1021-1139, buttons 1021-1139. */
    padding-right: 4px;
}
.live-ouh-spacer {
    width: 28px;            /* matches .live-ou-line */
    flex-shrink: 0;
}
/* An extra column holding a three-way market (1X2, next goal, double chance) has no
   line slot — three buttons, so its header spans three. */
.live-league-ou-header.is-3 .live-ouh-label,
.live-league-cou-header.is-3 .live-ouh-label { width: calc(3 * var(--odd-w, 58px) + 4px); }
/* From 1100px both extra columns show; two three-way ones at the full 88px token
   took 120px from the team names (down to ~60px, clipped). There, a three-way column
   keeps a two-way column's width (line slot + 2 buttons) and splits it three ways. */
@media (min-width: 1101px) {
    .live-match-ou.is-3 .live-odd-btn,
    .live-match-cou.is-3 .live-odd-btn { width: calc((2 * var(--odd-w, 58px) + 28px) / 3); }
    .live-league-ou-header.is-3 .live-ouh-label,
    .live-league-cou-header.is-3 .live-ouh-label { width: calc(2 * var(--odd-w, 58px) + 32px); }
}
.live-ouh-label {
    width: calc(2 * var(--odd-w, 58px) + 2px);   /* 2 buttons + the 2px gap */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 3px;
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
}

/* `Tregje` — live market count per row. The cell is always present so the column
   stays plumb even while some rows have no count (and on an SP that predates
   sql/live-perf/04_market_count, where every row is empty). */
.live-match-mkt-count {
    width: 52px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding-right: 15px;
}

.live-mkt-count-val {
    font-size: 11.5px;
    font-weight: 700;
    color: var(--accent-green);
    font-variant-numeric: tabular-nums;
}

/* "Closed" in the Tregje slot when the count is 0. Muted, not green: a count is
   an invitation ("+141 more to bet on"), this is the opposite, and it must not
   read as another actionable figure. Sized down and allowed to shrink so the
   longest translation still fits the 52px column. */
.live-mkt-count-closed {
    font-size: 10px;
    font-weight: 600;
    color: var(--text-muted);
    letter-spacing: 0.2px;
    white-space: nowrap;
}

.live-league-mkt-header {
    width: 52px;
    flex-shrink: 0;
    text-align: right;
    padding-right: 6px;
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
}

/* Only where the market columns are (football, basketball), like the other extended columns. */
.live-league-no-ou .live-match-mkt-count {
    display: none;
}

/* --- Live row "pulse" (football): the scout line (stnScout) and xG ---------
   Narrow rows: xG per team between the red cards and the score, and the scout
   line as a pill in the band after the row buttons (just the event on a phone;
   the team joins it when there is room, the kit always says whose it is).
   Wide rows (the info block has room past the 360px team block): both move into
   that empty middle — the pill on top, an xG split bar under it. Markup is
   always present (hidden while empty) so Live._patchRowPulse can fill it. */
.live-match-info--pulse {
    container: lminfo / inline-size;
    position: relative;
}
.live-match-xg {
    flex-shrink: 0;
    width: 28px;
    text-align: right;
    font-size: 10.5px;
    font-weight: 700;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}
.live-match-xg.is-hi { color: var(--accent-green); }
.live-match-xg[hidden] { display: none; }
.live-match-scout {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    min-width: 0;
    max-width: 100%;
    height: 22px;
    box-sizing: border-box;
    padding: 0 8px 0 7px;
    border-radius: 999px;
    background: var(--bg-input);
    color: var(--text-primary);
    font-size: 11px;
    line-height: 1;
}
.live-match-scout[hidden] { display: none; }
/* The scout line is the user's choice (Settings): off until they turn it on, which puts
   .live-scout-on on <html> (Live.setScoutOn, js/live.js). */
html:not(.live-scout-on) .live-match-scout { display: none; }
.lms-dot { width: 7px; height: 7px; flex-shrink: 0; border-radius: 50%; background: var(--bg-lightg); }
/* The team's kit says whose event it is (a dot only for whole-match states). */
.lms-kit { width: 14px; height: 14px; flex-shrink: 0; object-fit: contain; }
/* In the band there is room for kit + event word only: with a kit the event
   icon steps aside (the wide pill keeps both). */
.lms-inline .lms-kit ~ .lms-ico { display: none; }
.lms-ico { width: 13px; height: 13px; flex-shrink: 0; }
.lms-text { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.lms-text b { font-weight: 700; }
.lms-who { color: var(--text-muted); }
.live-match-scout.is-hot { background: color-mix(in srgb, var(--accent-red) 16%, transparent); color: var(--accent-red-soft); }
.live-match-scout.is-goal { background: color-mix(in srgb, var(--gold) 18%, transparent); color: var(--gold); }
.live-match-metaline .lms-inline { flex: 0 1 auto; }
.lms-inline .lms-team,
.lms-inline .lms-who { display: none; }
.live-match-pulse { display: none; }
.live-match-xgbar { display: flex; align-items: center; gap: 10px; font-variant-numeric: tabular-nums; }
.live-match-xgbar[hidden] { display: none; }
.lxb-h, .lxb-a { width: 34px; flex-shrink: 0; font-size: 13px; font-weight: 800; }
.lxb-h { text-align: right; color: var(--text-primary); }
.lxb-a { color: var(--text-muted); }
.lxb-track { flex: 1; min-width: 40px; height: 5px; display: flex; overflow: hidden; background: var(--text-muted); }
.lxb-fill { display: block; height: 100%; background: var(--accent-green); border-right: 2px solid var(--bg-secondary); }
.lxb-lbl { flex-shrink: 0; font-size: 10px; font-weight: 800; letter-spacing: 0.04em; color: var(--bg-lightg); }

/* A roomier band (tablet widths): the team joins the event. */
@container lminfo (min-width: 420px) {
    .lms-inline .lms-team { display: inline; }
}
/* Wide rows: the empty middle holds the pulse; the band and the per-team
   cells step aside. 396px = 12px padding + the 360px team block + 24px air. */
@container lminfo (min-width: 620px) {
    .live-match-info--pulse .live-match-pulse {
        position: absolute;
        top: 0;
        bottom: 0;
        left: 396px;
        right: 16px;
        display: flex;
        flex-direction: column;
        justify-content: center;
        gap: 10px;
        min-width: 0;
    }
    .live-match-info--pulse .lms-inline,
    .live-match-info--pulse .live-match-xg { display: none; }
    .lms-wide {
        align-self: flex-start;
        height: 30px;
        padding: 0 12px 0 10px;
        border-radius: var(--radius-md);
        font-size: 13px;
    }
    .lms-wide .lms-ico { width: 16px; height: 16px; }
    .lms-wide .lms-kit { width: 18px; height: 18px; }
    .lms-wide .lms-who { font-size: 12px; }
}

/* Stats button + notification bell. These have moved twice: originally on a meta
   line under the team names, then out to a 60px rail at the row's right edge for
   the dense two-line row, and now back onto the meta band beside the clock. The
   90px row is what pays for the band; in exchange the right-hand rail is gone, so
   the odds/O-U columns get those 60px back. */
.live-match-actions {
    display: flex;
    align-items: center;
    gap: 0px;
    flex-shrink: 0;
}

/* Both buttons on ONE line and the SAME size. They were 26x26 and 30x30 with
   different baselines — invisible when they were stacked in a vertical rail, and
   obviously wrong once they sat side by side.
   TWO-CLASS selector (0,2,0) on purpose: the bell is `.push-bell { width: 30px }`
   from notifications.css, which loads AFTER this file — a single-class rule here
   ties at (0,1,0) and loses on source order. */
.live-match-metaline .live-match-actions > * {
    width: 26px;
    height: 26px;
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    margin: 0;
}

/* The league header's right-hand spacer existed only to reserve the width of the
   actions rail so the header's 1/X/2 labels stayed over the odds they label. The
   rail is on the left now, so reserving anything here pushes the labels back out
   of alignment — the exact bug the old comment warned about, inverted. */
.live-league-actions-header {
    display: none;
}

/* Right column: the price buttons, the band beneath them left empty. Same
   `1fr var(--lm-band-h)` row template as .live-match-info — that is what keeps the
   prices level with the team lines, and the clock/buttons band clear of them. */
.live-match-oddscol {
    display: grid;
    grid-template-rows: 1fr var(--lm-band-h, 26px);
    align-items: center;
    flex-shrink: 0;
    min-width: 0;
    /* MUST match .live-match-info's vertical padding. Identical row templates only
       align if both grids span the same box — with padding on one side only, the
       band rows sat 9px apart. Horizontal
       padding stays 0: .live-match-odds brings its own. */
    padding: var(--live-row-pad, 9px) 0;
}

/* Match odds container aligns with header */
.live-match-odds {
    display: flex;
    gap: 2px;
    align-items: center;
    padding: 4px;
    flex-shrink: 0;
}

/* Fallback main-market (next-goal / ET / RKSL substituted for a closed Final
   Result). The market-name label floats ABOVE the odds without taking layout
   space, so the main odds stay on one line and level with the O/U + corner
   columns in the same row (flex-wrap pushed them down and misaligned them). */
/* The label is pinned to the TOP of the odds container, with padding reserving its
   line box. Two bugs this shape avoids:
   - it used to be anchored with `bottom: calc(50% + 30px)` — a magic number tuned
     to the old ~98px row and 50px buttons, which the dense row invalidates (the
     label would land outside the row entirely);
   - putting it in normal flow instead makes it part of the container's max-content
     width, so a long market name ("Shënon golin 4") widened the odds column and
     ellipsised the team names on that row alone. Absolute positioning keeps it out
     of intrinsic sizing, so fallback rows stay the same width as plain ones. */
/* Two-class selector (0,2,0) on purpose: `.live-match-odds--mkt` alone ties with
   `.live-match-odds { padding: 4px }` at (0,1,0), and source order was winning —
   so the top strip was never reserved and the market name rendered ON TOP of the
   price buttons. Measured padding-top was 4px where 16px was intended. */
.live-match-row--mkt .live-match-odds {
    position: relative;
    padding-top: 20px;
}
.live-match-mkt-label {
    position: absolute;
    top: 4px;
    left: 0;
    right: 0;
    text-align: center;
    font-size: 10px;
    line-height: 1.1;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    pointer-events: none;
}
/* "No Goal" caption stacked over the middle odd on goal fallback markets. */
.live-odd-btn-cap {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    line-height: 1.05;
}
.live-odd-cap {
    font-size: 9px;
    color: var(--text-muted);
    font-weight: 600;
}

/* Hide O/U + Corner O/U in compact mode */
.live-compact .live-match-ou,
.live-compact .live-match-cou,
.live-compact .live-league-ou-header,
.live-compact .live-league-cou-header {
    display: none;
}

/* Groups with no markets beside the main one (tennis / cricket / hockey…) carry no
   O/U in the overview — every cell would be a lock. Drop the columns for those rows
   (the header cells are omitted in JS). Applied per league group (single-sport)
   and on the flat list when it holds no football or basketball match. Basketball
   keeps them: its total points ride in the first one (sql/live-perf/28). */
.live-league-no-ou .live-match-ou,
.live-league-no-ou .live-match-cou {
    display: none;
}

/* ---- Board column budget ----------------------------------------------------
   The extended row carries a lot of fixed width: 1X2 186 + O/U 152
   + corner O/U 152 + Tregje 52 + actions 56 = ~694px BEFORE the match column.
   The only breakpoint used to be 600px, which was fine when the row was just
   1X2 + O/U; with the 1a columns added, everything between 601px and ~1100px
   had no room left for team names and the match column collapsed to nothing.
   Columns now drop out in order of how little they're missed. */
@media (max-width: 1100px) {
    .live-match-mkt-count,
    .live-league-mkt-header,
    /* Corner O/U goes at the same step, not a lower one: keeping it to 900px left
       the 901-1100 band with 490px of odds and squeezed team names to ~50px. */
    .live-match-cou,
    .live-league-cou-header {
        display: none;
    }
}

/* Mobile: keep 1X2 inline, O/U columns hidden in compact or below in extended */
@media (max-width: 600px) {
    /* Three 58px prices plus the clock and the actions rail left the team column
       with nothing on a 375px screen — `min-width: 0` let the names and scores
       shrink to literally zero and vanish. Narrow the price token and floor the
       team column so the names always win the remaining space. */
    /* Width budget on a 375px phone: the row is ~347px after the page gutter, and
       three price buttons plus the clock and the actions rail leave the team names
       roughly 70px. Every value below is squeezed for that reason — the names are
       what suffers first, so they get whatever the fixed columns don't need. */
    :root {
        --odd-w: 55px;
    }

    .live-match-teams {
        min-width: 92px;
    }

    .live-match-info {
        gap: 0px;
        padding-left: 6px;
        padding-right: 4px;
    }

    /* The clock is no longer a fixed column — it is content-width on the meta
       band, so there is nothing to shrink here. The old `width: 32px` would now
       clamp the inline clock and clip long minute strings. */

    .live-match-live-tag {
        font-size: 8px;
        letter-spacing: 0.02em;
    }

    .live-match-odds {
        flex-shrink: 0;
        padding: 4px 2px;
    }

    .live-match-ou,
    .live-match-cou {
        display: none;
    }

    .live-league-ou-header,
    .live-league-cou-header {
        display: none;
    }

    /* The Momenti column costs 96px — more than a phone can spare next to the
       team names and three prices. Dropped on mobile along with its header; the
       possession split is still in the stats popover. The Tregje count goes with
       it for the same reason (the row itself opens the full market list). */
    .live-match-mkt-count,
    .live-league-mkt-header {
        display: none;
    }

    /* The actions rail and its header spacer are gone from the row's right edge —
       both buttons are on the meta band now, so there is no width for the header
       to mirror. The old pair of rules is deliberately NOT replaced: reserving
       32px on the right would push the 1/X/2 labels off the odds again, which is
       the same misalignment the original comment was written to prevent. */

    /* Matches .live-match-odds' mobile padding (4px 2px) — see the note on the
       header rule for why this has to track it. */
    .live-league-odds-header {
        padding: 0 2px;
    }

    /* The band reservation that keeps these level with the 1X2 prices on desktop
       is dead space here: on mobile these blocks wrap onto their OWN lines, so
       there is no 1X2 column beside them to line up with. */
    .live-match-ou,
    .live-match-cou,
    .live-match-mkt-count {
        margin-bottom: 0;
    }

    /* In extended mode on mobile, show O/U columns as a second row */
    #live-page-matches:not(.live-compact) .live-match-row {
        flex-wrap: wrap;
    }

    /* The O/U rows are width:100%, so they force a wrap — anything after them in
       DOM order lands on ITS OWN line, so the two O/U blocks have to be ordered
       last. The actions rail used to need an `order` here too (it sat after the
       O/U blocks in DOM order and got stranded on a fourth line); it is inside
       .live-match-info now, so it is no longer a flex item of the row and an
       `order` on it would do nothing. .live-match-odds likewise — the row's item
       is its wrapper, .live-match-oddscol. */
    #live-page-matches:not(.live-compact) .live-match-info      { order: 1; }
    #live-page-matches:not(.live-compact) .live-match-oddscol   { order: 2; }
    #live-page-matches:not(.live-compact) .live-match-linebreak { order: 4; }
    #live-page-matches:not(.live-compact) .live-match-ou        { order: 5; }
    #live-page-matches:not(.live-compact) .live-match-cou       { order: 6; }

    /* Zero-height full-width item that FORCES the wrap before the O/U pair.
       Width alone cannot do this. Flex fills a line greedily using each item's
       hypothetical main size, so two 50% blocks do NOT reserve a line of their
       own: on a 440px phone (iPhone 16 Pro Max) there was room for the first one
       beside the info, the prices and the actions rail, and it jumped up there —
       squeezing the team names out of existence and stranding the corner block
       alone on the next line. `flex-basis: 100%` + `max-width: 50%` cannot fix it
       either, because the hypothetical size is the basis already CLAMPED by
       max-width, which lands back at 50%.
       A real 100%-wide item has no such ambiguity: nothing can share its line, so
       the pair below always starts clean. */
    #live-page-matches:not(.live-compact) .live-match-linebreak {
        display: block;
        width: 100%;
        height: 0;
    }

    /* Both O/U blocks SHARE the wrapped line instead of taking one each.
       Measured on a 375px phone: the goals block needs 140px of content and the
       corner block 152px against a 359px row, so two halves fit with room over
       and the row drops from 179px to 125px. Still clean at 320px, where each
       block's content clears its 152px half without clipping.

       50%, not `flex: 1` or a content-based basis: the WIDTH is what forces the
       wrap in the first place. Flex breaks lines on hypothetical main size, not
       on the grown result, so with a content basis these two could be packed
       onto the main line beside the match info and the prices. Two halves add up
       to exactly one line, so they can never join the row above — and if a
       future column makes them genuinely too wide, they wrap apart again rather
       than overflowing. */
    #live-page-matches:not(.live-compact) .live-match-ou,
    #live-page-matches:not(.live-compact) .live-match-cou {
        display: grid;
        /* Columns pinned to the price width, NOT `auto`: the caption sitting in
           row 1 is wider than a single price, so auto columns would stretch to
           it and the two prices below would stop being equal. Fixed tracks let
           the caption overflow-centre across the pair instead — there is ~44px
           of slack each side inside the half. */
        grid-template-columns: repeat(2, var(--odd-w, 44px));
        justify-content: center;
        align-items: center;
        column-gap: 4px;
        row-gap: 3px;
        width: 50%;
        padding: 0 4px 4px;
    }

    /* Market label OVER its prices, per the reference. The four children are
       fixed in number and order — [tag][line][over][under] — for BOTH branches
       the renderer emits (priced and all-locked), so they are placed directly
       rather than wrapped in extra elements. Keeping the DOM flat matters: the
       delta patcher writes `.live-ou-line` and the odd buttons in place. */
    #live-page-matches:not(.live-compact) .live-match-ou  > *:nth-child(1),
    #live-page-matches:not(.live-compact) .live-match-cou > *:nth-child(1) { grid-row: 1; grid-column: 1; justify-self: end; }
    #live-page-matches:not(.live-compact) .live-match-ou  > *:nth-child(2),
    #live-page-matches:not(.live-compact) .live-match-cou > *:nth-child(2) { grid-row: 1; grid-column: 2; justify-self: start; }
    #live-page-matches:not(.live-compact) .live-match-ou  > *:nth-child(3),
    #live-page-matches:not(.live-compact) .live-match-cou > *:nth-child(3) { grid-row: 2; grid-column: 1; }
    #live-page-matches:not(.live-compact) .live-match-ou  > *:nth-child(4),
    #live-page-matches:not(.live-compact) .live-match-cou > *:nth-child(4) { grid-row: 2; grid-column: 2; }

    /* Tag and line now read as one caption, so the inline-row spacing they carry
       for the desktop columns has to go: `margin-right: auto` is what pushed the
       tag away from the prices, and the line's 28px is a COLUMN width that no
       longer exists here. */
    #live-page-matches:not(.live-compact) .live-ou-line {
        width: auto;
        text-align: left;
    }

    /* The league header's O/U columns are hidden above, so each wrapped row
       names its own market instead of showing a bare "1.5" / "9.5". */
    #live-page-matches:not(.live-compact) .live-ou-tag {
        display: inline-flex;
        margin-right: 0;        /* see the caption note above */
        padding-left: 0;
    }

    /* ...but NEVER for non-football groups. O/U is football-only in the overview
       (_hasOverviewOu), and `.live-league-no-ou` (0,2,0) loses to the extended-view
       rule above (1,2,0) — so without this override tennis / basketball / cricket
       reappear on mobile with two rows of padlocks each. Desktop was always fine;
       this gate only ever worked there. */
    #live-page-matches:not(.live-compact) .live-league-no-ou .live-match-ou,
    #live-page-matches:not(.live-compact) .live-league-no-ou .live-match-cou {
        display: none;
    }
}

/* ---- Market switcher (Live._MOB_MKTS) ----
   Live page, football rows, every width: one select field in the view pill names the
   first market and opens a sheet that picks it and up to two more. A phone draws the
   extra markets as rows under each match (below); desktop puts them in the two columns
   beside the first one (the old goals / corner O/U columns). It takes no room on the
   board itself. */
/* Compact / extended mean nothing any more: the extra rows (phone) and extra columns
   (desktop) are what "extended" used to be. */
.live-view-toggle .live-view-btn[data-view] { display: none; }
/* The view pill is a tool box (design A), at every width: search · sort · collapse-all
   on top, and under them a select field naming the first market. The toolbar's own
   collapse button hides — the box carries one. */
#page-live .live-top-bar > [data-lc-toggle-all] { display: none; }
.live-view-toggle {
    width: 136px;
    height: 80px;
    box-sizing: border-box;
    padding: 4px;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-auto-rows: 34px;
    gap: 4px 2px;
    border-radius: 10px;
}
.live-view-toggle .live-view-btn { width: auto; }
.live-view-toggle .lmx-collapse-btn { display: flex; }
.live-view-toggle .lmx-rows-btn {
    display: flex;
    grid-column: 1 / -1;
    position: relative;
    align-items: center;
    gap: 6px;
    padding: 0 8px 0 10px;
    border: 1px solid color-mix(in srgb, var(--text-muted) 40%, var(--bg-input));
    border-radius: var(--radius-md);
    background: var(--bg-input);
    color: var(--text-primary);
    text-align: left;
}
.live-view-toggle .lmx-rows-btn:active:not(:disabled) { background: var(--bg-hover); }
.live-view-toggle .lmx-rows-btn:focus-visible { outline: 2px solid var(--accent-odds); outline-offset: 1px; }
.lmx-rows-btn:disabled { opacity: 0.4; cursor: default; }
.lmx-btn-txt {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
    line-height: 1;
}
.lmx-btn-cap {
    font-size: 8.5px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.lmx-btn-lbl {
    min-width: 0;
    font-size: 12px;
    font-weight: 800;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.lmx-btn-chev { flex: none; width: 12px; height: 12px; color: var(--accent-green); }
.lmx-rows-n {
    position: absolute;
    top: -7px;
    right: -5px;
    height: 16px;
    padding: 0 5px;
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    border-radius: 999px;
    background: var(--accent-green);
    color: var(--bg-input);
    font-size: 10px;
    font-weight: 800;
    line-height: 1;
    box-shadow: 0 0 0 2px var(--bg-secondary);
}
.lmx-rows-n[hidden] { display: none; }

/* Two-column markets (both score): two buttons as wide as the three they stand in
   for, header labels included, so the right edge stays plumb (3w + 2 gaps = 2W + 1 gap). */
.live-odd-btn.lmx-wide,
.live-league-odds-header span.lmx-wide { width: calc(var(--odd-w, 55px) * 1.5 + 1px); }

/* A basketball row whose points stand in the Winner's slot keeps its Points column
   cell the right size but empty, so the columns beside it stay in line. */
.live-odd-btn.is-void { visibility: hidden; }

/* A total's line is not a price, so not a button: an outlined cell in the first column. */
.lmx-line {
    width: var(--odd-w, 55px);
    height: var(--odd-h, 44px);
    flex-shrink: 0;
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    font-size: 14px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}

/* Phone: the extra markets as rows under each match. */
@media (max-width: 600px) {
    /* The extra rows: one full-width block under the row — name left, prices under the
       first row's columns (same gap and inset as .live-match-odds on a phone). */
    .live-match-row.has-lmx { flex-wrap: wrap; }
    .lmx-rows {
        order: 9;
        flex-basis: 100%;
        min-width: 0;
        display: flex;
        flex-direction: column;
        gap: 4px;
        padding: 6px 0 8px 6px;
        border-top: 1px solid var(--border-subtle);
    }
    .lmx-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
    .lmx-name {
        flex: 1;
        min-width: 0;
        font-size: 12px;
        font-weight: 600;
        color: var(--text-muted);
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .lmx-cells { display: flex; gap: 2px; padding: 0 2px; flex-shrink: 0; }
    .lmx-cells .live-odd-btn,
    .lmx-cells .lmx-line { height: 38px; }
}

/* The extra-rows picker — a bottom sheet (opened only on a phone). */
.lmx-sheet {
    margin: auto 0 0;
    width: 100%;
    max-width: 100%;
    max-height: 85dvh;
    overflow-y: auto;
    box-sizing: border-box;
    border: 0;
    border-radius: 16px 16px 0 0;
    padding: 16px 16px calc(20px + env(safe-area-inset-bottom, 0px));
    background: var(--bg-secondary);
    color: var(--text-primary);
}
.lmx-sheet::backdrop { background: var(--scrim); }
@media (min-width: 601px) {
    .lmx-sheet { margin: auto; width: 440px; max-width: calc(100% - 32px); border-radius: 16px; padding-bottom: 20px; }
}
.lmx-sheet-body { display: flex; flex-direction: column; gap: 12px; }
.lmx-sheet-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.lmx-sheet-head h3 { margin: 0; font-size: 16px; font-weight: 800; }
.lmx-sheet-done {
    height: 36px;
    padding: 0 16px;
    border: 0;
    border-radius: var(--radius-md);
    background: var(--accent-green-grad);
    color: var(--bg-input);
    font-family: inherit;
    font-size: 13px;
    font-weight: 800;
    cursor: pointer;
}
.lmx-sheet-hint { margin: 0; font-size: 12px; line-height: 1.4; color: var(--text-muted); }
.lmx-sec { display: flex; flex-direction: column; gap: 8px; }
.lmx-sec-title {
    margin: 4px 0 0;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.lmx-mains { display: flex; flex-wrap: wrap; gap: 6px; }
.lmx-chip {
    height: 38px;
    padding: 0 14px;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    background: transparent;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 13px;
    font-weight: 700;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 0.15s, color 0.15s;
}
.lmx-chip[aria-checked="true"] {
    border-color: var(--accent-green);
    background: var(--bg-tertiary);
    color: var(--text-primary);
}
.lmx-chip:focus-visible { outline: 2px solid var(--accent-odds); outline-offset: 2px; }
.lmx-sheet-list { display: flex; flex-direction: column; gap: 6px; }
.lmx-opt {
    min-height: 44px;
    padding: 0 12px;
    display: flex;
    align-items: center;
    gap: 10px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-odds);
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
}
.lmx-opt:has(input:checked) { border-color: var(--accent-green); }
.lmx-opt input { width: 18px; height: 18px; margin: 0; accent-color: var(--accent-green); }
.lmx-opt-name { flex: 1; }
.lmx-opt-note { font-size: 11px; font-weight: 600; color: var(--text-muted); }
.lmx-opt.is-main { color: var(--text-muted); cursor: default; }

/* The live list holds every live match (150-300 rows, ~10,000 elements). The browser
   skips style, layout and paint for a league group that is off screen until it
   scrolls near, so showing the page (Back, the bottom nav) and redrawing it after a
   push cost a third of what they did: Sporte → Live 343-625 ms of frames, 126-143 ms
   with this, measured on the live site. Safe here: the group already clips
   (overflow: clip, below), its sticky header still pins (checked), the stats popover
   lives on <body>, and nothing measures rows any more (_markTruncatedNames is gone —
   it was what made this slower when tried before). `auto` keeps a group's real
   height once it has been drawn; 330px is about the average, so the page's height
   barely moves while scrolling. */
#live-page-matches > .live-league-group {
    content-visibility: auto;
    contain-intrinsic-size: auto 330px;
}

.live-league-group {
    /* margin-bottom: 8px; */
    /* border-radius: var(--radius-dec); */
    /* `clip`, NOT `hidden` — this rounds the group's corners, and `hidden` does
       that just as well, but it also makes the group a SCROLL CONTAINER. The
       sticky .live-league-header inside resolves against its nearest scroll
       container, so with `hidden` it pinned against a box that never scrolls and
       did nothing at all. `clip` clips identically without creating one. */
    overflow: clip;
    margin-bottom: 5px;
}

/* Score change animation */
.live-score-flash {
    animation: scoreFlash 1s ease;
}

@keyframes scoreFlash {
    0% {
        color: var(--text-primary);
    }

    20% {
        color: var(--accent-green);
        font-size: 16px;
    }

    100% {
        color: var(--text-primary);
        font-size: inherit;
    }
}

/* ==========================================
   LEAGUE PAGE
   ========================================== */
.league-page-header {
    margin-bottom: 20px;
}

/* With a competition banner the bare header becomes a band: it needs the
   padding and the radius only in that case, so a league without artwork keeps
   the plain title it has always had. Artwork list: [data-league-bg] above. */
.league-page-header[data-league-bg] {
    padding: 14px 16px 45px;
    border-radius: var(--radius-lg);
    background:
        linear-gradient(180deg, rgba(var(--bg-primary-rgb), 0.38) 0%, rgba(var(--bg-primary-rgb), 0.70) 58%, var(--bg-primary) 100%),
        var(--league-art) center/cover no-repeat;
}

.league-page-header[data-league-bg] .league-page-title { margin-left: 0; }

.league-page-title {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    transition: color 0.15s;
    margin-left: 5px; /* match the league header's left padding */
}

.league-page-title:hover {
    color: var(--accent-green);
}

.league-page-title h2 {
    font-size: 24px;
    font-weight: 800;
}

.league-page-title svg {
    color: var(--text-muted);
}

/* ==========================================
   MATCH DETAIL PAGE
   ========================================== */
.match-detail-top {
    background: linear-gradient(180deg, var(--bg-tertiary) 0%, var(--bg-primary) 100%);
    padding: 20px 10px 0px;
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
    /* margin: -12px -20px 0px; */
    position: relative;
}

/* Sport-specific background — applied to both prematch and live detail headers when JS
   sets data-sport-id on the wrapper (app.js loadMatchDetail / live.js detail render).
   Dark gradient overlay keeps text readable.

   ORDER MATTERS: `[data-sport-id]` and `[data-sport-id="1"]` have the SAME specificity,
   so the generic fallback must come FIRST and the per-sport rules after it — otherwise
   the fallback would win over every sport. Sport ids are the DOMAIN ids from the
   `sports` table (1 Futboll, 2 Basketboll, 3 Tenis, 11 Voleyball, 12 Ping Pong,
   15 Beach Volleyball, 18 Cricket); anything without artwork keeps the generic one. */
.match-detail-top[data-sport-id] {
    background:
        linear-gradient(180deg, rgba(var(--bg-tertiary-rgb), 0.30) 0%, rgba(var(--bg-primary-rgb), 0.62) 62%, var(--bg-primary) 100%),
        url('/img/banners/sports/sports-backgrounds-pack/headers/generic-sports-header.webp') center/cover no-repeat;
}

.match-detail-top[data-sport-id="1"] {
    background:
        linear-gradient(180deg, rgba(var(--bg-tertiary-rgb), 0.30) 0%, rgba(var(--bg-primary-rgb), 0.62) 62%, var(--bg-primary) 100%),
        url('/img/banners/sports/sports-backgrounds-pack/headers/football-header.webp') center/cover no-repeat;
}

.match-detail-top[data-sport-id="2"] {
    background:
        linear-gradient(180deg, rgba(var(--bg-tertiary-rgb), 0.30) 0%, rgba(var(--bg-primary-rgb), 0.62) 62%, var(--bg-primary) 100%),
        url('/img/banners/sports/sports-backgrounds-pack/headers/basketball-header.webp') center/cover no-repeat;
}

.match-detail-top[data-sport-id="3"] {
    background:
        linear-gradient(180deg, rgba(var(--bg-tertiary-rgb), 0.30) 0%, rgba(var(--bg-primary-rgb), 0.62) 62%, var(--bg-primary) 100%),
        url('/img/banners/sports/sports-backgrounds-pack/headers/tennis-header.webp') center/cover no-repeat;
}

/* Volleyball (11) + Beach Volleyball (15) share the volleyball artwork. */
.match-detail-top[data-sport-id="11"],
.match-detail-top[data-sport-id="15"] {
    background:
        linear-gradient(180deg, rgba(var(--bg-tertiary-rgb), 0.30) 0%, rgba(var(--bg-primary-rgb), 0.62) 62%, var(--bg-primary) 100%),
        url('/img/banners/sports/sports-backgrounds-pack/headers/volleyball-header.webp') center/cover no-repeat;
}

/* Ping Pong (12) = table tennis. */
.match-detail-top[data-sport-id="12"] {
    background:
        linear-gradient(180deg, rgba(var(--bg-tertiary-rgb), 0.30) 0%, rgba(var(--bg-primary-rgb), 0.62) 62%, var(--bg-primary) 100%),
        url('/img/banners/sports/sports-backgrounds-pack/headers/table-tennis-header.webp') center/cover no-repeat;
}

.match-detail-top[data-sport-id="18"] {
    background:
        linear-gradient(180deg, rgba(var(--bg-tertiary-rgb), 0.30) 0%, rgba(var(--bg-primary-rgb), 0.62) 62%, var(--bg-primary) 100%),
        url('/img/banners/sports/sports-backgrounds-pack/headers/cricket-header.webp') center/cover no-repeat;
}

/* League artwork — the operator's own banner per competition, which beats the
   per-sport photo for the leagues we have art for. app.js (LeagueArt) stamps
   `data-league-bg` on the prematch header from the match's leagueId.

   ORDER MATTERS, same trap as the sport rules above: `[data-league-bg]` and
   `[data-sport-id]` are both (0,2,0), so this block only wins by sitting after
   them. The scrim is heavier than the sport one — these banners are brand
   colour at full strength and the team names sit straight on top. */
.match-detail-top[data-league-bg] {
    background:
        linear-gradient(180deg, rgba(var(--bg-primary-rgb), 0.40) 0%, rgba(var(--bg-primary-rgb), 0.72) 62%, var(--bg-primary) 100%),
        var(--league-art) center/cover no-repeat;
}

/* The artwork itself hangs off the ATTRIBUTE alone, not off one surface, so
   every place that stamps `data-league-bg` — the match header, the home live
   hero — reads the same five files from one list. */
[data-league-bg="england-premier-league"] { --league-art: url('/img/banners/leagues/england-premier-league.webp'); }
[data-league-bg="italy-serie-a"]          { --league-art: url('/img/banners/leagues/italy-serie-a.webp'); }
[data-league-bg="spain-laliga"]           { --league-art: url('/img/banners/leagues/spain-laliga.webp'); }
[data-league-bg="germany-bundesliga"]     { --league-art: url('/img/banners/leagues/germany-bundesliga.webp'); }
[data-league-bg="france-ligue-1"]         { --league-art: url('/img/banners/leagues/france-ligue-1.webp'); }
[data-league-bg="uefa-champions-league"]  { --league-art: url('/img/banners/leagues/uefa-champions-league.webp'); }
[data-league-bg="uefa-europa-league"]     { --league-art: url('/img/banners/leagues/uefa-europa-league.webp'); }
[data-league-bg="uefa-conference-league"] { --league-art: url('/img/banners/leagues/uefa-conference-league.webp'); }

/* Artwork band — MUST come after every per-sport rule above, which set `center/
   cover` through the `background` shorthand and would otherwise reset this.
   Same specificity (0,2,0), so source order decides.

   `cover` scales the image to fill whichever axis binds. The headers are wide
   and short against 2048x550 artwork, so HEIGHT binds — and that made the
   artwork's scale a function of the header's CONTENT height. Expanding the
   latest-goals ticker inside the header grew it 275px -> 358px and zoomed the
   background 0.50x -> 0.65x, which reads as the image stretching on a click
   that should not have touched it.

   Capping the band decouples the two: the scale stops growing, and a taller
   header simply reveals more of the page beneath rather than resizing anything.
   The GRADIENT is capped to the same band on purpose — it ends on opaque
   --bg-primary, so it meets the background-color exactly where the image stops
   and there is no seam.

   A CAP (`min(100%, ...)`), not a floor. Flooring the header with min-height
   also "works", but it pads every SHORTER header up to the band: the periods
   variant is ~180px of content, and a floor gave tennis 95px of dead artwork
   above the video. Capping instead leaves short headers exactly as they were —
   band == header height, gradient completing at the bottom edge, which is what
   `cover` already did for them. Only headers that would have grown PAST the cap
   change behaviour, which is precisely the case being fixed. */

/* SCOPED TO THE LIVE HEADER ONLY. It was first written against
   `.match-detail-top[data-sport-id]`, which also matches the PREMATCH header —
   and broke it. `auto <height>` derives the width from the aspect ratio, so a
   275px band renders 275 x (2048/550) = ~1024px wide; the prematch header on a
   wide desktop is wider than that, leaving uncovered strips filled by
   background-color and a hard vertical edge either side of the artwork. The
   live header is ~704px so it never showed the fault.
   Prematch keeps plain `cover`: it has no collapsible ticker inside it, so its
   height never changes and there was nothing to decouple. If the live header
   ever exceeds ~1024px, this needs the same treatment as prematch. */
#live-md-detail-top[data-sport-id] {
    --md-art-h: 275px;
    background-color: var(--bg-primary);
    background-size:
        100% min(100%, var(--md-art-h)),
        auto  min(100%, var(--md-art-h));
    background-position: center top, center top;
}

/* A league banner in the live header needs its own sizing, and NOT the band
   above. The band derives the artwork's width from a fixed height (275px x the
   sports pack's 2048/550 = ~1024px, comfortably wider than this header) — but
   the league banners are 16:9, so the same 275px band would render them 489px
   wide and leave bare strips either side of a 580px header.

   `100% auto` keys the image to the header's WIDTH instead, which keeps the
   decoupling the band was written for: the scale no longer moves when the
   header's CONTENT height changes (expanding the goals ticker, the periods
   variant). The gradient takes the full box so its opaque end always lands on
   the bottom edge — where the artwork runs out on a tall header, it has
   already faded to --bg-primary and there is no seam. */
#live-md-detail-top[data-league-bg] {
    /* Ties with the band rule above on specificity (1,1,0 both), so it wins on
       SOURCE ORDER alone — keep it below. */
    background-size: 100% 100%, 100% auto;
    background-position: center top, center top;
}

.match-detail-hero {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: 16px;
    padding: 20px 10px;
}

.md-team {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    text-align: center;
}

.md-kit {
    width: 64px;
    height: 64px;
    display: flex;
    align-items: center;
    justify-content: center;
}

.md-kit .team-kit-lg {
    width: 64px;
    height: 64px;
}

.md-team-name {
    font-size: 15px;
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1.2;
}

.md-center {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding-top: 10px;
}

.md-date {
    font-size: 13px;
    color: var(--text-muted);
    font-weight: 500;
}

.md-vs {
    font-size: 16px;
    font-weight: 700;
    color: var(--text-muted);
}

.md-change-match-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    margin: 0 auto;
    padding: 8px 20px;
    background: var(--bg-tertiary);
    border: 1px solid var(--border-color);
    border-radius: 0;
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    font-family: inherit;
    transition: all 0.15s;
    margin-bottom: 20px;
}

.md-change-match-btn:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}

/* Category tabs wrapper */
.md-categories-wrapper {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 8px;
    margin-top: 20px;
}

.md-cat-arrow {
    flex-shrink: 0;
}

.md-search-toggle {
    flex-shrink: 0;
    width: 32px;
    height: 45px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-tertiary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-muted);
    cursor: pointer;
    transition: all 0.15s;
}

.md-search-toggle:hover {
    color: var(--text-primary);
    border-color: var(--accent-green);
}

.md-search-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    margin-bottom: 12px;
    transition: border-color 0.2s;
}

.md-search-bar:focus-within {
    border-color: var(--accent-green);
}

.md-search-bar svg {
    color: var(--text-muted);
    flex-shrink: 0;
}

.md-search-bar input {
    flex: 1;
    background: none;
    border: none;
    color: var(--text-primary);
    font-size: 13px;
    font-family: inherit;
    outline: none;
}

.md-search-bar input::placeholder {
    color: var(--text-muted);
}

.md-search-close {
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    padding: 2px;
    transition: color 0.15s;
}

.md-search-close:hover {
    color: var(--accent-red);
}

@media (max-width: 600px) {
    .md-cat-arrow {
        display: none;
    }
}

/* Category tabs */
.md-categories {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 4px;
    /* background: var(--bg-darkb); */
    border-radius: var(--radius-dec);
    flex: 1;
    min-width: 0;
    height:50px;
    /* `pan-x pan-y` — NOT bare `pan-x`, which would swallow vertical swipes
       that start on this row and stop the page from scrolling. Horizontal
       pans scroll the row; vertical pans fall through to the document.
       `overscroll-behavior-x: contain` stops the horizontal bounce from
       chaining up to the body (the old "scrolls left/right, snaps back"
       complaint). */
    touch-action: pan-x pan-y;
    overscroll-behavior-x: contain;
}

.md-categories::-webkit-scrollbar {
    display: none;
}

.md-cat-btn {
    padding: 8px 8px;
    background: transparent;
    color: var(--text-cat);
    font-size: 14px;
    font-weight: 600;
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    white-space: nowrap;
    font-family: inherit;
    transition: all 0.15s;
}

.md-cat-btn:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
}

.md-cat-btn.active {
    color: var(--bg-deep);
    background: var(--accent-green-grad);
}

/* --- Category icons (live strip) ---------------------------------------------
   The operator's market icons, in their own colours while a pill is idle and dark
   once it is selected: on the lime a green scoreboard or a yellow card sinks into
   the background. Both variants ship in the markup (js/caticons.js) and the swap
   lives here, so selecting a pill needs no re-render. */
#live-md-categories .md-cat-btn,
#md-categories .md-cat-btn {
    display: inline-flex;
    align-items: center;
    /* Never shrink: the strip scrolls, and a squeezed pill let its name run out
       over the next one instead of taking the width it needs. */
    flex: none;
    gap: 6px;
    padding: 8px 10px 8px 8px;
}
.md-cat-ico { flex: none; display: flex; align-items: center; }
.md-cat-ico svg { display: block; width: 16px; height: 16px; }
.md-cat-ico .ci-m,
.md-cat-btn.active .md-cat-ico .ci-c { display: none; }
.md-cat-btn.active .md-cat-ico .ci-m { display: block; }

/* Popular tab (MarketConfig.POPULAR_CAT_ID): a flame drawn through the asset's
   mask, so it takes the orange while the pill is idle and the pill's own text
   colour once selected — the swap the generated icons do with .ci-c / .ci-m. */
.md-cat-flame {
    display: block;
    width: 16px;
    height: 16px;
    background-color: var(--accent-orange);
    -webkit-mask: url('/img/assets/flame_color.svg') no-repeat center / contain;
    mask: url('/img/assets/flame_color.svg') no-repeat center / contain;
}
.md-cat-btn.active .md-cat-flame { background-color: currentColor; }

/* Phone: the icon goes above the name, the way the livescore sport tiles read.
   Beside the name it costs about 22px a pill, which is most of a phone's strip. */
@media (max-width: 600px) {
    #live-md-categories,
    #md-categories { height: 62px; }
    #live-md-categories .md-cat-btn,
    #md-categories .md-cat-btn {
        flex-direction: column;
        justify-content: center;
        gap: 4px;
        min-width: 64px;
        height: 54px;
        box-sizing: border-box;
        padding: 6px 9px;
        font-size: 11.5px;
    }
    #live-md-categories .md-cat-ico svg,
    #md-categories .md-cat-ico svg,
    #live-md-categories .md-cat-flame,
    #md-categories .md-cat-flame { width: 20px; height: 20px; }
}

/* Markets / odds groups */
.md-markets {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.md-market {
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-dec);
    overflow: hidden;
}

.md-market-header {
    padding: 12px 16px;
    font-size: 16px;
    font-weight: 700;
    color: var(--text-primary);
    border-bottom: 1px solid var(--border-color);
    display: flex;
    align-items: center;
    justify-content: space-between;
    cursor: pointer;
    /* `-webkit-user-select` for Safari ≤17 / iOS Safari; standard property for everyone else. */
    -webkit-user-select: none;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
}

.md-market-header:hover {
    background: rgba(var(--bg-tertiary-rgb), 0.2);
}

.md-market-toggle {
    color: var(--text-muted);
    transition: transform 0.2s;
    flex-shrink: 0;
}

.md-market.collapsed .md-market-toggle {
    transform: rotate(180deg);
}

.md-market.collapsed .md-market-odds,
.md-market.collapsed .md-market-grid,
.md-market.collapsed .md-market-table,
.md-market.collapsed .md-cs-grid,
.md-market.collapsed .md-side-grid,
.md-market.collapsed .md-side-groups,
.md-market.collapsed table {
    display: none;
}

.md-market.collapsed .md-market-header {
    border-bottom: none;
}

/* A button (it was a span nothing could focus) with a 24px target: 5px of
   padding round the 14px star, and negative margins that give the extra 3px back
   so the star and the market name don't move. */
.md-market-fav {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--text-muted);
    flex-shrink: 0;
    padding: 5px;
    margin: -3px 1px -3px -3px;
    border: 0;
    background: none;
    cursor: pointer;
    transition: color 0.15s;
}

.md-market-fav:focus-visible {
    outline: 2px solid var(--accent-orange);
    outline-offset: -1px;
    border-radius: 0;
}

.md-market-fav:hover {
    color: var(--accent-orange);
}

.md-market-fav.fav-active {
    color: var(--accent-orange);
}

.md-market-fav.fav-active svg {
    fill: var(--accent-orange);
}

/* Favorite market animations */
.md-market.fav-fly-up {
    animation: marketFlyUp 0.5s ease;
}

.md-market.fav-fly-down {
    animation: marketFlyDown 0.5s ease;
}

@keyframes marketFlyUp {
    0% {
        transform: translateY(0);
        opacity: 1;
    }

    30% {
        transform: translateY(-30px);
        opacity: 0.3;
    }

    60% {
        transform: translateY(-10px);
        opacity: 0;
    }

    61% {
        transform: translateY(0);
        opacity: 0;
    }

    100% {
        transform: translateY(0);
        opacity: 1;
    }
}

@keyframes marketFlyDown {
    0% {
        transform: translateY(0);
        opacity: 1;
    }

    30% {
        transform: translateY(30px);
        opacity: 0.3;
    }

    60% {
        transform: translateY(10px);
        opacity: 0;
    }

    61% {
        transform: translateY(0);
        opacity: 0;
    }

    100% {
        transform: translateY(0);
        opacity: 1;
    }
}

/* Temporary debug badge — remove later */
.md-grp-debug {
    font-size: 10px;
    font-weight: 500;
    color: var(--accent-orange);
    opacity: 0.7;
    margin-left: 4px;
    display:none;
}

.md-market-odds {
    display: flex;
    flex-wrap: wrap;
    gap: 0;
    padding: 8px 5px 12px;
}

/* Markets with MORE THAN 3 selections (correct-score, result+total-goals,
   result+BTTS…) carry long compound labels — "Alianza Atletico | Mbi 3.5".
   As flex children they all shared one row, collapsing to ~150px each and
   ellipsising to "Alianza Atl…", which is unreadable.
   Wrap them into an auto-fitting grid so the ROW COUNT grows instead of the
   labels shrinking: ~3 columns on a wide panel, 2 with the betslip rail open,
   and the existing max-600px rule still forces a single column on mobile.
   `min-width: 0` is required — as grid items the buttons otherwise inherit
   min-width:auto (= intrinsic label width) and blow past their track. */
.md-market-odds.md-many-opts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.md-market-odds.md-many-opts .md-odd-btn {
    min-width: 0;
    justify-content: space-between;
}

.md-odd-btn {
    flex: 1;
    min-width: 80px;
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 8px;
    /* 1px less than before on each side: the border below is new and the height
       is auto, so without this every market row would grow 2px. */
    padding: 9px 6px;
    background: var(--bg-odds);
    /* Transparent, not none — same reason as .live-odd-btn: hover and selected
       set border-color, which does nothing without a border. */
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    cursor: pointer;
    font-family: inherit;
    transition: all 0.15s;
    margin: 3px;
}

/* Pointer devices only, like .live-odd-btn: on a phone :hover sticks to the
   last tapped button, which would now leave a green edge on a price the user
   just took out of the slip. */
@media (hover: hover) {
    .md-odd-btn:hover {
        background: var(--bg-hover);
        border-color: var(--accent-green);
    }
}

.md-odd-btn.selected {
    background: var(--blue-alt);
    border-color: var(--blue-alt);
}

.md-odd-btn.selected .md-odd-label {
    color: rgba(255, 255, 255, 0.8);
}

.md-odd-btn.selected .md-odd-value {
    color: #fff;
}

.md-odd-label {
    font-size: 13px;
    color: white;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

@media (max-width: 600px) {
    .md-odd-label {
        font-size: 11px;
    }
}

.md-odd-value {
    font-size: 16px;
    font-weight: 700;
    color: var(--accent-odds);
    margin-left: auto;
}

/* Over/Under table style */
.md-market-table {
    width: 100%;
    border-collapse: collapse;
}

.md-market-table th {
    padding: 10px 12px;
    font-size: 12px;
    font-weight: 700;
    color: var(--text-muted);
    text-align: center;
    background: var(--bg-tertiary);
}

.md-market-table td {
    padding: 4px 6px;
    border-top: 1px solid rgba(var(--bg-tertiary-rgb), 0.3);
}

.md-market-table td .md-odd-btn {
    width: 100%;
    justify-content: center;
    margin: 0;
}

.md-market-table td .md-odd-btn .md-odd-value {
    margin-left: 0;
}

/* Team-name markets (Rezultat Final, Kualifikohet, Shenon i pari, …)
   stack as full-width rows on narrow screens — label left, odds right. */
@media (max-width: 600px) {
    .md-market-odds.md-team-rows {
        flex-direction: column;
    }

    .md-market-odds.md-team-rows .md-odd-btn {
        flex: none;
        width: calc(100% - 6px);
        padding: 12px 10px;
    }
}

/* Correct-score grid: Home / Draw / Away columns */
.md-cs-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0 4px;
    padding: 8px 5px 4px;
}

.md-cs-col {
    min-width: 0;
    display: flex;
    flex-direction: column;
}

.md-cs-head {
    padding: 10px 4px;
    font-size: 12px;
    font-weight: 700;
    color: var(--text-muted);
    text-align: center;
    background: var(--bg-tertiary);
    border-radius: var(--radius-md) var(--radius-md) 0 0;
    margin: 0 3px 3px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.md-cs-col .md-odd-btn {
    flex: none;
    width: calc(100% - 6px);
    min-width: 0;
}

.md-cs-grid + .md-market-odds {
    padding-top: 0;
}

/* Combo markets by side (App._renderSideGrid): home | draw | away. One grid
   filled column by column, so every row is shared — a label that wraps lifts its
   whole row — and an empty slot holds a row where the feed offers no pick. On a
   phone it reads as one column, one side's picks after another. */
.md-side-grid {
    display: grid;
    grid-template-columns: repeat(var(--side-cols, 3), minmax(0, 1fr));
    grid-template-rows: repeat(var(--side-rows, 1), auto);
    grid-auto-flow: column;
    column-gap: 4px;
    padding: 8px 5px 4px;
}
.md-side-grid .md-odd-btn {
    min-width: 0;
    justify-content: space-between;
}
.md-side-empty { visibility: hidden; pointer-events: none; }
.md-side-grid + .md-market-odds { padding-top: 0; }
/* HT/FT with totals (App._renderHtFtGroups): one group per total, under its own
   heading, a hairline between groups. */
.md-side-group + .md-side-group { border-top: 1px solid var(--border-subtle); }
.md-side-group-head {
    padding: 10px 11px 0;
    font-size: 12px;
    font-weight: 700;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}
.md-side-group .md-side-grid { padding-top: 4px; }
/* The pick's two sides shorten; its total never does. */
.md-side-group .md-odd-label { display: flex; min-width: 0; }
.md-htft-sides { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.md-htft-total { flex: none; white-space: pre; }
@media (max-width: 600px) {
    .md-side-grid {
        grid-template-columns: minmax(0, 1fr);
        grid-template-rows: none;
        grid-auto-flow: row;
    }
    .md-side-start { margin-top: 11px; }   /* the button's 3px + a gap between sides */
    .md-side-empty { display: none; }
}

.md-table-line {
    text-align: center;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-secondary);
    padding: 8px 12px !important;
    border-right: 1px solid rgba(var(--bg-tertiary-rgb), 0.3);
    min-width: 60px;
}

.md-market-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
}

/* Player-prop list (Anytime Goalscorer, Player to be Booked, Player Assists,
   Player Shots on Target, …) — one row per player: name on the left, single
   odds button right-aligned. Two columns on desktop to halve the scroll for
   20-player lists; single column on mobile. */
.md-player-list {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 6px;
    row-gap: 0;
}
/* Each player row IS a full-width .md-odd-btn (see _renderPlayerList): name on the
   left as the label, odd on the right as the value. The whole row is the selectable
   unit and highlights as one when picked — same style as the correct-score grid,
   not a name-span sitting outside a separate odd box. */
.md-player-name {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    font-size: 13px;
    font-weight: 500;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.md-player-qual {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-muted);
}
.md-odd-btn.selected .md-player-qual {
    color: rgba(255, 255, 255, 0.85);
}
@media (max-width: 600px) {
    .md-player-list {
        grid-template-columns: 1fr;
    }
}

/* Goalscorer lists split by the player's team (_renderPlayerList): one tab per
   team, kit + name, in the segmented-control language of the sidebar's
   A–Z / Popular switch. Same on desktop and phone. */
.md-team-tabs {
    display: flex;
    gap: 4px;
    margin: 10px 8px 0;
    padding: 3px;
    background: var(--bg-input);
    border: 1px solid var(--border-subtle);
    border-radius: 0;
}
.md-team-tab {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    height: 40px;
    padding: 0 8px;
    background: none;
    border: none;
    border-radius: 0;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}
.md-team-tab[aria-selected="true"] {
    background: var(--bg-tertiary);
    color: var(--text-primary);
}
@media (hover: hover) {
    .md-team-tab:hover {
        color: var(--text-primary);
    }
}
.md-team-tab-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* The panels are .md-player-list grids, which would override [hidden]; and a
   collapsed market hides its lists but would leave the tabs behind. */
.md-team-panel[hidden],
.md-market.collapsed .md-player-teams {
    display: none;
}
/* A pick in the other team's tab would be out of sight: its tab carries a dot.
   Betslip.syncButtonStates toggles .selected on hidden buttons too. */
.md-player-teams:has(.md-team-panel[data-side="H"] .md-odd-btn.selected) .md-team-tab[data-side="H"]::after,
.md-player-teams:has(.md-team-panel[data-side="A"] .md-odd-btn.selected) .md-team-tab[data-side="A"]::after,
.md-player-teams:has(.md-team-panel[data-side="X"] .md-odd-btn.selected) .md-team-tab[data-side="X"]::after {
    content: "";
    flex: none;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--accent-green);
}

@media (max-width: 600px) {
    .md-market-grid {
        grid-template-columns: 1fr;
    }

    .md-market-grid .md-odd-btn,
    .md-market-odds-list .md-odd-btn {
        justify-content: space-between;
    }

    /* All markets with more than 3 options → single column list on mobile */
    .md-market-odds.md-many-opts {
        display: flex;
        flex-direction: column;
    }

    .md-market-odds.md-many-opts .md-odd-btn {
        justify-content: space-between;
        width: 100%;
    }
}

.md-market-table .md-odd-btn {
    width: 100%;
    justify-content: center;
}

/* ==========================================
   FULL SCREEN MODAL
   ========================================== */
.modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 300;
    background: rgba(0, 0, 0, 0.7);
    display: flex;
    align-items: center;
    justify-content: center;
}

.modal-full {
    width: 100%;
    max-width: 500px;
    /* `dvh` so the modal shrinks when iOS Chrome/Safari URL bar appears
     * — otherwise the bottom action button gets clipped under the toolbar. */
    height: 100dvh;
    max-height: 100dvh;
    background: var(--bg-primary);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

@media (min-width: 600px) {
    .modal-full {
        height: 90vh;
        max-height: 90vh;
        border-radius: var(--radius-lg);
    }

    /* Centred at 90vh here, so the header never touches the top edge — drop the
       status-bar inset that the full-height mobile layout needs. */
    .modal-header {
        padding-top: 14px;
    }
}

.modal-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* INSTALLED PWA: .modal-full is 100dvh below 600px, so this header sits hard against
       the top edge — and standalone adds `viewport-fit=cover`, which lays it out UNDER the
       iOS status bar. The back arrow and the close × ended up behind the clock and battery
       and could not be tapped. env() is 0 without viewport-fit=cover, so this is a no-op in
       the browser. Same pattern as .slots-launch-header. */
    padding: calc(14px + env(safe-area-inset-top, 0px)) 16px 14px;
    border-bottom: 1px solid var(--border-color);
    background: var(--bg-secondary);
    flex-shrink: 0;
}

.modal-title {
    font-size: 15px;
    font-weight: 700;
    color: var(--text-primary);
}

.modal-back,
.modal-close {
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    /* Were 18px icons with 4px padding = a 26px target. These are the only way out of a
       full-screen modal, so they get the full 44px minimum. */
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    margin: -9px 0;          /* keep the 44px hit area without growing the header */
    border-radius: 0;
    flex-shrink: 0;
    touch-action: manipulation;
    transition: color 0.15s;
}

.modal-back:focus-visible,
.modal-close:focus-visible {
    outline: 2px solid var(--accent-green-neon);
    outline-offset: -2px;
}

.modal-back:hover,
.modal-close:hover {
    color: var(--accent-green);
}

.modal-body {
    flex: 1;
    overflow-y: auto;
    padding: 0;
}

/* Change match modal items */
.modal-date-label {
    text-align: center;
    padding: 12px;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-muted);
    background: var(--bg-secondary);
    border-radius: var(--radius-md);
    margin: 12px 16px 8px;
}

.modal-match-item {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 16px;
    padding: 16px;
    cursor: pointer;
    transition: background 0.1s;
    border-bottom: 1px solid rgba(var(--bg-tertiary-rgb), 0.2);
}

.modal-match-item:hover {
    background: var(--bg-secondary);
}

.modal-match-team {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    text-align: center;
}

.modal-match-team img {
    width: 44px;
    height: 44px;
    object-fit: contain;
}

.modal-match-team span {
    font-size: 13px;
    font-weight: 600;
}

.modal-match-center {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}

.modal-match-time {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-primary);
}

/* League list items */
.modal-league-item {
    padding: 16px 20px;
    font-size: 15px;
    font-weight: 700;
    color: var(--text-primary);
    cursor: pointer;
    transition: background 0.1s;
    border-bottom: 1px solid rgba(var(--bg-tertiary-rgb), 0.2);
}

.modal-league-item:hover {
    background: var(--bg-secondary);
}

/* ==========================================
   SPORT DETAIL PAGE
   ========================================== */
.sport-detail-header {
    /* Row layout so the collapse/expand-all button can sit at the RIGHT edge,
       level with the sport title. The back-link takes a full-width basis so it
       keeps its own line above them. */
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-bottom: 20px;
}
.sport-detail-header .sport-back-link { flex: 1 0 100%; }
.sport-detail-header .sport-detail-title { flex: 1; min-width: 0; }
.sport-detail-header .lc-toggle-all { margin-left: auto; }
/* The sort button (time-window lists, App._syncSportSortButton) leads the pair at the right
   edge when it shows; the collapse button then sits beside it. */
.sport-detail-header .sport-sort-btn[hidden] { display: none; }
.sport-detail-header .sport-sort-btn:not([hidden]) + .lc-toggle-all { margin-left: 0; }
.sport-sort-btn[aria-expanded="true"] { color: var(--text-primary); background: var(--bg-hover, var(--bg-lightg)); }

/* Inline sport sub-nav — horizontal pill row of quick filters
   (Live / In 3h / In 8h / Today / Leagues) shown on the sport-detail page
   for sports in _sportsWithSubmenu. The actual chips reuse the existing
   .sidebar-subitem class so the link semantics stay aligned with the
   desktop sidebar; this block just relays out the row. */
.sport-subnav {
    display: flex;
    gap: 6px;
    margin: 0 0 14px;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 2px;
    /* Standard horizontal scroller; `pan-x pan-y` so vertical swipes that
       land here still scroll the page (bare pan-x would swallow them). */
    touch-action: pan-x pan-y;
}
.sport-subnav::-webkit-scrollbar { display: none; }

/* Restyle the inherited subitem to look like a pill (it's a vertical list row
   in the sidebar context — needs to flatten in this horizontal row). */
.sport-subnav .sidebar-subitem {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 999px;
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    /* Reset whatever the sidebar context applied. */
    margin: 0;
    border-left: none;
}
.sport-subnav .sidebar-subitem svg {
    width: 14px;
    height: 14px;
    flex-shrink: 0;
}
.sport-subnav .sidebar-subitem:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}
.sport-subnav .sidebar-subitem.active {
    background: var(--accent-green-grad);
    border-color: var(--accent-green);
    color: var(--bg-green-deep);
}
.sport-subnav .sidebar-subitem.active svg { color: var(--bg-green-deep); }

/* Live indicator — softly pulsing red dot, like the 🔴 emoji. Halo only
   animates; the inner solid dot stays steady so the chip feels "lit" even
   between pulses. Applied wherever the live SVG appears (sidebar + the
   inline sport-subnav row). */
.sub-icon-live { overflow: visible; }
.sub-icon-live .sub-icon-live-halo {
    transform-origin: 12px 12px;
    animation: sub-icon-live-pulse 1.8s ease-in-out infinite;
}
@keyframes sub-icon-live-pulse {
    0%, 100% { transform: scale(0.85); opacity: 0.45; }
    50%      { transform: scale(1.10); opacity: 0.10; }
}
/* On the green active pill the red dot would clash — invert it to a
   darker red that still reads clearly against the green chip. */
.sport-subnav .sidebar-subitem.active .sub-icon-live circle { fill: var(--bg-green-deep); }

.sport-back-link {
    display: inline-flex;
    align-items: center;
    gap: 0px;
    font-size: 14px;
    color: var(--text-muted);
    margin-bottom: 20px;
    transition: color 0.15s;
    padding-left: 10px;
}

.live-md-main .sport-back-link {
    padding-left: 0px;
}


.sport-back-link:hover {
    color: var(--text-primary);
}

.sport-detail-title {
    display: flex;
    align-items: center;
    gap: 12px;
}

.sport-detail-icon {
    width: 32px;
    height: 32px;
}

.sport-detail-title h2 {
    font-size: 28px;
    font-weight: 800;
    color: var(--text-primary);
}

/* Country pills */
.sport-countries-wrapper {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 20px;
}

.sport-countries-scroll {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding-bottom: 4px;
    flex: 1;
    min-width: 0;
}

.sport-countries-scroll::-webkit-scrollbar {
    display: none;
}

.country-pill {
    flex: 0 0 auto;
    scroll-snap-align: start;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 16px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all 0.15s;
    white-space: nowrap;
    font-family: inherit;
    color: var(--text-primary);
    font-size: 13px;
    font-weight: 600;
}

.country-pill:hover {
    background: var(--bg-tertiary);
    border-color: var(--bg-hover);
}

.country-pill.active {
    border-color: var(--accent-green);
    background: rgba(0, 231, 1, 0.08);
}

.country-pill-flag {
    font-size: 16px;
}

.country-pill-name {
    font-weight: 600;
}

/* ===== 7-day date filter strip on the leagues-only view (#S<id>_L#) ===== */
.sport-date-strip {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    padding: 8px 2px;
    margin-top: 4px;
}
.sport-date-strip::-webkit-scrollbar { display: none; }

.sport-date-btn {
    flex: 0 0 auto;
    min-width: 64px;
    padding: 7px 12px;
    border-radius: 999px;
    border: 1px solid var(--border-color, var(--bg-lightg));
    background: var(--bg-card, var(--bg-tertiary));
    color: var(--text-secondary, #aab8c9);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.sport-date-btn:hover {
    color: var(--text-primary, #fff);
    border-color: var(--accent-green, #2ecc71);
}

.sport-date-btn.active {
    background: var(--accent-green, #2ecc71);
    border-color: var(--accent-green, #2ecc71);
    color: var(--bg-primary);
}

@media (max-width: 600px) {
    .sport-date-btn {
        min-width: 58px;
        padding: 6px 10px;
        font-size: 11px;
    }
}

/* ===== Leagues-only list (entry point: #S<id>_L#) ===== */
.leagues-list {
    display: flex;
    flex-direction: column;
    margin-top: 4px;
}

.leagues-list-section-title {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 14px 4px 12px;
    font-size: 15px;
    font-weight: 700;
    color: var(--text-primary);
}

.leagues-list-row {
    display: grid;
    grid-template-columns: 36px 1fr auto;
    align-items: center;
    gap: 12px;
    padding: 14px 6px;
    border-bottom: 1px solid var(--border-color);
    color: var(--text-primary);
    text-decoration: none;
    transition: background 0.15s;
    cursor: pointer;
}

.leagues-list-row:hover {
    background: rgba(255, 255, 255, 0.02);
}

.ll-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    overflow: hidden;
    flex-shrink: 0;
}

.ll-flag {
    font-size: 18px;
    line-height: 1;
    /* When the flag is a Twemoji <img class="emoji"> the parent <span> must be a flex
       container so the image centers cleanly inside the round 32×32 .ll-icon. The default
       img.emoji height of 1em + margin would otherwise leave it hugging the bottom-left. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
}
.ll-flag img.emoji {
    /* Override the global `img.emoji { height: 1em }` so the flag fills the icon chip. */
    width: 22px;
    height: 22px;
    margin: 0;
    vertical-align: middle;
}

.ll-star {
    color: #ffd83d;
    display: flex;
    align-items: center;
    justify-content: center;
}

.ll-label {
    font-size: 15px;
    font-weight: 500;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ll-count {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    background: var(--accent-green-grad);
    color: var(--bg-deep);
    border-radius: var(--radius-sm);
    font-size: 12px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}

.ll-count svg {
    flex-shrink: 0;
}

/* Category accordion (outright sports: Formula 1, MotoGP) — the league row
   is a <button> toggling an inline match list instead of navigating. */
.ll-cat-head {
    width: 100%;
    background: none;
    border: none;
    border-bottom: 1px solid var(--border-color);
    font-family: inherit;
    font-size: inherit;
    text-align: left;
}

.ll-cat-chev {
    display: inline-flex;
    transition: transform 0.15s;
}

/* Chevron points down when closed, up when open. */
.ll-cat-open .ll-cat-chev {
    transform: rotate(180deg);
}

/* Green flame inside the outright category rows' icon chip (bet365
   "featured" look). The flame asset carries no fill of its own — use it
   as a mask and paint it with the brand green. */
.ll-flame {
    width: 15px;
    height: 19px;
    background-color: #28ffbb;
    background-color: color(display-p3 .157 1 .733);
    -webkit-mask: url('/img/assets/flame_color.svg') no-repeat center / contain;
    mask: url('/img/assets/flame_color.svg') no-repeat center / contain;
    flex-shrink: 0;
}

/* Outright match header (F1, MotoGP, Speciale): a single event name with a
   "Book Closes …" line — no away side, no "v", no kits. */
.md-outright .match-detail-hero .md-team:last-of-type,
.md-outright .md-kit,
.md-outright .md-vs {
    display: none;
}

/* Stack vertically: event name centered, then the "Book Closes …" line
   and Change Match button underneath — the side-by-side home/away split
   makes no sense with a single-event title. */
.md-outright .match-detail-hero {
    flex-direction: column;
    align-items: center;
    gap: 4px;
}

/* Outright markets: entrant lists read as ONE column (name left, odds
   right — bet365 style), instead of the two-column player grid. */
.md-outright-markets .md-player-list {
    grid-template-columns: 1fr;
}

/* Merged 2-odd families (Yes/No per entrant): one pair per row. */
.md-market-odds.md-pair-grid {
    display: grid;
    grid-template-columns: 1fr 1fr;
}

/* Sport icon in outright category rows (replaces the flag/star). */
.ll-sport-ico {
    width: 18px;
    height: 18px;
    object-fit: contain;
}

.ll-cat-body {
    background: rgba(255, 255, 255, 0.015);
    border-bottom: 1px solid var(--border-color);
}

.ll-cat-loading {
    padding: 12px 16px;
    color: var(--text-muted);
    font-size: 13px;
}

.ll-cat-match {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    /* 26px indent + 16px icon + 12px gap = name starts at 54px, aligned
       with the league label above. */
    padding: 12px 16px 12px 26px;
    color: var(--text-primary);
    text-decoration: none;
    border-bottom: 1px solid rgba(var(--bg-tertiary-rgb), 0.35);
    transition: background 0.15s;
}

.ll-cat-match:last-child {
    border-bottom: none;
}

.ll-cat-match:hover {
    background: rgba(255, 255, 255, 0.03);
}

/* Sport icon (checkered flag) on the match rows inside an open category. */
.ll-cat-match-ico {
    width: 16px;
    height: 16px;
    object-fit: contain;
    flex-shrink: 0;
}

.ll-cat-match-name {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 14px;
}

.ll-cat-match-meta {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    flex-shrink: 0;
    color: var(--text-muted);
    font-size: 12px;
    font-variant-numeric: tabular-nums;
}

.ll-cat-match-date {
    color: var(--text-muted);
}

/* Date group header inside an open category. Season/event leagues (Boxing, MMA, Snooker,
   American Football) span months, so the match list is grouped by day — same
   "Today / Tomorrow / Pre Jul 18" labels the league page uses. Indent matches .ll-cat-match. */
.ll-cat-date {
    padding: 8px 16px 8px 26px;
    background: rgba(255, 255, 255, 0.03);
    border-bottom: 1px solid rgba(var(--bg-tertiary-rgb), 0.35);
    color: var(--text-muted);
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* Kick-off time on a match row — only rendered for non-outright sports (see showTime). */
.ll-cat-match-time {
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.country-pill-count {
    font-size: 11px;
    color: var(--text-muted);
}

/* Sport detail loading */
.sport-loading {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 60px 20px;
    color: var(--text-muted);
    font-size: 14px;
}

/* ==========================================
   BROWSE PAGE (Mobile sports A-Z)
   ========================================== */
.browse-search {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 16px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    margin-bottom: 20px;
}

.browse-search input {
    flex: 1;
    background: none;
    border: none;
    color: var(--text-primary);
    font-size: 15px;
}

.browse-search input::placeholder {
    color: var(--text-muted);
}

.browse-search-wrapper {
    position: relative;
    margin-bottom: 20px;
}

.browse-search-wrapper .browse-search {
    position: relative;
    z-index: 202;
    margin-bottom: 0;
}

.browse-search-overlay {
    display: none;
    position: fixed;
    inset: 0;
    background: rgba(var(--bg-primary-rgb), 0.6);
    z-index: 200;
}

.browse-search-overlay.active {
    display: block;
}

/* The search bar's 202 is a LOCAL decision — it only needs to clear its own
   dimming backdrop (.browse-search-overlay, 200) — but .browse-search-wrapper is
   `position: relative` with no z-index, so it never made a stacking context and
   that 202 competed page-wide. .betslip-overlay is 200, so opening Betslip or My
   Bets from the Sports tab drew the search bar straight across the open sheet.
   Same shape as the user-menu/search collision noted further down.
   All THREE need moving. .browse-search-dropdown is a SIBLING of .browse-search,
   not a child of it — both hang directly off the wrapper — so its 201 competes
   page-wide on its own and is not contained by lowering .browse-search. The
   backdrop moves too: it is meaningless while a modal is up, and at an equal 200
   the winner would otherwise be decided by DOM order. */
body.betslip-open .browse-search-wrapper .browse-search,
body.betslip-open .browse-search-wrapper .browse-search-dropdown,
body.betslip-open .browse-search-overlay {
    z-index: 1;
}

.browse-search-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    right: 0;
    max-height: 60vh;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg);
    box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5);
    overflow: hidden;
    z-index: 201;
    display: flex;
    flex-direction: column;
}

.browse-nav-links {
    display: flex;
    gap: 8px;
    margin-bottom: 20px;
    overflow-x: auto;
    scrollbar-width: none;
}

.browse-nav-links::-webkit-scrollbar {
    display: none;
}

.browse-nav-item {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 16px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-primary);
    font-size: 13px;
    font-weight: 600;
    white-space: nowrap;
    transition: all 0.15s;
}

.browse-nav-item svg {
    color: var(--text-muted);
    flex-shrink: 0;
}

.browse-nav-item:hover {
    background: var(--bg-tertiary);
    border-color: var(--accent-green);
}

.browse-section {
    margin-bottom: 20px;
}

.browse-section-title {
    font-size: 14px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 10px;
    color: var(--text-muted);
}

.browse-section-title.green {
    color: var(--accent-green);
}

.browse-sport-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 14px 16px;
    background: var(--bg-secondary);
    border-radius: var(--radius-md);
    margin-bottom: 3px;
    cursor: pointer;
    transition: background 0.15s;
    text-decoration: none;
    color: var(--text-primary);
}

.browse-sport-item:hover {
    background: var(--bg-tertiary);
}

.browse-sport-left {
    display: flex;
    align-items: center;
    gap: 12px;
}

.browse-sport-left img {
    width: 28px;
    height: 28px;
}

.browse-sport-left span {
    font-size: 15px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.browse-sport-arrow {
    color: var(--text-muted);
    font-size: 18px;
}

/* ==========================================
   A–Z SPORTS, LIVE FIRST (sidebar + mobile Browse)
   Direction D of the sports-menu canvas: the sports with matches in play lead
   as cards with their live count (and, in the sidebar, their filters); the rest
   follow as a compact list. App._sidebarLiveFirstHtml / _renderBrowseSports.
   ========================================== */
#sidebar-sports-section.live-first > .sidebar-heading {
    display: none;
}
.sb-group-live {
    margin-bottom: 14px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--border-subtle);
}
.sb-live-heading {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 0 8px 4px;
    font-size: 10px;
    line-height: 1;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.13em;
    color: #e7a3b1;
}

/* Live: a card, a size up. */
.sidebar-item.sport-row-live {
    padding: 9px 8px;
    margin: 6px 0 2px;
    background: rgba(var(--bg-deep-rgb), 0.64);
}
.sidebar-item.sport-row-live:hover,
.sidebar-item.sport-row-live.active {
    background: var(--bg-secondary);
}
.sport-row-live .sport-svg-icon {
    width: 20px;
    height: 20px;
}
.sport-row-live > span:not([class]) {
    font-size: 14.5px;
}
.sport-row-live .sb-live-num {
    font-size: 12px;
}

/* The rest: compact, no card. */
.sb-all-heading {
    padding-bottom: 6px;
}
.sidebar-item.sport-row-compact {
    padding: 6px 8px;
    margin: 0;
    border-radius: 0;
    font-size: 13px;
    color: var(--text-secondary);
}
.sidebar-item.sport-row-compact:hover,
.sidebar-item.sport-row-compact.active {
    background: var(--bg-secondary);
    color: #fff;
}
.sport-row-compact .sport-svg-icon {
    width: 16px;
    height: 16px;
    opacity: 0.9;
}
/* Room for the caret on a row with a submenu, whichever size it is. */
.sidebar-item.sport-row-live.has-submenu,
.sidebar-item.sport-row-compact.has-submenu {
    padding-right: 42px;
}

/* Mobile Browse (Sporte): one quiet list. Small muted section labels in one
   colour, calm pill links, the frequent cards without their colour bands, then
   every sport in one grouped list — live ones first, each with a red "58 Live"
   pill that opens its live matches (the row itself opens the sport). Three card
   styles, three heading colours and capitals everywhere made the page loud. */
.browse-search-wrapper {
    margin-bottom: 12px;
}
.browse-nav-links {
    gap: 6px;
    margin-bottom: 0;
}
.browse-nav-item {
    height: 40px;
    padding: 0 14px;
    border: 0;
    border-radius: 999px;
    background: rgba(var(--bg-deep-rgb), 0.64);
}
.browse-nav-item svg {
    width: 18px;
    height: 18px;
}
.browse-nav-item:hover {
    background: var(--bg-secondary);
}
#page-browse .browse-section {
    margin-bottom: 0;
}
#page-browse .browse-section-title {
    margin: 22px 2px 8px;
    font-size: 11px;
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: 0.08em;
    color: var(--text-muted);
}
.browse-all-list {
    border-radius: 0;
    background: rgba(var(--bg-deep-rgb), 0.64);
    overflow: hidden;
}
.browse-sport-item.browse-all-row {
    height: 56px;
    padding: 0 12px 0 14px;
    margin: 0;
    border-radius: 0;
    background: none;
}
.browse-sport-item.browse-all-row:hover {
    background: var(--bg-secondary);
}
.browse-all-row + .browse-all-row {
    border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.browse-all-left {
    display: flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
    color: inherit;
    text-decoration: none;
}
.browse-all-left img {
    width: 22px;
    height: 22px;
    flex: none;
}
.browse-all-left span {
    font-size: 15px;
    font-weight: 700;
    color:var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    text-transform: uppercase;
}
.browse-all-arrow {
    flex: none;
    color: var(--text-muted);
}
/* A live row is two links side by side: the name (prematch) takes the row, so
   it carries the row's left padding, and the pill (live matches) sits right. */
.browse-sport-item.browse-row-live {
    padding-left: 0;
}
.browse-row-live .browse-all-left {
    flex: 1 1 auto;
    align-self: stretch;
    padding-left: 14px;
}
.browse-live-pill {
    position: relative;
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 26px;
    padding: 0 10px 0 8px;
    border-radius: 999px;
    background: rgba(237, 65, 99, 0.12);
    border: 1px solid rgba(237, 65, 99, 0.24);
    color: #fff;
    text-decoration: none;
}
/* 26px pill, 48px row: stretch the hit area to the row's height. */
.browse-live-pill::after {
    content: "";
    position: absolute;
    inset: -11px -8px;
}
.browse-live-pill .sidebar-live-count {
    gap: 6px;
}
.browse-live-pill .sb-live-num {
    min-width: 0;
    padding: 0;
    border: 0;
    background: none;
    color: #fff;
    font-size: 12px;
    font-weight: 700;
}
.browse-live-pill .sb-live-waves svg {
    width: 14px;
    height: 11px;
}
.browse-live-pill-word {
    font-size: 11px;
    font-weight: 800;
    color: #ff7d90;
}

/* Frequently Visited on mobile sits on the same ground as the list. */
#browse-frequent-list .browse-sport-item {
    background: rgba(var(--bg-deep-rgb), 0.64);
}
#browse-frequent-list .browse-sport-item:hover {
    background: var(--bg-secondary);
}

/* ==========================================
   BOTTOM NAVIGATION BAR (Mobile/Tablet)
   ========================================== */
/* The BACKDROP. Square to the screen edges and running to the very bottom so
   page content cannot show through beside or beneath the bar — a floating pill
   on its own leaves a gap either side of it, and on iOS the home-indicator strip
   below it, through which rows scroll visibly.
   Painted in the PAGE colour so the bar reads as the page ending rather than a
   separate slab. The top radius and the drop shadow are gone: both drew the hard
   edge the fade replaces, and a rounded lip under a dissolve reads as a seam.

   The gradient is SOLID for the bottom half and fades out across the top half —
   so the bar is fully opaque exactly where the row of items sits, and dissolves
   from its midpoint upward. The pill carries its own background, so the items
   never lose their ground even though the nav behind them is thinning out.
   Keeping the ramp INSIDE the bar is also what leaves the glass something to do:
   the pill's upper portion then sits over see-through nav, so backdrop-filter has
   real content to blur. With a solid bar and the fade moved above it, the pane had
   nothing but flat colour behind it and the glass read as a plain tint. */
.bottom-nav {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 100;
    background: linear-gradient(to top,
        var(--bg-primary) 0%,
        var(--bg-primary) 50%,
        var(--bg-primary-fade) 100%);
    height: var(--bottom-nav-height);
    padding: 5px 10px;
    /* 14px floor, not 4px — this is what lifts the pill off the bottom edge and
       leaves Safari a solid strip of --bg-primary to sample. See the note on
       --bottom-nav-height. env() wins whenever the device reports a larger
       home-indicator inset, so the installed app is unchanged. */
    padding-bottom: max(env(safe-area-inset-bottom, 4px), 0px);
    /* The nav is the backdrop, the inner pill is the row — so this must stop
       being a flex ROW of items and become a single-child box. */
    align-items: center;
}

/* No ::before strip above the bar. A tall one was tried (92px) and it swamped the
   board — three rows of odds sitting under a dissolve, and with the bar solid
   behind it the glass pane had only flat colour to blur, so the frosted effect
   went with it. The short in-bar ramp above is the version that keeps both. */

/* The PILL. Floats inside the backdrop with the five items on it — frosted glass:
   a light translucent tint over a blurred sample of what is behind it, a hairline
   edge, and a top inner highlight for the lit rim a real pane catches.
   The blur only has something to work with across the pill's UPPER portion, where
   the nav's gradient has faded out; lower down it samples the bar's flat colour,
   which blurs to itself. That is the intended read — it looks like glass exactly
   where something is passing behind it, which is why the nav's ramp has to stay
   inside the bar rather than moving above it. */
.bottom-nav-inner {
    display: flex;
    align-items: stretch;
    width: 100%;
    height: 62px;
    padding: 4px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.07);
    border: 1px solid rgba(255, 255, 255, 0.10);
    /* blur ONLY — no saturate(). The usual glass recipe adds saturation because
       blurring a colourful backdrop (photos, vivid art) washes it out and the
       boost puts the colour back. Nothing here is colourful: the backdrop is the
       app's near-neutral navy, so there is nothing to restore and the filter just
       oversaturates the base. Measured — every background token in the palette
       sits at hue 200-203 / saturation 28-37%, and saturate(160%) took the pill to
       59.7% at that same hue. Same colour, half again as vivid, which is why it
       read as a deep blue cast against everything around it. */
    -webkit-backdrop-filter: blur(16px);
    backdrop-filter: blur(16px);
    /* NO outer drop shadow — inset highlight only. It used to carry
       `0 8px 22px rgba(0,0,0,0.35)`, which spans roughly offsetY + blur/2 = 19px
       below the pill. Only ~9px of solid --bg-primary sat between the pill and the
       page's bottom edge at the time, so the shadow covered that entire strip and
       overshot the viewport by 11px. iOS Safari tints its toolbar by sampling that
       strip, read --bg-primary under ~20% black, and painted its toolbar darker
       than the page — which looked like theme-color being ignored when in fact the
       meta was right and the pixels beneath it were wrong.
       If a lift is ever wanted back here, keep offsetY + blur/2 well under the
       clearance below the pill (currently ~19px, see --bottom-nav-height) or the
       toolbar seam returns. The inset highlight is safe: it paints inside the pill
       and never reaches the edge. */
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.10);
}

/* Without backdrop-filter the tint on its own is a washed-out panel with the page
   showing through it unblurred — worse than no glass at all. Fall back to the
   solid fill this replaced. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .bottom-nav-inner {
        background: var(--bg-input, var(--bg-input));
        border-color: rgba(255, 255, 255, 0.06);
    }
}

.bottom-nav-item {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    color: var(--text-muted);
    font-size: 12px;
    font-weight: 700;
    transition: color 0.15s, background-color 0.15s;
    -webkit-tap-highlight-color: transparent;
    /* Normalize so a <button> nav item (My Bets opens an overlay — it's an
       action, not a link) matches the <a> items exactly. */
    background: none;
    border: none;
    padding: 0;
    font-family: inherit;
    /* Matches the pill's inner radius so the active chip nests instead of
       squaring off inside a rounded track. */
    border-radius: 999px;
}

/* The active tab wears its own chip. Colour alone was carrying the whole state
   on a row of five same-sized icons; a filled shape is legible at a glance and
   at arm's length. */
.bottom-nav-item.active {
    color: var(--accent-green);
    /* background: var(--bg-secondary, #1f3743); */
}

.bottom-nav-item {
    position: relative;
}

.bottom-nav-badge {
    position: absolute;
    top: 2px;
    right: 50%;
    transform: translateX(14px);
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    background: var(--accent-red);
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Icon pairs (white + selected imgs, see index.html): the idle icon shows by
   default; .active swaps to the *_selected file, which brings its own
   gradient/glow — no CSS filter recoloring (that was the old SVG hack and it
   would flatten the gradients). Inplay is 34×30 — object-fit keeps it
   proportional inside the square box. */
.bottom-nav-icon {
    width: 28px;
    height: 28px;
    object-fit: contain;
    opacity: 0.7;
    transition: opacity 0.15s;
}

.bottom-nav-item .bni-active { display: none; }
.bottom-nav-item.active .bni-idle { display: none; }
.bottom-nav-item.active .bni-active { display: block; }

.bottom-nav-item.active .bottom-nav-icon {
    opacity: 1;
}

/* ==========================================
   FLOATING BETSLIP FAB (Mobile/Tablet)
   ========================================== */
.betslip-fab {
    display: none;
    position: fixed;
    z-index: 99;
    bottom: calc(72px + env(safe-area-inset-bottom, 0px));
    right: 16px;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: var(--accent-green-grad);
    color: var(--bg-deep);
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 16px rgba(0, 231, 1, 0.3);
    transition: transform 0.15s, box-shadow 0.15s;
    -webkit-tap-highlight-color: transparent;
}

.betslip-fab:active {
    transform: scale(0.93);
}

.betslip-fab svg {
    stroke: var(--bg-deep);
}

.betslip-fab-count {
    position: absolute;
    top: -4px;
    right: -4px;
    min-width: 20px;
    height: 20px;
    padding: 0 5px;
    background: var(--accent-red);
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* ==========================================
   BETSLIP OVERLAY (Mobile/Tablet)
   ========================================== */
.betslip-overlay {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 200;
    /* Keeps the slip in step with the on-screen keyboard sliding IN AND OUT. This must
       stay on the base rule: inside `body.bs-keyboard-open` it vanished with the class,
       so the close snapped while the keyboard was still easing down. */
    transition: height 0.3s cubic-bezier(0.22, 0.61, 0.36, 1);
    background: rgba(0, 0, 0, 0.6);
    display: flex;
    align-items: flex-end;
    justify-content: center;
    /* No explicit height — top:0 + bottom:0 already size the box, and the
     * <=900px block below overrides `bottom` to the bottom-nav height so the
     * overlay ends exactly ON the nav. Setting an explicit 100dvh here fought
     * that offset (panel ran under the nav on phones), and subtracting the nav
     * height unconditionally left a ~65px dead gap on tablets (e.g. 912px iPad)
     * where the nav doesn't exist and the page showed through. */
}

.betslip-overlay-panel {
    width: 100%;
    max-width: 500px;
    max-height: 85vh;
    background: var(--bg-secondary);
    border-radius: var(--radius-md) var(--radius-md) 0 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    /* Smooth the size/shape change when the panel switches state — e.g. Betslip →
       My Bets (.mybets-active grows it to near-full height) or the numpad opening
       (.bs-keyboard-open squares the bottom corners). Height/max-height are the
       properties that actually change, so they animate rather than snapping. */
    transition: all 300ms ease-in-out;
}

/* Respect the OS "reduce motion" setting — the resize is decorative. */
@media (prefers-reduced-motion: reduce) {
    .betslip-overlay-panel {
        transition: none;
    }
}

/* Prevent background scroll when overlay is open */
/* Page scroll lock while a full-screen sheet is up. Both use the plain `overflow`
   shorthand, which also overrides body's `overflow-x: clip` — normally something to
   avoid (see the note on body: overflow-x:hidden makes body a scroll container and
   kills position:sticky in Firefox), but sticky headers are moot while a modal
   covers them, and this is the shape already proven by betslip and the user menu. */
body.betslip-open,
body.chat-open {
    overflow: hidden;
}

/* The slip opened by itself on a first selection (App.peekBetslipOverlay): a sheet over
   the bottom of a LIVE page — no backdrop, taps outside the panel reach the page (so the
   next odd can be picked, which folds it back to the bar), and the page still scrolls.
   body's own overflow (visible + overflow-x: clip) is restored, not just `visible`. */
.betslip-overlay.bs-peek { background: transparent; pointer-events: none; }
.betslip-overlay.bs-peek .betslip-overlay-panel {
    pointer-events: auto;
    box-shadow: 0 -8px 24px rgba(var(--bg-deep-rgb), 0.55);
}
body.betslip-open.bs-peek:not(.chat-open) {
    overflow: visible;
    overflow-x: clip;
}

.betslip-overlay-header {
    display: flex;
    align-items: center;
    /* border-bottom: 1px solid var(--border-color); */
    height: 60px;
}

.betslip-overlay-header .betslip-tabs {
    flex: 1;
}

.betslip-close {
    padding: 12px 14px;
    background: none;
    color: var(--text-muted);
    transition: color 0.15s;
}

.betslip-close:hover {
    color: var(--text-primary);
}

.betslip-overlay-body {
    flex: 1;
    overflow: hidden;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    min-height: 250px;
}
/* The 250px floor is for the EMPTY slip's message. A slip with selections ends on
   its stake bar: there the floor left a blank band under the bar, above the bottom
   nav, whenever the content came out shorter (one pick, no "Ruaj" row). */
.betslip-overlay-body:has(.bs-foot) { min-height: 0; }

/* In overlay, bs-content becomes a flex column with fixed footer */
.betslip-overlay-body .bs-content {
    display: flex;
    flex-direction: column;
    height: 100%;
    max-height: calc(85vh - 50px);
}

/* The wrapper is now the flex-growing child of .bs-content; the list fills it. */
.betslip-overlay-body .bs-selections-wrap {
    flex: 1;
    min-height: 0;
}
.betslip-overlay-body .bs-selections {
    flex: 1;
    max-height: none;
    overflow-y: auto;
    min-height: 0;
}

.betslip-overlay-body .bs-totals,
.betslip-overlay-body .bs-stake,
.betslip-overlay-body .bs-place-btn,
.betslip-overlay-body .bs-result-area {
    /* `bs-result-area` had no flex-shrink rule, so when an accepted/rejected
     * message appeared it would get squeezed by the flex column instead of
     * pushing the selections list to shrink. With .bs-content overflow:hidden
     * that meant the bottom half of the message got clipped under the place
     * button. Pinning it to flex-shrink:0 makes the selections list scroll
     * within its remaining height while the message stays fully visible. */
    flex-shrink: 0;
}

/* ==========================================
   RESPONSIVE — TABLET (<=1100px)
   ========================================== */
@media (max-width: 1100px) {

    /* Hide desktop betslip, show FAB + overlay instead */
    .betslip-panel {
        display: none !important;
    }

    .betslip-fab {
        display: flex;
    }
}

/* ==========================================
   RESPONSIVE — SMALL TABLET / LARGE PHONE (<=900px)
   ========================================== */
@media (max-width: 900px) {
    .scroll-arrows {
        display: none;
    }

    /* Sidebar becomes slide-in drawer */
    .sidebar {
        position: fixed;
        top: var(--header-height);
        left: 0;
        bottom: 0;
        z-index: 90;
        transform: translateX(-100%);
        transition: transform 0.25s ease;
    }

    /* Drop shadow ONLY while the drawer is out.
       It used to live on .sidebar itself, which looked harmless because the panel
       is translated fully off-canvas — but `translateX(-100%)` moves the box, not
       what it paints. The shadow is offset +4px with a 24px blur, so it spilled
       from the hidden panel's right edge (x=0) to about x=28 and laid a dark band
       down the full height of every page, on every screen under 900px. Impossible
       to find by inspecting the page, because the element casting it is not on it.
       Tie it to .open and the drawer still gets its lift when it matters. */
    .sidebar.open {
        transform: translateX(0);
        box-shadow: 4px 0 24px rgba(0, 0, 0, 0.4);
    }

    .sidebar-overlay {
        display: none;
        position: fixed;
        top: var(--header-height);
        left: 0;
        right: 0;
        bottom: 0;
        background: rgba(0, 0, 0, 0.5);
        z-index: 89;
    }

    .sidebar-overlay.active {
        display: block;
    }

    .header-center {
        display: none;
    }

    /* Show bottom nav. z-index sits ABOVE the betslip overlay (200) so the user can still
       jump between Sporte/Slote/Live/Browse while the betslip is open. */
    .bottom-nav {
        display: flex;
        z-index: 300;
    }

    /* Keep the betslip overlay above the page but BELOW the bottom nav. Leaves room at the
       bottom so the panel content (place-bet button, etc.) sits cleanly above the nav. */
    .betslip-overlay {
        bottom: calc(var(--bottom-nav-height) - 5px);
        padding-bottom: 0;
    }
    /* Cap the panel height to the reduced overlay viewport so it never spills under the nav
       and the inner scroll containers (mybets-list / bs-selections) get a finite height.
       Use 100dvh so the cap shrinks when iOS Chrome/Safari's URL bar appears — otherwise
       the place-bet button and last ticket get pushed off the bottom of the screen. */
    .betslip-overlay-panel {
        /* Subtract the top inset too so a tall panel (many selections) can't push its
           header under the notch in the fullscreen app. env() = 0 in the browser. */
        max-height: calc(100dvh - var(--bottom-nav-height) - env(safe-area-inset-top, 0px));

        /* Matches the nav pill's geometry so the two read as one stack of floating
           surfaces. The sheet used to be `8px 8px 0 0` — rounded on top, square at
           the foot — which was right while the nav was a flat full-width bar the
           sheet could sit ON. The nav is now a rounded pill inset 10px, so a square
           bottom edge landed on nothing: it stopped 10px short of the pill with a
           strip of bar showing between, and read as a sheet cut off rather than a
           card resting above the menu.
           Same 10px side inset as .bottom-nav's padding, so the sheet and the pill
           share their left and right edges instead of one overhanging the other. */
        width: calc(100% - 20px);
        border-radius: 0;
    }

    /* Hide FAB when bottom nav is visible — use bottom nav "Bets" instead */
    .betslip-fab {
        display: none !important;
    }

    /* Add bottom padding for content so it doesn't hide behind bottom nav */
    .content {
        padding-bottom: calc(80px + env(safe-area-inset-bottom, 0px));
    }

    /* Betslip FAB moves above bottom nav */
    .betslip-fab {
        bottom: calc(74px + env(safe-area-inset-bottom, 0px));
    }

    .match-card {
        flex: 0 0 270px;
        min-width: 250px;
    }

    .leagues-grid {
        grid-auto-columns: minmax(200px, 260px);
    }

    /* Promo carousel goes full-width single slide */
    .promo-slide {
        flex: 0 0 300px;
        min-width: 300px;
    }
}

/* ==========================================
   RESPONSIVE — MOBILE (<=600px)
   ========================================== */
@media (max-width: 600px) {
    :root {
        --header-height: calc(var(--header-bar) + env(safe-area-inset-top, 0px));
    }

    .top-header {
        padding: env(safe-area-inset-top, 0px) 12px 0;
    }

    .header-left {
        min-width: auto;
        gap: 0px;
        /* Tighter than the desktop card — the padding that gives the group its
           shape is exactly what a 375px header cannot afford at full size. */
        padding: 3px 6px 3px 4px;
    }

    .logo-img {
        height: 50px;
    }

    /* The whole `-mini` artwork swap that used to live here is gone with the
       background-image toggle — the control is one shape at every width now, and
       the base rule is already icon-only, so phones need no override at all.
       Keeping the buttons at 36px here (vs 38) is the only concession: it buys
       back 4px of a header that has to fit a logo, this control and two auth
       buttons across 375px, and 36 is still above the 24px minimum for a pointer
       target sitting in a row of its own. */
    .product-toggle-btn {
        width: 36px;
        height: 36px;
    }

    .header-right {
        min-width: 0;       /* allow it to shrink within the header flex row */
        gap: 8px;
    }

    /* The flag and the user menu are fixed-size anchors — never shrink them, so
       a long balance can't push the menu icon off the right edge. */
    .lang-toggle {
        flex-shrink: 0;
    }

    /* The wallet is the release valve: it shrinks first and truncates the
       balance with an ellipsis only at extreme widths, keeping the menu icon
       fully on screen. The currency badge stays pinned (flex-shrink:0). */
    .wallet-display {
        padding: 6px 10px;
        font-size: 13px;
        min-width: 0;
        flex-shrink: 1;
        overflow: hidden;
    }

    .wallet-display #user-balance {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .wallet-display svg {
        display: none;
    }

    .currency-badge {
        font-size: 10px;
        padding: 1px 4px;
        flex-shrink: 0;
    }

    .content {
        padding: 10px;
        padding-bottom: 80px;
    }

    /* Grouped league matches — mobile. Fixed width on BOTH (matching the
       base rule's approach) so the header and odds columns stay aligned. */
    .league-match-odds {
        width: 180px;
    }

    .odds-header-labels {
        width: 180px;
    }

    .league-match-row {
        padding: 8px 12px;
    }

    .league-group-header {
        padding: 10px 12px;
    }

    .league-group-title {
        font-size: 11px;
    }

    .odd-btn-inline {
        font-size: 15px;
        padding: 5px 2px;
    }

    .content-tabs {
        margin-bottom: 20px;
    }

    .tab-btn {
        padding: 7px 14px;
        font-size: 12px;
    }

    .promo-slide {
        flex: 0 0 280px;
        min-width: 280px;
    }

    .promo-slide-title {
        font-size: 15px;
    }

    .promo-slide-subtitle {
        font-size: 11px;
    }

    .promo-slide-bg {
        padding: 16px;
    }

    .match-card {
        flex: 0 0 260px;
        min-width: 240px;
    }

    .mc-team-name {
        font-size: 12px;
    }

    .mc-kit {
        width: 40px;
        height: 40px;
    }

    .team-kit-lg {
        width: 40px;
        height: 40px;
    }

    .odd-btn-card-value {
        font-size: 13px;
    }

    .leagues-grid {
        grid-auto-columns: minmax(180px, 240px);
        gap: 8px;
    }

    .league-card {
        padding: 10px 12px;
    }

    .league-icon {
        width: 30px;
        height: 30px;
        font-size: 15px;
    }

    .league-name {
        font-size: 13px;
    }

    /* .section-header h3 sized in the DISPLAY TYPE block at the end of this file,
       desktop and mobile together — that block loads later and would override a
       font-size set here, so keeping the pair apart made the mobile value dead
       code. The 23px that used to sit here was compensating for Futura PT Cond's
       narrow cut; Oxanium does not need it. */

    .user-dropdown {
        position: fixed;
        top: var(--header-height);
        right: 8px;
        left: auto;               /* cancel any inherited left so it docks to the right edge */
        width: 92vw;
        max-width: 360px;
        /* Fit between the header and the bottom of the screen; scroll the overflow
           (dvh tracks the mobile URL-bar so the last item / "Dil" is never clipped). */
        max-height: calc(100dvh - var(--header-height) - 16px);
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        border-radius: 0;
    }

    .lang-dropdown {
        position: fixed;
        top: var(--header-height);
        right: 0;
        width: 180px;
        border-radius: 0 0 var(--radius-md) var(--radius-md);
    }
}
/* ==========================================
   LIVE MATCH DETAIL PAGE
   ========================================== */
.live-match-top {
    background: linear-gradient(180deg, #2a1a3a 0%, var(--bg-primary) 100%);
}

.live-md-hero {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 0px 0 0px;
}

.live-md-meta {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    font-size: 12px;
    color: var(--text-muted);
}

.live-md-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: #d32f2f;
    color: #fff;
    padding: 2px 8px;
    border-radius: 0;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.5px;
}

.live-md-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #fff;
    animation: live-pulse 1.4s infinite;
}

@keyframes live-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.35; }
}

.live-md-league {
    font-weight: 500;
}

/* Empty/closed markets state for live match detail */
.live-md-closed {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 32px 20px;
    margin: 12px 0;
    background: var(--bg-tertiary);
    border-radius: var(--radius-md);
    /* border: 1px dashed rgba(237, 65, 99, 0.4); */
    color: var(--text-muted);
    text-align: center;
    font-size: 14px;
    font-weight: 500;
}

.live-md-closed svg {
    color: var(--accent-red);
    opacity: 0.85;
}

.live-md-teams {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 5px;
    /* Top-align the two columns so the kits and form pills line up even when
       one team's name wraps to two lines (center alignment shifted the
       shorter column down). The reserved name height below keeps the scores
       aligned as well. */
    align-items: start;
    margin-bottom: 5px;
}

.live-md-team {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    text-align: center;
    margin:10px;
}



.live-md-team-name {
    font-size: 15px;
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1.2;
    /* Reserve two lines' height so a name that wraps on one side keeps the
       score (and everything below) aligned with the single-line side. Text is
       centered within the reserved box; width:100% constrains wrapping to the
       column so the name doesn't overflow. */
    min-height: 2.4em;
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Name + serving-ball row (tennis): keeps the ball beside the player name while
   the name still centres and wraps within the column. */
.live-md-name-row {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 5px;
    width: 100%;
}
.live-md-name-row .live-md-team-name {
    width: auto;
    min-width: 0;
    flex: 0 1 auto;
}
/* Serve ball — rides the racket icon's top-right corner (absolute inside
   .md-kit-wrap, a SIBLING of the kit div so kit innerHTML swaps can't wipe
   it). Bigger than the old name-row version + a gentle bounce so the eye
   catches whose serve it is. */
.md-kit-wrap {
    position: relative;
    display: inline-block;
}
.live-md-serve {
    position: absolute;
    top: -6px;
    right: -8px;
    width: 20px;
    height: 20px;
    z-index: 2;
    filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.6));
    animation: live-md-serve-bounce 1.2s ease-in-out infinite;
    pointer-events: none;
}
@keyframes live-md-serve-bounce {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-8px); }
}

/* Last 5 matches W/D/L pills under each team kit */
.live-md-form {
    display: flex;
    gap: 3px;
    margin-top: 4px;
    margin-bottom: 2px;
    min-height: 16px;
    justify-content: center;
}

.lmf-dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    font-size: 9px;
    font-weight: 800;
    color: #fff;
    letter-spacing: 0;
    line-height: 1;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
    cursor: default;
    -webkit-user-select: none;
    user-select: none;
}

.lmf-w { background: #16a34a; }
.lmf-d { background: var(--gray-mid); }
.lmf-l { background: var(--accent-red); }
.lmf-x { background: rgba(255, 255, 255, 0.1); color: var(--text-muted); }

/* Form-badge tooltip — the opponent and scoreline behind each W/D/L.
   Replaces `title`, which never appears on touch; these badges are 14-16px and
   touch is exactly where "who was that against?" is hardest to answer. Shown on
   hover, on keyboard focus, and on tap (JS adds .is-tipped — see
   Live._initFormTips). */
.lmf-dot[data-tip] {
    position: relative;
    cursor: pointer;
    border: none;
    padding: 0;
    font-family: inherit;
}

.lmf-dot[data-tip]::after {
    content: attr(data-tip);
    position: absolute;
    bottom: calc(100% + 7px);
    left: 50%;
    transform: translateX(-50%);
    z-index: 60;
    padding: 6px 9px;
    border-radius: 0;
    background: var(--bg-primary);
    border: 1px solid var(--border-color, var(--border-color));
    color: var(--text-primary, #fff);
    font-size: 11px;
    font-weight: 600;
    line-height: 1.35;
    letter-spacing: 0;
    /* The bubble must not inherit the badge's centring or its 9px type, and it
       must be allowed to be wider than its 16px parent. */
    white-space: nowrap;
    text-align: left;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.12s ease;
    pointer-events: none;
}

.lmf-dot[data-tip]::before {
    content: '';
    position: absolute;
    bottom: calc(100% + 2px);
    left: 50%;
    transform: translateX(-50%);
    z-index: 61;
    border: 5px solid transparent;
    border-top-color: var(--border-color, var(--border-color));
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.12s ease;
    pointer-events: none;
}

/* `hover: hover` guard so a tap on touch does not fire the hover rule as well as
   the .is-tipped toggle — on hybrid devices that combination leaves the bubble
   stuck open after the finger lifts. */
@media (hover: hover) {
    .lmf-dot[data-tip]:hover::after,
    .lmf-dot[data-tip]:hover::before {
        opacity: 1;
        visibility: visible;
    }
}

.lmf-dot[data-tip]:focus-visible::after,
.lmf-dot[data-tip]:focus-visible::before,
.lmf-dot[data-tip].is-tipped::after,
.lmf-dot[data-tip].is-tipped::before {
    opacity: 1;
    visibility: visible;
}

/* The form row clips its overflow for the pill layout; a bubble rising out of a
   16px badge needs the row to let it out. */
.live-md-form {
    overflow: visible;
}

/* Anchor the bubble to the row's OUTER side rather than centring it on the badge.
   A ~140px bubble centred on a 16px badge always overhangs at the ends of the
   row — measured at 653px wide: the first home badge's bubble started at -32px
   and both trailing away bubbles ran past the right edge. Anchoring is
   deterministic and needs no measuring at runtime; the arrow stays centred on the
   badge, which is what reads as "this one".
   The home row grows rightward off its first badge, the away row leftward off its
   last, so neither can leave the card. */
#live-md-home-form .lmf-dot[data-tip]::after {
    left: 0;
    transform: none;
}

#live-md-away-form .lmf-dot[data-tip]::after {
    left: auto;
    right: 0;
    transform: none;
}

@media (max-width: 600px) {
    .lmf-dot {
        width: 14px;
        height: 14px;
        font-size: 8px;
    }

    .live-md-teams .live-md-team {

    margin:0px;
}
}

.live-md-score {
    font-size: 32px;
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

/* Tennis live current-game points, shown under the big set score in the hero. */
.live-md-gamepts {
    display: inline-block;
    margin-top: 4px;
    min-width: 26px;
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--accent-green-grad);
    color: #05231a;
    font-size: 15px;
    font-weight: 800;
    line-height: 1.3;
    font-variant-numeric: tabular-nums;
}

/* Point-change notification: the new value drops in and the pill pulses. */
.live-md-gamepts.gamepts-flash {
    animation: gameptsDrop 0.55s cubic-bezier(0.2, 0.7, 0.2, 1);
}
@keyframes gameptsDrop {
    0%   { transform: translateY(-70%) scale(0.8);  opacity: 0.3; box-shadow: 0 0 0 7px rgba(86, 209, 141, 0.45); }
    45%  { transform: translateY(0)    scale(1.28); opacity: 1;   box-shadow: 0 0 0 4px rgba(86, 209, 141, 0.30); }
    100% { transform: translateY(0)    scale(1);    opacity: 1;   box-shadow: 0 0 0 0 rgba(86, 209, 141, 0); }
}

.live-md-status {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    font-size: 13px;
    color: var(--text-muted);
}

.live-md-minute {
    font-weight: 700;
    color: #ff5252;
    font-size: 14px;
    font-variant-numeric: tabular-nums;
}

.live-md-periods {
    font-size: 12px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    letter-spacing: 1px;
}

/* Match-detail stats row: 1H, corners, yellow/red cards */
.live-md-stats {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 14px;
    /* margin-top: 8px; */
    padding: 6px 10px;
    /* border-top: 1px solid var(--border-color); */
    color: var(--text-secondary);
    font-size: 13px;
    font-variant-numeric: tabular-nums;
    margin-bottom: 20px;
}

.live-md-stat {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 2px 10px;
    background: var(--bg-tertiary);
    /* border-radius: 999px; */
    line-height: 1;
    height: 20px;
}

/* Fixed leading slot — keeps icons/labels visually centered and the score start position consistent across every pill */
.live-md-stat-lead {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 14px;
    flex-shrink: 0;
}

/* Fixed score slot — same width whether the score is "0:0", "1:0", "10:8" */
.live-md-stat-score {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-width: 32px;
    font-variant-numeric: tabular-nums;
}

.live-md-stat-label {
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
    letter-spacing: 0.5px;
}

.live-md-stat-icon {
    color: var(--accent-green);
    display: block;
}

.live-md-stat-val {
    display: inline-block;
    min-width: 10px;
    text-align: center;
    font-weight: 700;
    color: var(--text-primary);
}

.live-md-stat-sep {
    color: var(--text-muted);
    font-weight: 500;
}

.live-md-card {
    display: inline-block;
    width: 10px;
    height: 14px;
    border-radius: 0;
    margin-right: 2px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}

/* Both cards are FLAT, FIXED colours — a referee's card is an identifying mark,
   so it must look identical on both sides of the header no matter what the
   count is. NOT var(--accent-red): that token is #ed4163, a crimson that reads
   as pink next to the yellow rather than as a red card. The token stays as-is —
   it is right for odds-down flashes and alerts, just not for this. */
.live-md-card-yellow { background: var(--gold); }
.live-md-card-red    { background: red; }

/* Score / stat flip animation */
.live-md-score,
.live-md-stat-val {
    display: inline-block;
    will-change: transform, opacity;
}

.score-flip-up {
    animation: scoreFlipUp 0.55s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.score-flip-down {
    animation: scoreFlipDown 0.55s cubic-bezier(0.2, 0.7, 0.2, 1);
}

@keyframes scoreFlipUp {
    0%   { transform: translateY(0)      scale(1);   opacity: 1; color: inherit; }
    35%  { transform: translateY(-90%)   scale(0.85); opacity: 0; }
    36%  { transform: translateY(90%)    scale(0.85); opacity: 0; }
    65%  { transform: translateY(0)      scale(1.15); opacity: 1; color: var(--accent-green); }
    100% { transform: translateY(0)      scale(1);   opacity: 1; color: inherit; }
}

@keyframes scoreFlipDown {
    0%   { transform: translateY(0)      scale(1);   opacity: 1; color: inherit; }
    35%  { transform: translateY(90%)    scale(0.85); opacity: 0; }
    36%  { transform: translateY(-90%)   scale(0.85); opacity: 0; }
    65%  { transform: translateY(0)      scale(1.15); opacity: 1; color: var(--accent-red); }
    100% { transform: translateY(0)      scale(1);   opacity: 1; color: inherit; }
}

@media (max-width: 600px) {
    .live-md-stats {
        gap: 8px;
        font-size: 12px;
    }
    .live-md-stat {
        padding: 2px 6px;
    }
}

/* ============================================
   Site Footer
   ============================================ */
.site-footer {
    margin-top: 32px;
    padding: 32px 24px 28px;
    background: var(--bg-secondary);
    border-top: 1px solid var(--border-color);
    color: var(--text-muted);
    font-size: 13px;
    line-height: 1.6;
}

.site-footer-top {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 32px;
    max-width: 1200px;
    margin: 0 auto;
}

.site-footer-col {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.site-footer-col h4 {
    color: var(--text-primary);
    font-size: 14px;
    font-weight: 700;
    margin: 0 0 6px;
}

.site-footer-col a,
.site-footer-link {
    color: var(--text-muted);
    text-decoration: none;
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    width: fit-content;
    transition: color 0.15s;
    text-align: left;
}

.site-footer-col a:hover,
.site-footer-link:hover {
    color: var(--text-primary);
}

/* Footer "Live TV" — emphasised with a pulsing live dot. */
.site-footer-livetv { font-weight: 600; color: var(--text-secondary); }
.site-footer-livetv:hover { color: var(--accent-green-neon, var(--text-primary)); }
.site-footer-livetv-dot {
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--accent-red);
    box-shadow: 0 0 0 3px rgba(237, 65, 99, 0.18);
    animation: footerLiveTvPulse 1.8s ease-in-out infinite;
}
@keyframes footerLiveTvPulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.4; } }
@media (prefers-reduced-motion: reduce) { .site-footer-livetv-dot { animation: none; } }

.site-footer-link-value {
    color: var(--text-secondary);
    font-weight: 500;
    margin-left: 2px;
}

.site-footer-dropdown-wrap {
    position: relative;
}

.site-footer-dropdown {
    position: absolute;
    bottom: calc(100% + 8px);
    left: 0;
    min-width: 200px;
    max-height: 280px;
    overflow-y: auto;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.45);
    z-index: 200;
    padding: 4px 0;
}

.site-footer-dropdown-option {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 14px;
    font-size: 13px;
    color: var(--text-secondary);
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}

.site-footer-dropdown-option:hover {
    background: var(--bg-hover);
    color: var(--text-primary);
}

.site-footer-dropdown-option.active {
    color: var(--accent-green);
}

.site-footer-divider {
    height: 1px;
    background: var(--border-color);
    margin: 28px auto 20px;
    max-width: 1200px;
}

.site-footer-badges {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
    max-width: 1200px;
    margin: 0 auto 20px;
}

.site-footer-badge {
    display: inline-flex;
    align-items: center;
    padding: 6px 12px;
    background: var(--bg-tertiary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.3px;
}

.site-footer-bottom {
    max-width: 1200px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.site-footer-logo {
    width: 96px;
    height: auto;
    margin-bottom: 6px;
    opacity: 0.9;
}

.site-footer-legal,
.site-footer-copy,
.site-footer-server-time,
.site-footer-cookies {
    margin: 0;
    color: var(--text-muted);
    font-size: 12px;
    line-height: 1.55;
}

.site-footer-server-time {
    font-weight: 600;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}

.site-footer-cookies {
    font-size: 11px;
    opacity: 0.8;
    margin-top: 8px;
}

@media (max-width: 900px) {
    .site-footer-top {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 24px;
    }
}

@media (max-width: 600px) {
    .site-footer {
        padding: 24px 16px 20px;
    }
    /* Two columns on a phone as well: Help and Statistics on the left, Results beside them, the
       language / odds format selects across the whole width under them (their labels are long). */
    .site-footer-top {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 18px 16px;
    }
    .site-footer-col-results { grid-column: 2; grid-row: 1 / span 2; }
    .site-footer-col-settings { grid-column: 1 / -1; }
}

/* ============================================
   Live match summary & stats collapsible panel
   ============================================ */
.live-md-summary {
    margin: 0px 0% 0;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    overflow: hidden;
    margin-bottom: 15px;
    box-shadow: #0003 0 4px 6px -1px, #0000001f 0 2px 4px -1px;
}

/* ============================================
   Live match video stream (allwatch1 HLS) + Stream/Scout switcher
   ============================================ */

/* Two-icon segmented control, centred above the pitch/stats row (like the
   old app). Both icons stay visible; the selected one shows its green variant
   via the .is-active class (which flips which of the two stacked <img>s show). */
.live-md-media-switch {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 10px;
    padding: 10px 0 10px;
}
.lmm-switch-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 4px;
    border: none;
    background: transparent;
    cursor: pointer;
    line-height: 0;
    opacity: 0.85;
    transition: opacity 0.15s ease, transform 0.15s ease;
}
.lmm-switch-btn:hover { opacity: 1; }
.lmm-switch-btn.is-active { opacity: 1; }
/* Show the "off" (grey) icon by default; the "on" (green/selected) icon only
   for the active button. */
.lmm-switch-btn .lmm-ico-on  { display: none; }
.lmm-switch-btn.is-active .lmm-ico-off { display: none; }
.lmm-switch-btn.is-active .lmm-ico-on  { display: inline-block; }

/* Video host card. The frame inside provides the 16:9 stage. */
.live-md-stream {
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    overflow: hidden;
}

/* "Solo" video (no scout pitch and no stats/summary panel for this sport, e.g.
   cricket): the lone flex child would otherwise grow to a full-width 16:9 stage.
   Cap the width and centre it so it reads as a normal player, not a billboard.
   Works in both the mobile `display: contents` stack and the desktop flex row —
   `margin: 0 auto` centres a block child and a flex item alike. */
.live-md-stream.is-solo {
    max-width: 640px;
    margin-left: auto;
    margin-right: auto;
}

/* 16:9 video stage. `aspect-ratio` keeps it responsive without JS; the
   status/error overlays absolutely fill it. */
.live-md-stream-frame {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: #000;
    overflow: hidden;
}

.live-md-stream-video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    background: #000;
    object-fit: contain;
}

/* Loading / error overlays centred on the black stage. */
.live-md-stream-status,
.live-md-stream-error {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 12px;
    text-align: center;
    color: rgba(255, 255, 255, 0.8);
    font-size: 13px;
    pointer-events: none;
}
.live-md-stream-status { background: rgba(0, 0, 0, 0.35); }
.live-md-stream-error {
    background: var(--bg-deep);
    cursor: pointer;          /* tap to retry */
    pointer-events: auto;
}

/* Desktop 50/50 row: the video shares the left column with the scout pitch
   (only one is visible at a time). Match the scout column's card chrome. */
@media (min-width: 1200px) {
    .live-md-row > .live-md-stream {
        flex: 1 1 calc(50% - 6px);
        min-width: 0;
        margin: 0;
        order: 1;                /* same slot as the scout (also order: 1) */
        align-self: flex-start;  /* don't stretch the 16:9 stage to summary height */
    }
}

/* ---- Floating "mini-player" (docks top-right when scrolled out of view) ----
   When the in-flow video scrolls off screen, the frame detaches to a fixed
   corner player while #live-md-stream stays put as a reserved-height placeholder
   (keeps the IntersectionObserver target stable so it doesn't flap). */
.live-md-stream.is-placeholder { aspect-ratio: 16 / 9; }

.live-md-stream-frame.is-floating {
    position: fixed;
    top: calc(var(--header-height) + 8px);
    right: 12px;
    width: 260px;
    max-width: 62vw;
    z-index: 900;               /* above content, below drawers/modals (≥1000) */
    border-radius: 0;
    box-shadow: 0 10px 30px rgba(0, 0, 0, 0.55);
    border: 1px solid rgba(255, 255, 255, 0.12);
}
@media (max-width: 480px) {
    .live-md-stream-frame.is-floating { width: 190px; right: 8px; }
}

/* Close (×) button — only shown in floating mode. */
.lmsv-close { display: none; }
.live-md-stream-frame.is-floating .lmsv-close {
    display: flex;
    position: absolute;
    top: 4px;
    right: 4px;
    width: 22px;
    height: 22px;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: none;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.6);
    color: #fff;
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    z-index: 2;
}
.live-md-stream-frame.is-floating .lmsv-close:hover { background: rgba(0, 0, 0, 0.8); }

/* Desktop layout: place the Live Pitch and the Stats / Summary panel side
   by side, splitting the row 50/50. iPad and mobile stack instead — the
   1200px breakpoint keeps iPad Pro (1024px landscape) on the stacked layout
   where the pitch can be a comfortable size. `flex: 1 1 0` + a hidden-
   sibling rule means if one panel is display:none, the other expands to
   fill the row instead of leaving half empty. */
/* `display: contents` makes the row's box vanish from layout — its children
   participate directly in #page-live-match's flow. Two benefits:
   1) scout / stripe / summary stack in DOM order (scout, stripe, summary)
      with no flex container shrinking them.
   2) `position: sticky` on the stripe gets the tall #page-live-match as its
      containing block, so it stays pinned under the top header across the
      entire match-detail scroll (markets + everything else).
   Overridden to `display: flex` on desktop where we want explicit 50/50. */
/* Plain block now. This used to be `display: contents` so its children could
   stack on mobile and pair 50/50 on desktop — but the pitch and the stats both
   moved into the side rail, so the row wraps ONLY the video stream and has no
   pairing left to do.
   NB this is not what fixed the 2x2 player below 1200px — the row is itself a
   flex item of .live-md-cols, so it collapsed for the same reason its child did.
   See the `align-items: stretch` note in the <=980px block. */
.live-md-row {
    display: block;
}

/* Unified desktop toggle — hidden on mobile where each panel keeps its own
   chevron. */
.live-md-row-toggle {
    display: none;
}
@media (min-width: 1200px) {
    .live-md-row {
        /* Was flex for the 50/50 pitch+stats pairing; that pairing is gone, so
           it only needs to be a full-width box for the stream. */
        display: block;
        margin: 8px 0 8px;
    }
    /* Two columns of 50% (minus half the 12px gap). Explicit basis is needed
       so `flex-wrap` can push the stripe to the second row instead of laying
       all three children on one line. */
    .live-md-row > .live-md-scout,
    .live-md-row > .live-md-summary {
        flex: 1 1 calc(50% - 6px);
        min-width: 0;     /* allow children to shrink below intrinsic width */
        margin: 0;        /* the row provides the outer spacing now */
    }
    .live-md-row > .live-md-scout    { order: 1; }
    /* flex-start so a collapsed summary shrinks to just its header instead of
       stretching to the scout column's height. */
    .live-md-row > .live-md-summary  { order: 2; align-self: flex-start; }
    /* Give the Live Pitch the same chrome as the Stats panel so they read as
       a matched pair. The pitch already has its own internal background for
       the field; this just wraps it in a card so both columns share visual
       weight. */
    .live-md-row > .live-md-scout {
        background: var(--bg-secondary);
        border: 1px solid var(--border-color);
        border-radius: var(--radius-md);
        padding: 10px 12px;
        overflow: hidden;
    }
    /* Drop the inner toggle's own dark bg so it sits flush on the card. */
    .live-md-row > .live-md-scout .lms-toggle {
        background: transparent;
        padding-left: 0;
        padding-right: 0;
    }

    /* --- Desktop panels --- */
    /* Hide the scout pitch's own chevron (its visibility is driven elsewhere),
       but KEEP the summary's chevron so the stats panel stays collapsible on
       desktop — the user can close it. */
    .live-md-row > .live-md-scout .lms-toggle {
        display: none;
    }
    /* Force the scout pitch body visible on desktop (its header is hidden, so a
       body left `hidden` would blank the column). The SUMMARY body is NOT forced
       — its own chevron toggles `hidden`, so collapsing actually hides it. */
    .live-md-row > .live-md-scout .lms-body[hidden] {
        display: block;
    }

    .live-md-row-toggle {
        display: flex;
        align-items: center;
        justify-content: space-between;
        width: 100%;
        padding: 10px 14px;
        margin: 8px 0 0;
        background: var(--bg-secondary);
        border: 1px solid var(--border-color);
        border-radius: var(--radius-md);
        color: var(--text-primary);
        cursor: pointer;
        font: inherit;
        font-size: 13px;
        font-weight: 600;
        display:none;
    }
    .live-md-row-toggle:hover {
        background: var(--bg-tertiary, var(--bg-secondary));
    }
    .live-md-row-toggle .lmrt-label {
        display: inline-flex;
        align-items: center;
        gap: 10px;
    }
    .live-md-row-toggle .lmrt-chev {
        transition: transform 0.2s ease;
    }
    /* When collapsed: rotate chevron, hide the row's two panels. The stripe
       lives OUTSIDE the row on desktop (JS places it after the row) so it
       stays visible and sticky-pinned even when collapsed. */
    .live-md-row-toggle[aria-expanded="false"] .lmrt-chev {
        transform: rotate(-90deg);
    }
    .live-md-row.collapsed {
        display: none;
    }
}

.live-md-summary-toggle {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 14px;
    background: var(--bg-hover);
    border: none;
    color: var(--text-primary);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s;
}

.live-md-summary-toggle:hover {
    background: var(--bg-hover);
}

.lmst-toggle-label {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--text-primary);
}

.lmst-chev {
    transition: transform 0.2s;
    color: var(--text-muted);
}

.live-md-summary.open .lmst-chev {
    transform: rotate(180deg);
}

/* Size container for the per-sport stats layouts inside.
   Those layouts were written when this panel spanned the page, so their "am I
   cramped?" rules were viewport media queries. In the desktop rail the panel is
   ~330px on a 1400px window — narrow panel, wide viewport — so none of them
   fired and the content simply overflowed the rail (basketball needed 467px of
   the 310px it had, and lost its whole away flank off the right edge).
   Querying the panel's OWN width fixes every sport at once and keeps working
   wherever the panel is placed next. */
.live-md-summary-body {
    container-type: inline-size;
    container-name: lmst;
    margin-bottom: 25px;
    margin-top:25px;
}

.live-md-summary-body[hidden] {
    display: none;
}

.lmst-tabs {
    display: flex;
    gap: 8px;
    padding: 8px 14px 0;
    border-top: 1px solid var(--border-color);
}

.lmst-tab {
    background: none;
    border: none;
    padding: 8px 4px 10px;
    color: var(--text-muted);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    border-bottom: 2px solid transparent;
    transition: color 0.15s, border-color 0.15s;
    line-height: 15px;
    margin-bottom: 15px;
}

.lmst-tab:hover { color: var(--text-secondary); }

.lmst-tab.active {
    color: var(--text-primary);
    border-bottom-color: var(--text-primary);
}

.lmst-panel {
    display: none;
    padding: 7px;
}

.lmst-panel.active {
    display: block;
}

/* =================================================================
   Basketball stats panel (sportId === 2)
   ================================================================= */
.lmst-bb-score {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 14px;
    font-size: 13px;
    color: var(--text-secondary);
}

.lmst-bb-score th,
.lmst-bb-score td {
    padding: 6px 4px;
    text-align: center;
    border-bottom: 1px solid var(--border-color);
}

.lmst-bb-score thead th {
    color: var(--text-muted);
    font-weight: 600;
    font-size: 12px;
}

.lmst-bb-score tbody th {
    text-align: left;
    color: var(--text-primary);
    font-weight: 700;
}

.lmst-bb-sep {
    background: rgba(0, 231, 1, 0.05);
    font-weight: 600;
}

.lmst-bb-total {
    font-weight: 800;
    color: var(--accent-green);
    font-size: 15px;
}

.lmst-bb-stats {
    display: grid;
    grid-template-columns: 1fr 1.4fr 1fr;
    gap: 10px;
    align-items: center;
    padding-top: 4px;
    border-top: 1px solid var(--border-color);
}

.lmst-bb-flank {
    display: flex;
    gap: 8px;
    justify-content: center;
}

.lmst-bb-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    padding: 4px 8px;
    min-width: 48px;
    background: var(--bg-tertiary);
    border-radius: var(--radius-sm);
    border-bottom: 2px solid var(--accent-red);
}

.lmst-bb-card-val {
    font-size: 18px;
    font-weight: 800;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.lmst-bb-card-lbl {
    font-size: 10px;
    color: var(--text-muted);
}

.lmst-bb-card-2pt { border-bottom-color: var(--gold); }
.lmst-bb-card-3pt { border-bottom-color: var(--accent-green); }
.lmst-bb-card-fouls { border-bottom-color: var(--accent-red); }

.lmst-bb-center {
    display: flex;
    flex-direction: column;
    gap: 6px;
    align-items: stretch;
    text-align: center;
}

.lmst-bb-timeouts {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: 8px;
}

.lmst-bb-timeouts-lbl {
    font-size: 11px;
    color: var(--text-muted);
    font-weight: 600;
}

.lmst-bb-dots {
    display: inline-flex;
    gap: 3px;
    justify-content: center;
}

.lmst-bb-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.15);
}

.lmst-bb-dot.on {
    background: var(--accent-red);
}

.lmst-bb-ft {
    display: grid;
    grid-template-columns: auto 1fr auto;
    gap: 6px;
    align-items: center;
}

.lmst-bb-ft-side {
    font-size: 12px;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}

.lmst-bb-ft-side b {
    color: var(--text-primary);
    margin-right: 2px;
    font-size: 14px;
}

.lmst-bb-ft-bar {
    display: flex;
    height: 4px;
    border-radius: 2px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.08);
}

.lmst-bb-ft-bar-h { background: var(--accent-red); transition: width 0.4s; }
.lmst-bb-ft-bar-a { background: rgba(255, 255, 255, 0.25); transition: width 0.4s; }

.lmst-bb-ft-lbl {
    font-size: 11px;
    color: var(--text-muted);
}

/* =================================================================
   Tennis stats panel (sportId === 3)
   ================================================================= */
.lmst-tn-court {
    text-align: center;
    font-size: 11px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.6px;
    margin-bottom: 8px;
}

.lmst-tn-header {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: 12px;
    align-items: center;
    margin-bottom: 14px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--border-color);
}

.lmst-tn-side {
    font-weight: 700;
    color: var(--text-primary);
    font-size: 14px;
    line-height: 1.25;
    min-width: 0;
    /* A long name ("Juan Carlos Prado Angelo") wraps onto a second line instead of
       being cut with "…"; only a name longer than two lines is clipped. */
    overflow: hidden;
    overflow-wrap: break-word;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
}

.lmst-tn-side-a { text-align: right; }

.lmst-tn-mid {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
}

.lmst-tn-sets-lbl {
    font-size: 10px;
    text-transform: uppercase;
    color: var(--text-muted);
    letter-spacing: 0.6px;
}

.lmst-tn-sets {
    font-weight: 800;
    color: var(--accent-green);
    font-size: 18px;
    font-variant-numeric: tabular-nums;
}

.lmst-tn-games {
    font-size: 11px;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}

/* Head-to-head stat rows: home value | label | away value, with a proportional
   split bar beneath. Replaces a flank/center/flank grid that interleaved three
   unrelated metrics per visual row. Colour language is consistent with the
   momentum ticks: home = green, away = purple. */
.lmst-tn-cmp {
    display: grid;
    gap: 13px;
}

.lmst-tn-cmp-row {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: baseline;
    column-gap: 10px;
    row-gap: 6px;
}

.lmst-tn-cmp-v {
    font-size: 14px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: var(--text-primary);
    /* Reserve a stable column so the centre label doesn't shift as values change. */
    min-width: 34px;
}

.lmst-tn-cmp-v-h { text-align: left; }
.lmst-tn-cmp-v-a { text-align: right; }

.lmst-tn-cmp-lbl {
    text-align: center;
    font-size: 11.5px;
    line-height: 1.3;
    color: var(--text-muted);
    min-width: 0;      /* let a long label wrap instead of stretching the row */
}

/* Bars grow outward from the centre line, each side scaled against the leader —
   so the longer bar always means "more", and equal values read as symmetric.
   A single full-width split bar looked like a divider at panel width. */
.lmst-tn-cmp-bar {
    grid-column: 1 / -1;
    display: flex;
    align-items: center;
    gap: 3px;               /* the gap IS the centre line */
    height: 5px;
}

.lmst-tn-cmp-half {
    flex: 1;
    display: flex;
    height: 100%;
    background: rgba(255, 255, 255, 0.06);
    border-radius: 0;
    overflow: hidden;
}

/* Home fills toward the centre (right edge), away away from it (left edge). */
.lmst-tn-cmp-half-h { justify-content: flex-end; }
.lmst-tn-cmp-half-a { justify-content: flex-start; }

.lmst-tn-cmp-half i {
    display: block;
    height: 100%;
    border-radius: 0;
    transition: width 0.4s ease;
}

.lmst-tn-cmp-half-h i { background: var(--accent-green-grad); }
.lmst-tn-cmp-half-a i { background: #a855f7; }

/* Lower-is-better stats: show the ratio without awarding the accent colour. */
.lmst-tn-cmp-bar-neutral .lmst-tn-cmp-half-h i,
.lmst-tn-cmp-bar-neutral .lmst-tn-cmp-half-a i {
    background: rgba(255, 255, 255, 0.28);
}

/* Ties the green/purple bars back to the two players. */
.lmst-tn-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    vertical-align: middle;
}

.lmst-tn-dot-h { background: var(--accent-green-neon); margin-right: 6px; }
.lmst-tn-dot-a { background: #a855f7; margin-left: 6px; }

/* =================================================================
   Tennis match-progression (set table + point history) — from scoreList
   ================================================================= */
.lmst-tn-progress {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 14px;
}

.lmst-tn-sets-tbl {
    width: 100%;
    border-collapse: collapse;
    font-size: 13px;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}
.lmst-tn-sets-tbl th,
.lmst-tn-sets-tbl td {
    padding: 5px 4px;
    text-align: center;
    border-bottom: 1px solid var(--border-color);
}
.lmst-tn-sets-tbl thead th {
    color: var(--text-muted);
    font-weight: 600;
    font-size: 12px;
}
.lmst-tn-sets-tbl tbody th.lmst-tn-sets-name {
    text-align: left;
    color: var(--text-primary);
    font-weight: 700;
    max-width: 130px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.lmst-tn-sets-tbl tbody td {
    color: var(--text-primary);
    font-weight: 700;
}
/* Current (in-progress) set column — subtle highlight. */
.lmst-tn-set-cur {
    background: rgba(86, 209, 141, 0.08);
}
/* Live game-points column. */
.lmst-tn-pts-col {
    color: var(--accent-green) !important;
    font-weight: 800;
}

/* Point-history momentum — a tick per point, coloured by who won. */
.lmst-tn-mom-lbl {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 5px;
}
.lmst-tn-mom-row {
    display: flex;
    align-items: flex-end;
    gap: 2px;
    overflow-x: auto;
    padding-bottom: 2px;
    touch-action: pan-x pan-y;
}
.lmst-tn-mom-tick {
    flex: 0 0 auto;
    width: 5px;
    height: 14px;
    border-radius: 0;
    background: rgba(255, 255, 255, 0.15);
}
.lmst-tn-mom-h { background: var(--accent-green-grad); }
.lmst-tn-mom-a { background: #a855f7; }
.lmst-tn-mom-sep { margin-left: 7px; }

/* =================================================================
   Cricket stats panel (sportId === 18)
   ================================================================= */
.lmst-ck {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* Innings scoreboard — one row per side, batting side highlighted. */
.lmst-ck-innings {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.lmst-ck-inn {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 12px;
    background: var(--bg-tertiary);
    border-radius: var(--radius-sm);
    border-left: 3px solid transparent;
}
.lmst-ck-inn-live {
    border-left-color: var(--accent-green);
}
.lmst-ck-inn-team {
    font-size: 13px;
    font-weight: 700;
    color: var(--text-primary);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.lmst-ck-inn-score {
    font-size: 16px;
    font-weight: 800;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
    padding-left: 10px;
}
.lmst-ck-inn-live .lmst-ck-inn-score {
    color: var(--accent-green);
}

/* Live batting / bowling two-column block. */
.lmst-ck-live {
    display: flex;
    gap: 10px;
}
.lmst-ck-col {
    flex: 1 1 0;
    min-width: 0;
    background: var(--bg-tertiary);
    border-radius: var(--radius-sm);
    padding: 8px 10px;
}
.lmst-ck-col-bowl {
    flex: 0 0 40%;
}
.lmst-ck-hdr {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 6px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 6px;
}
.lmst-ck-meta {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0;
    text-transform: none;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}
.lmst-ck-bat-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    padding: 3px 0;
}
.lmst-ck-bat-name {
    font-size: 13px;
    color: var(--text-primary);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.lmst-ck-strike {
    color: var(--accent-green);
    font-weight: 800;
    margin-left: 2px;
}
.lmst-ck-bat-rb {
    font-size: 13px;
    font-weight: 700;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}
.lmst-ck-balls {
    color: var(--text-muted);
    font-weight: 500;
}
.lmst-ck-bowl-row {
    font-size: 13px;
    color: var(--text-primary);
    padding: 3px 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.lmst-ck-empty {
    font-size: 13px;
    color: var(--text-muted);
    padding: 3px 0;
}
.lmst-ck-target {
    text-align: center;
    font-size: 12px;
    font-weight: 700;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
    padding: 6px;
    background: var(--bg-tertiary);
    border-radius: var(--radius-sm);
}

/* --- Statistika panel: gauges --- */
.lmst-gauges {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
    margin-bottom: 14px;
}

.lmst-gauge-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
}

.lmst-gauge-label {
    font-size: 12px;
    color: var(--text-muted);
    text-align: center;
    line-height: 1.2;
    /* Reserve at least one line so single- vs two-line labels stay close enough in vertical position */
    min-height: 1.2em;
    display: flex;
    align-items: flex-start;
    justify-content: center;
}

.lmst-gauge {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
}

.lmst-gauge-val {
    font-size: 18px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    min-width: 22px;
    text-align: center;
}

.lmst-gauge-h { color: var(--text-primary); }
.lmst-gauge-a { color: var(--text-muted); }

.lmst-gauge-svg {
    flex-shrink: 0;
}

.lmst-gauge-icon {
    color: var(--accent-green);
}

/* --- Statistika panel: shots + flanks row --- */
.lmst-shots-row {
    display: grid;
    grid-template-columns: minmax(72px, auto) 1fr minmax(72px, auto);
    gap: 10px;
    align-items: center;
    padding: 14px 4px 0;
    border-top: 1px solid var(--border-color);
}

.lmst-flank {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-variant-numeric: tabular-nums;
}

.lmst-flank-icons,
.lmst-flank-vals {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    /* text-align: center; */
    align-items: center;
}

.lmst-flank-icons {
    color: var(--text-muted);
}

.lmst-flank-vals {
    font-weight: 700;
    font-size: 14px;
    color: var(--text-primary);
    text-align: center;
}

.lmst-card {
    display: inline-block;
    width: 10px;
    height: 14px;
    border-radius: 0;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}

.lmst-card-yellow { background: var(--gold); }
.lmst-card-red    { background: var(--accent-red); }

.lmst-shots {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
}

.lmst-shots-label {
    font-size: 12px;
    color: var(--text-muted);
}

.lmst-shots-bars {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
}

.lmst-shots-val {
    font-size: 13px;
    font-weight: 700;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    min-width: 28px;
    text-align: center;
}

.lmst-shots-mid {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.lmst-shots-bar {
    position: relative;
    height: 4px;
    background: rgba(255, 255, 255, 0.08);
    border-radius: 2px;
    overflow: hidden;
}

.lmst-shots-bar-h .lmst-shots-fill-total { background: #d5cf2c; }
.lmst-shots-bar-a .lmst-shots-fill-total { background: #d5cf2c; opacity: 0.5; }

.lmst-shots-fill {
    position: absolute;
    top: 0;
    height: 100%;
}

.lmst-shots-fill-total {
    left: 0;
    background: rgba(213, 207, 44, 0.45);
    border-radius: 0;
}

.lmst-shots-fill-on {
    left: 0;
    background: var(--accent-green-grad);
    border-radius: 0;
}

/* --- Statistika panel: the team statistics AutoLive 1.1.37 adds (football) ---
   xG across the top, the action-areas pitch and a two-colour bar per statistic
   under the shots row. Home is the lime the gauges already use, away the muted
   tone; every block appears only when the feed sent its key. */
.lmst-xg {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    margin-bottom: 14px;
    font-variant-numeric: tabular-nums;
}
.lmst-xg-val { font-size: 22px; font-weight: 800; color: var(--text-primary); line-height: 1; }
.lmst-xg-lbl { font-size: 12px; color: var(--text-muted); cursor: help; }
.lmst-xg-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.lmst-xg-dot-h { background: var(--accent-green); }
.lmst-xg-dot-a { background: var(--text-muted); }

.lmst-sec-label {
    text-align: center;
    font-size: 12px;
    color: var(--text-muted);
    margin-bottom: 8px;
}
.lmst-areas {
    margin-top: 14px;
    padding: 14px 4px 0;
    border-top: 1px solid var(--border-color);
}
.lmst-areas-pitch {
    position: relative;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    height: 78px;
    border-radius: var(--radius-sm);
    overflow: hidden;
    background: var(--bg-input);
    color: var(--bg-lightg);
}
.lmst-areas-lines { position: absolute; inset: 0; width: 100%; height: 100%; }
/* Drawn apart from the SVG so it stays round however wide the pitch gets. */
.lmst-areas-circle {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 38px;
    height: 38px;
    transform: translate(-50%, -50%);
    border: 1px solid var(--bg-lightg);
    border-radius: 50%;
}
.lmst-area {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 17px;
    font-weight: 800;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    text-shadow: 0 1px 2px var(--bg-input);
}
/* Tinted by the share of play (--p, 0..1): the busier the third, the stronger. */
.lmst-area::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    opacity: calc(0.08 + var(--p, 0) * 0.7);
}
.lmst-area-h::before { background: var(--accent-green); }
.lmst-area-m::before { background: var(--text-primary); opacity: calc(var(--p, 0) * 0.14); }
.lmst-area-a::before { background: var(--text-muted); }

.lmst-bars {
    display: flex;
    flex-direction: column;
    gap: 14px;
    margin-top: 14px;
    padding: 14px 4px 0;
    border-top: 1px solid var(--border-color);
}
.lmst-bar-row {
    display: grid;
    grid-template-columns: 44px minmax(0, 1fr) 44px;
    align-items: end;
    column-gap: 10px;
}
/* Fonbet's own counters start after a break from the provider's statistics. */
.lmst-bar-row-gap {
    padding-top: 14px;
    border-top: 1px dashed var(--border-color);
}
.lmst-bar-val {
    font-size: 15px;
    font-weight: 800;
    line-height: 1;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    text-align: right;
}
.lmst-bar-row .lmst-bar-val:last-child { text-align: left; }
.lmst-bar-mid { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.lmst-bar-lbl {
    font-size: 12px;
    color: var(--text-muted);
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Square, like the shots bars above it. */
.lmst-bar-track {
    display: flex;
    height: 4px;
    overflow: hidden;
    background: var(--bg-tertiary);
}
.lmst-bar-track i { display: block; height: 100%; }
.lmst-bar-h { background: var(--accent-green); }
.lmst-bar-a { background: var(--text-muted); }

/* --- Permbledhje panel: progress bar --- */
.lmst-progress {
    position: relative;
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 14px;
}

.lmst-progress-bar {
    position: relative;
    flex: 1;
    height: 8px;
    background: rgba(255, 255, 255, 0.1);
    border-radius: 4px;
}

.lmst-progress-fill {
    height: 100%;
    background: linear-gradient(90deg, #2e8e5d, var(--accent-green));
    border-radius: 0;
    transition: width 0.4s ease;
}

.lmst-progress-ball {
    position: absolute;
    top: 50%;
    transform: translate(-50%, -50%);
    transition: left 0.4s ease;
}

.lmst-progress-min {
    background: rgba(0, 0, 0, 0.4);
    border-radius: 0;
    padding: 3px 8px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text-primary);
}

/* === Scout pitch — decoded from scoutMessage ===
 * Sits directly under .live-md-stats. Contains a timeline strip on top + a
 * football-pitch SVG below with field markings, a translucent gray "attack zone"
 * wedge with directional arrows, and an overlay (minute + team name + event).
 * Hidden when there's no decodable message. */
.live-md-scout {
    display: flex;
    flex-direction: column;
    width: 100%;
    overflow: hidden;
    border-radius: var(--radius-md);
    margin: 0px 0 0px;
    /* background: #1a6630; */
}

/* --- header toggle (click to collapse pitch+timeline body) --- */
.lms-toggle {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 6px 12px;
    margin: 0 0 6px;
    background: rgba(0, 0, 0, 0.45);
    border: none;
    border-radius: var(--radius-sm);
    color: var(--text-primary);
    cursor: pointer;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    align-self: flex-start;
    display:none;
}

.lms-toggle:hover { background: rgba(0, 0, 0, 0.55); }

.lms-toggle-title {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: rgba(255, 255, 255, 0.85);
}

.lms-toggle-chev {
    transition: transform 0.18s ease;
    opacity: 0.7;
}

.lms-body[hidden] { display: none; }

/* --- timeline strip on top --- */
.lms-timeline {
    position: relative;
    padding: 18px 4px 4px;
    background: rgba(0, 0, 0, 0.42);
}

.lms-tl-track {
    position: relative;
    height: 22px;
}

.lms-tl-axis {
    position: absolute;
    left: 0; right: 0;
    top: 50%;
    height: 1px;
    background: rgba(255, 255, 255, 0.25);
}

.lms-tl-htband {
    position: absolute;
    top: 3px;
    bottom: 3px;
    background: rgba(255, 255, 255, 0.12);
    border-radius: 0;
}

.lms-tlm {
    position: absolute;
    top: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 0;
}

/* home markers above the axis, away markers below */
.lms-tlm-h { transform: translate(-50%, -100%); }
.lms-tlm-a { transform: translate(-50%, 0%); }

.lms-tl-ticks {
    position: relative;
    height: 14px;
    color: rgba(255, 255, 255, 0.6);
    font-size: 10px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.lms-tl-tick {
    position: absolute;
    top: 0;
    transform: translateX(-50%);
}

.lms-tl-tick-plus { color: rgba(255, 255, 255, 0.4); }

/* --- pitch + overlay --- */
/* The wrap is the 3D stage for the tilted pitch, dressed as a stadium bowl:
 * the 3D backdrop photo (stands + scoreboard up top, silhouetted crowd along
 * the bottom) fills the wrap, and the tilted SVG pitch sits in the image's
 * grass zone so the crowd frames it. The deep-green fallback paints while the
 * jpg loads (and if it ever 404s). */
/* ---- Goalscorers pill + panel -----------------------------------------------
   Top-left of the pitch, over the grass. Same reason as .lms-pk for being
   absolute: the wrap's aspect-ratio and perspective are calibrated against the
   pitch SVG's 3D transform, so anything in normal flow shrinks the grass and
   pulls the markings off the photo.
   Collapsed to the pill by default — the pitch belongs to the ball, and a
   permanent list would sit over the half the action is usually in. */
.lms-gs {
    position: absolute;
    top: 6px;
    left: 6px;
    z-index: 7;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 5px;
    max-width: calc(100% - 12px);
}

.lms-gs-pill {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 9px;
    border: none;
    border-radius: 999px;
    background: rgba(var(--bg-primary-rgb), 0.82);
    color: var(--text-primary, #fff);
    font-family: inherit;
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
}

.lms-gs-pill svg { width: 13px; height: 13px; flex-shrink: 0; }

.lms-gs-count {
    padding: 1px 5px;
    border-radius: 999px;
    background: var(--accent-green-neon, #c0e849);
    color: var(--bg-deep);
    font-size: 10px;
    font-variant-numeric: tabular-nums;
}

.lms-gs-panel {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4px 14px;
    padding: 8px 10px;
    border-radius: 0;
    background: rgba(var(--bg-primary-rgb), 0.9);
    border: 1px solid var(--border-color, var(--border-color));
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
    box-shadow: 0 10px 24px rgba(0, 0, 0, 0.5);
    /* The panel can outgrow a short pitch on a long scoreline — scroll inside
       itself rather than pushing past the grass. */
    max-height: 148px;
    overflow-y: auto;
}

.lms-gs-panel[hidden] { display: none; }

.lms-gs-col { min-width: 0; }

.lms-gs-team {
    /* Pinned: the two columns scroll as one box, so without this the team names
       slide away and a column of bare minutes says nothing about who scored. */
    position: sticky;
    top: 0;
    z-index: 1;
    background: rgba(var(--bg-primary-rgb), 0.95);
    padding-bottom: 2px;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--text-muted, #7c8798);
    margin-bottom: 3px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.lms-gs-col ul { list-style: none; margin: 0; padding: 0; }

.lms-gs-row {
    display: flex;
    align-items: baseline;
    gap: 6px;
    font-size: 11px;
    line-height: 1.45;
    color: var(--text-primary, #fff);
}

.lms-gs-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.lms-gs-min {
    flex-shrink: 0;
    margin-left: auto;
    color: var(--accent-green-neon, #c0e849);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.lms-gs-none { font-size: 11px; color: var(--text-muted, #7c8798); }

/* ---- Penalty shootout strip -------------------------------------------------
   Overlays the top of the pitch during a shootout. ABSOLUTE on purpose: the wrap
   has a fixed aspect-ratio and a perspective calibrated against the pitch SVG's
   3D transform (see the note below), so adding a block in normal flow would
   shrink the grass and pull the markings off the photo. Floating above it costs
   the geometry nothing.
   Built by Live._penaltyStripHtml from stnScout's kick sequence. */
/* Both this and the goalscorers pill are pinned to top: 6px of the same wrap,
   and .lms-gs carries the higher z-index — so the pill painted straight over the
   "Penalty Shootout" title. Drop this widget below the pill's row, but only when
   the pill is actually there (a 0-0 after extra time renders no goalscorers). */
.lms-pitch-wrap:has(.lms-gs) .lms-pk { top: 34px; }

.lms-pk {
    position: absolute;
    top: 6px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 6;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    pointer-events: none;
}

.lms-pk-title {
    padding: 2px 10px;
    border-radius: 0;
    background: rgba(var(--bg-primary-rgb), 0.82);
    color: var(--accent-green);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: .03em;
    white-space: nowrap;
}

.lms-pk-row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 3px 10px;
    border-radius: 0;
    background: rgba(var(--bg-primary-rgb), 0.82);
}

.lms-pk-side {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

.lms-pk-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 12px;
    height: 12px;
    flex: none;
}

.lms-pk-mark svg { width: 100%; height: 100%; display: block; }
.lms-pk-mark.is-score { color: #fff; }
.lms-pk-mark.is-miss  { color: var(--accent-red, #ed4163); }

/* A kick not yet taken — a dim placeholder, so the row keeps its full width from
   the first penalty and the score never shifts sideways as the set fills in. */
.lms-pk-mark.is-empty::after {
    content: '';
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.32);
}

/* "PenaltyToTake" — a kicker is over the ball. The pulse marks WHOSE kick and
   WHICH slot is coming, which the score alone cannot say. Only ever one slot on
   screen at a time (the empty one nearest the score on the taking side), so this
   is a single looping element, not a row of them. */
.lms-pk-mark.is-next::after {
    background: var(--accent-green);
    animation: lms-pk-next 1s ease-in-out infinite;
}

@keyframes lms-pk-next {
    0%, 100% { transform: scale(1);   opacity: 0.65; }
    50%      { transform: scale(1.9); opacity: 1; }
}

.lms-pk-taker {
    padding: 1px 8px;
    border-radius: 0;
    background: rgba(var(--bg-primary-rgb), 0.82);
    color: var(--text-secondary);
    font-size: 10px;
    font-weight: 700;
    white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
    .lms-pk-mark.is-next::after { animation: none; opacity: 1; transform: scale(1.5); }
}

.lms-pk-score {
    color: var(--gold, #f5c451);
    font-size: 15px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.lms-pk-dash { opacity: .7; margin: 0 1px; }

.lms-pitch-wrap {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 7;
    max-height: 240px;
    min-height: 150px;
    overflow: hidden;
    /* Calibrated with the .lms-pitch-3d transform so the SVG markings land on
     * the photo's pitch (see the geometry note there). 550px is only the
     * first-paint fallback: _positionPitchFurniture re-sets perspective to
     * 2.29 × wrap height (550/240) so the projection is the same FRACTION of
     * the box at every size — a fixed px value drifts off the grass as the
     * wrap grows or shrinks. */
    perspective: 550px;
    perspective-origin: 50% 100%;
    /* STRETCHED (100% 100%), not `cover`: the marking overlay is positioned in
     * % of this box, so the photo must map 1:1 to the box at every viewport
     * width — cover's aspect-dependent crop made the lines drift off the grass
     * as the wrap resized. Slight photo distortion at extreme widths is the
     * acceptable trade. */
    background:
        url('/img/assets/inplay/3d-background-soccer-no-brand.jpg') center / 100% 100% no-repeat,
        var(--bg-green-deep);
}

/* Tilted pitch — anchored into the backdrop's grass band: stands stay visible
 * above (top 24%), the foreground crowd silhhouettes peek out below (bottom 6%),
 * and a thin apron of the image's own grass frames the sides. Rotated back at
 * the top edge for the tv-camera angle, bottom edge closest to the viewer.
 * Tuning knobs: top/bottom/left/right below — they only move the stage; ball,
 * trail and name tags are all % of this box so they track automatically.
 * NOTE: no z-index here. The pitch must paint UNDER the .lms-overlay
 * (minute pill / event text) that follows it in DOM order — adding a
 * z-index once hid the clock behind the tilted plane. */
.lms-pitch-3d {
    position: absolute;
    /* Insets fitted to the MEASURED grass region of the backdrop photo
     * (stretched 100%/100% onto the wrap) so every white line stays on clean
     * grass with an out-of-bounds apron:
     *   - grass top edge sits at v≈0.28 but has large ROUNDED corners — grass
     *     doesn't reach full width until v≈0.33, so the projected far
     *     touchline (lands at v≈0.34, spanning u 0.23..0.77) clears them;
     *   - silhouette heads poke up from v≈0.78..0.90 and the bottom corners
     *     vignette to black, so the near touchline sits at v=0.78 spanning
     *     u 0.13..0.87 (grass there: 0.09..0.88). */
    top: 26%;
    bottom: 22%;
    left: 13%;
    right: 13%;
    transform-origin: 50% 100%;
    /* Perspective calibration — matched to the backdrop photo's own camera.
     * With transform-origin on the BOTTOM edge, the near touchline stays
     * exactly at the inset position (no perspective shift), and the far edge
     * foreshortens by rotateX/scaleY + the wrap perspective (rescaled to
     * 2.29 × wrap height by _positionPitchFurniture). Change any one of
     * these and the insets above need re-fitting against the photo. */
    transform: rotateX(52deg) scaleY(2.2);
    transform-style: preserve-3d;
    /* No box-shadow / darkening haze: the plane is TRANSPARENT now (the SVG
     * draws only white markings — the backdrop photo provides the grass), so
     * any shadow or gradient here would paint a visible floating rectangle
     * over the photo. The photo has its own baked-in lighting/vignette. */
}

.lms-pitch {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
}

/* Event-specific overlays — fan from corner flag for corners, vertical lane
 * band for attacks/dangers/shots. Both fade in fresh on every render so the
 * event reads as a discrete visual beat instead of a static decoration. */
.lms-corner-wedge,
.lms-attack-arrow {
    transform-origin: center;
    transform-box: fill-box;
    animation: lms-event-fade 0.5s ease-out;
}

@keyframes lms-event-fade {
    0%   { opacity: 0; }
    100% { opacity: 1; }
}

/* Set-piece "broadcast signal" — the wifi-style concentric arcs from
 * _signalWaves. Each arc loops the same fade pulse but its animation-delay is
 * staggered inner→outer (set inline in JS), so the wave visibly radiates
 * outward from the ball. The core dot pulses in place. */
.lms-signal-arc {
    animation: lms-signal-wave 1.5s ease-out infinite;
}
.lms-signal-core {
    animation: lms-signal-core 1.5s ease-out infinite;
}

@keyframes lms-signal-wave {
    0%   { opacity: 0; }
    25%  { opacity: 0.95; }
    70%  { opacity: 0.12; }
    100% { opacity: 0; }
}

@keyframes lms-signal-core {
    0%, 100% { opacity: 0.5; }
    30%      { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .lms-signal-arc, .lms-signal-core { animation: none; opacity: 0.85; }
}

/* Ball marker — proper soccer ball SVG sprite at the rez2 position on the
 * tilted pitch. The sprite lives on ::after so the roll rotation
 * (--lms-ball-rot, accumulated by JS per distance moved — bet365's
 * --ml1-ballRotation pattern) composes with the pulse scale on the element
 * itself. left/top transitions make the ball GLIDE between polls — this only
 * works because the patch-in-place render path keeps the node alive. */
.lms-ball {
    position: absolute;
    width: 9px;
    height: 9px;
    margin-left: -7px;
    margin-top: -7px;
    filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.7));
    animation: lms-ball-pulse 1.8s ease-in-out infinite;
    z-index: 2;
    transition: left 0.9s cubic-bezier(0.4, 0, 0.2, 1), top 0.9s cubic-bezier(0.4, 0, 0.2, 1);
}
.lms-ball::after {
    content: '';
    position: absolute;
    inset: 0;
    background: url('/img/soccer-ball.png') center / contain no-repeat;
    transform: rotate(var(--lms-ball-rot, 0deg));
    transition: transform 0.9s linear;
}

@keyframes lms-ball-pulse {
    0%, 100% { transform: scale(1); }
    50%      { transform: scale(1.25); }
}

/* Origin/target discs (bet365 XYBlob pattern) — solid disc at the previous
 * ball position, pulsing ring at the current one. Both re-render with the
 * dynamic SVG; the ring pulse animates transform so it works on SVG. */
.lms-target-ring {
    transform-box: fill-box;
    transform-origin: center;
    animation: lms-ring-pulse 1.4s ease-out infinite;
}
@keyframes lms-ring-pulse {
    0%   { transform: scale(0.6); opacity: 0.9; }
    70%  { transform: scale(1.5); opacity: 0.25; }
    100% { transform: scale(1.7); opacity: 0; }
}

/* STATSCORE-style incident card — replaces the old dark player tag AND the big
 * centered event splash whenever we have a ball position. Rendered UPRIGHT in
 * flat .lms-pitch-wrap space (NOT inside the rotated/scaled .lms-pitch-3d — a
 * label on that plane shears into a foreshortened mess). JS
 * (_positionIncidentCard) anchors it beside the ball's projected position and
 * flips it (--left) when the ball is on the right half so it always opens
 * toward the pitch centre. Starts hidden so it never flashes at 0,0. */
.lms-incident {
    position: absolute;
    visibility: hidden;
    display: flex;
    align-items: stretch;
    pointer-events: none;
    z-index: 4;
    filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.55));
}

.lms-incident-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    background: #fff;
    border-radius: 0;
    flex-shrink: 0;
}
.lms-incident-icon img {
    width: 22px;
    height: 22px;
    object-fit: contain;
}
/* Substitution + VAR: icons drawn for a dark ground (Live._INCIDENT_ICON_DARK).
   A little larger, so the 27:16 VAR badge gets its width. */
.lms-incident-icon--dark {
    background: var(--bg-primary);
}
.lms-incident-icon--dark img {
    width: 26px;
    height: 20px;
}

.lms-incident-text {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 1px;
    background: #fff;
    color: #000;
    padding: 4px 8px;
    min-width: 0;
}
.lms-incident-team {
    font-size: 10px;
    font-weight: 700;
    white-space: nowrap;
    max-width: 170px;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Event label wraps to as many lines as it needs — long labels (e.g. the
 * Albanian "Pushimi i Pjesës së Parë") were being ellipsis-clipped on a
 * single line. Full text stays readable; the card just grows taller. */
.lms-incident-event {
    font-size: 12px;
    font-weight: 600;
    line-height: 1.2;
    max-width: 170px;
    overflow-wrap: break-word;
}
.lms-incident-player {
    font-size: 10px;
    opacity: 0.6;
    white-space: nowrap;
    max-width: 170px;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Team-coloured side indicator (colour set inline via --lms-inc-bar). */
.lms-incident-bar {
    width: 5px;
    background: var(--lms-inc-bar, var(--accent-green));
    border-radius: 0 4px 4px 0;
    flex-shrink: 0;
}

/* Flipped variant — ball on the right half: card opens leftward, so the bar
 * leads on the left and the icon closes the right edge. */
.lms-incident--left { flex-direction: row-reverse; }
.lms-incident--left .lms-incident-icon { border-radius: 0; }
.lms-incident--left .lms-incident-bar  { border-radius: 0; }
.lms-incident--left .lms-incident-text { text-align: right; }

/* Centered variant — the fallback for events WITHOUT a ball position (e.g. a
 * goal once its celebration finishes): the same card, parked mid-pitch by the
 * overlay's flex centering instead of JS ball-anchoring, so every event gets
 * the same white-card background treatment. */
.lms-incident-center {
    position: static;
    visibility: visible;
}

/* Slim overlay variant — while the ball-anchored incident card is on the
 * pitch the overlay carries only the (absolutely positioned) minute pill, so
 * no extra layout rules are needed here. */

/* Invisible measuring anchors inside the tilted plane — their projected
 * screen boxes drive the upright goal/flag placement (visibility:hidden keeps
 * layout so getBoundingClientRect still works). */
.lms-anchor {
    position: absolute;
    width: 1px;
    height: 1px;
    visibility: hidden;
    pointer-events: none;
}

/* Corner flags — a tiny white pole with an orange pennant, bottom-anchored on
 * the projected corner point. */
.lms-flag3d {
    position: absolute;
    visibility: hidden;
    width: 2px;
    height: 11px;
    background: rgba(255, 255, 255, 0.95);
    transform: translate(-50%, -100%);
    pointer-events: none;
    filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.5));
}
.lms-flag3d::after {
    content: '';
    position: absolute;
    left: 2px;
    top: 0;
    border-top: 3px solid transparent;
    border-bottom: 3px solid transparent;
    border-left: 6px solid var(--accent-orange);
}

/* --- Goal celebration -------------------------------------------------------
 * One-shot dramatic overlay fired when a new goal is detected. Sits over the
 * entire pitch wrap, removed by JS after ~3.5s. Composed of:
 *   .lms-goal-flash  — team-colored radial burst
 *   .lms-goal-text   — huge "GOOOAL!" with bounce-in
 *   .lms-goal-team   — uppercase team name below the headline
 *   .lms-confetti    — 40 colored particles falling from the top
 * Each piece uses pointer-events:none so they don't block interactions. */
.lms-goal-celebration {
    position: absolute;
    inset: 0;
    z-index: 100;
    pointer-events: none;
    overflow: hidden;
}

.lms-goal-flash {
    position: absolute;
    inset: 0;
    background:
        radial-gradient(circle at center,
            hsla(var(--goal-hue), 90%, 60%, 0.85) 0%,
            hsla(var(--goal-hue), 90%, 60%, 0.35) 40%,
            transparent 75%);
    animation: lms-goal-flash 5.5s ease-out forwards;
    mix-blend-mode: screen;
}

@keyframes lms-goal-flash {
    0%   { opacity: 0;   transform: scale(0.6); }
    15%  { opacity: 1;   transform: scale(1.05); }
    40%  { opacity: 0.55; transform: scale(1); }
    100% { opacity: 0;   transform: scale(1.1); }
}

.lms-goal-text {
    position: absolute;
    top: 38%;
    left: 50%;
    /* Base size for "GOOOAL!" — short text fits even on narrow viewports.
     * Per-type overrides below shrink it further for longer labels. */
    font-size: clamp(40px, 7.5vw, 80px);
    font-weight: 900;
    color: #ffffff;
    letter-spacing: 3px;
    text-shadow:
        0 0 20px hsl(var(--goal-hue), 90%, 55%),
        0 0 40px hsl(var(--goal-hue), 90%, 45%),
        0 4px 10px rgba(0, 0, 0, 0.85);
    transform: translate(-50%, -50%) scale(0);
    animation: lms-goal-text 5.5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
    white-space: nowrap;
    /* Keep the text inside the pitch wrap even at peak bounce scale. */
    max-width: 90%;
}

@keyframes lms-goal-text {
    /* Peak bounce reduced from 1.4→1.15 and exit zoom from 1.6→1.25 so the
     * text doesn't break out of the pitch wrap on narrower viewports. */
    0%   { transform: translate(-50%, -50%) scale(0)    rotate(-8deg); opacity: 0; }
    18%  { transform: translate(-50%, -50%) scale(1.15) rotate(3deg);  opacity: 1; }
    30%  { transform: translate(-50%, -50%) scale(1)    rotate(0deg);  opacity: 1; }
    78%  { transform: translate(-50%, -50%) scale(1)    rotate(0deg);  opacity: 1; }
    100% { transform: translate(-50%, -50%) scale(1.25) rotate(0deg);  opacity: 0; }
}

.lms-goal-team {
    position: absolute;
    top: 62%;
    left: 50%;
    transform: translate(-50%, -50%) translateY(20px);
    font-size: clamp(16px, 2.4vw, 26px);
    font-weight: 800;
    letter-spacing: 1.5px;
    color: #ffffff;
    text-shadow: 0 2px 6px rgba(0, 0, 0, 0.9);
    opacity: 0;
    animation: lms-goal-team 5.5s ease-out forwards;
    animation-delay: 0.3s;
    white-space: nowrap;
}

@keyframes lms-goal-team {
    0%   { opacity: 0; transform: translate(-50%, -50%) translateY(20px); }
    20%  { opacity: 1; transform: translate(-50%, -50%) translateY(0); }
    80%  { opacity: 1; transform: translate(-50%, -50%) translateY(0); }
    100% { opacity: 0; transform: translate(-50%, -50%) translateY(-10px); }
}

/* Player involved in the celebrated event (scorer / shooter / booked player),
 * parsed from stnScout's "/player" segment. Sits just under the team name with
 * the same staggered fade so it reads as part of the same beat. Slightly
 * smaller + lighter so the team name stays the headline. */
.lms-goal-player {
    position: absolute;
    top: 74%;
    left: 50%;
    transform: translate(-50%, -50%) translateY(20px);
    font-size: clamp(13px, 1.8vw, 19px);
    font-weight: 700;
    letter-spacing: 0.6px;
    color: rgba(255, 255, 255, 0.92);
    text-shadow: 0 2px 6px rgba(0, 0, 0, 0.9);
    opacity: 0;
    animation: lms-goal-player 5.5s ease-out forwards;
    animation-delay: 0.45s;
    white-space: nowrap;
}

@keyframes lms-goal-player {
    0%   { opacity: 0; transform: translate(-50%, -50%) translateY(20px); }
    24%  { opacity: 1; transform: translate(-50%, -50%) translateY(0); }
    80%  { opacity: 1; transform: translate(-50%, -50%) translateY(0); }
    100% { opacity: 0; transform: translate(-50%, -50%) translateY(-10px); }
}

.lms-confetti {
    position: absolute;
    top: -24px;
    border-radius: 0;
    animation-name: lms-confetti-fall;
    animation-timing-function: ease-in;
    animation-fill-mode: forwards;
}

@keyframes lms-confetti-fall {
    0%   { transform: translateY(0)     rotate(0deg);          opacity: 1; }
    100% { transform: translateY(120vh) rotate(var(--rot, 720deg)); opacity: 0; }
}

/* Per-type celebration overrides — smaller text + per-event color for
 * corner / yellow card / red card / shot / var so they read differently
 * from a goal and so long labels never break out of the pitch wrap. */
.lms-cel-corner .lms-goal-text,
.lms-cel-penalty .lms-goal-text {
    font-size: clamp(32px, 6vw, 56px);
    letter-spacing: 4px;
}
.lms-cel-yc .lms-goal-text,
.lms-cel-rc .lms-goal-text {
    font-size: clamp(28px, 5vw, 48px);
    letter-spacing: 3px;
}
/* Long labels — "SHOT OFF TARGET" / "VAR — GOAL CHECK" — need smaller font
 * so the bounce-in scale doesn't push them past the pitch edges. */
.lms-cel-shoton  .lms-goal-text,
.lms-cel-shotoff .lms-goal-text {
    font-size: clamp(22px, 4.2vw, 38px);
    letter-spacing: 2px;
}
.lms-cel-var .lms-goal-text {
    font-size: clamp(22px, 4.2vw, 40px);
    letter-spacing: 2px;
}
/* Card-color the text so it reads at a glance */
.lms-cel-yc .lms-goal-text { color: #ffd000; text-shadow: 0 0 16px #ffd000, 0 2px 6px rgba(0,0,0,0.85); }
.lms-cel-rc .lms-goal-text { color: #ff5466; text-shadow: 0 0 16px #ff3344, 0 2px 6px rgba(0,0,0,0.85); }

/* Card icon — small rectangle sitting just above the text for yellow/red.
 * Uses the same bounce-in timing so it lands together with the headline. */
.lms-cel-card {
    position: absolute;
    top: 26%;
    left: 50%;
    width: clamp(28px, 4vw, 42px);
    height: clamp(40px, 5.6vw, 60px);
    border-radius: 0;
    transform: translate(-50%, -50%) scale(0) rotate(-12deg);
    animation: lms-goal-text 5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.8);
}
.lms-cel-card-y { background: linear-gradient(180deg, #ffe04a 0%, #f0c000 100%); }
.lms-cel-card-r { background: linear-gradient(180deg, #ff5466 0%, #c4232f 100%); }

/* Image-based icons for shot-on / shot-off / VAR celebrations. Uses the
 * same bounce-in keyframes as the card so all icon types land in sync
 * with the headline text. Bigger than the card sprites to give the
 * detailed PNGs / SVG room to read. */
.lms-cel-img {
    position: absolute;
    top: 26%;
    left: 50%;
    width: clamp(72px, 11vw, 120px);
    height: auto;
    transform: translate(-50%, -50%) scale(0) rotate(-8deg);
    animation: lms-goal-text 5s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
    filter: drop-shadow(0 4px 12px rgba(0, 0, 0, 0.75));
    pointer-events: none;
}

/* The VAR badge (27:16) sizes off the pitch's HEIGHT, not the viewport's
 * width, and sits higher: the wrap is 150-240px tall (16:7, capped), and the
 * badge has to clear the headline under it at every size. Sized by width it
 * sat on "VAR REVIEW" — on a narrow phone it covered it completely. */
.lms-cel-img-var {
    top: 17%;
    width: auto;
    height: 21%;
}

/* Shot-on / shot-off / VAR headline colours so the text reads at a
 * glance even before the user parses the icon. */
.lms-cel-shoton  .lms-goal-text { color: #ffffff; }
.lms-cel-shotoff .lms-goal-text { color: #c9d3ce; text-shadow: 0 0 14px #6b7773, 0 2px 6px rgba(0,0,0,0.85); }
.lms-cel-var     .lms-goal-text { color: #ffffff; text-shadow: 0 0 16px #a347ff, 0 2px 6px rgba(0,0,0,0.85); }

/* Original centered overlay — minute pill + team name + event label. Sits
 * over the pitch, small enough to leave the ball + markings readable (sizes
 * deliberately compact so the stadium-photo pitch stays visible behind it). */
.lms-overlay {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    text-align: center;
    pointer-events: none;
    color: #ffffff;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.55);
}

/* Minute pill — pinned top-centre, up in the photo's crowd band (grass starts
 * at ≈28% of the wrap height) so it never covers the field. Absolute, so it
 * escapes the overlay's flex centering in BOTH the slim and full variants. */
.lms-minute-pill {
    position: absolute;
    top: 4.5%;
    left: 50%;
    transform: translateX(-50%);
    background: rgba(0, 0, 0, 0.55);
    color: #ffffff;
    padding: 2px 9px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.3px;
    text-shadow: none;
    white-space: nowrap;
}

.lms-period {
    opacity: 0.75;
    margin-right: 4px;
}

/* Player involved in the current event — parsed from the "/player" segment of
 * stnScout. Only the throw-in overlay still uses it (other events carry the
 * player inside the incident card). */
.lms-event-player {
    margin-top: 2px;
    font-size: 11px;
    font-weight: 700;
    color: #fff;
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}

/* Throw-in — chunky yellow-box treatment that matches the screenshot. The team
 * name sits in a solid yellow bar, the event + minute on a darker translucent strip
 * directly below. */
.lms-overlay-throw {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0;
    pointer-events: none;
}

.lms-throw-team {
    background: #ffd000;
    color: #1a1a1a;
    padding: 4px 18px;
    font-size: 13px;
    font-weight: 800;
    letter-spacing: 0.4px;
    border-radius: 0;
}

.lms-throw-row {
    display: flex;
    align-items: center;
    gap: 12px;
    background: rgba(0, 0, 0, 0.55);
    color: #ffffff;
    padding: 4px 16px;
    border-radius: 0;
    font-size: 12px;
}

.lms-throw-min {
    font-weight: 700;
    opacity: 0.85;
    font-variant-numeric: tabular-nums;
}

/* Sticky stripe — sibling of #live-md-scout under #page-live-match. Pins
 * below the Bast 60px fixed top-header while the user scrolls through the
 * markets, so the current event stays in view. Bar on team's outer side. */
.lms-stripe {
    position: sticky;
    top: var(--header-height);
    height: 50px;
    z-index: 90;
    border-radius: 0 0 var(--radius-md) var(--radius-md);
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0px 16px;
    margin: -10px 0 8px;
    /* The alpha was missing here (`rgba(0,0,0)`), which computes to OPAQUE pure black —
       a colour used nowhere else in the app, and it defeated the blur below (you cannot
       blur through an opaque fill). Restored as the translucent scrim it was meant to be. */
    background: rgb(0, 0, 0);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    color: #fff;
    box-shadow: #0003 0 4px 6px -1px, #0000001f 0 2px 4px -1px;
}

.lms-stripe-left  { justify-content: flex-start; }
.lms-stripe-right { justify-content: flex-end; }

/* Standalone status stripe (sports with no pitch, e.g. cricket): no pitch card
 * above to tuck under, so cancel the negative top-margin and round the top. */
.lms-stripe--status {
    margin-top: 8px;
    border-radius: var(--radius-md);
}

/* Placeholder shown when the feed has no scout message. Same box, so nothing
   below it moves, but quiet enough to read as "nothing happening" rather than
   as an incident. */
.lms-stripe--idle .lms-stripe-event {
    font-weight: 500;
    font-size: 13px;
    color: var(--text-muted);
    letter-spacing: 0.2px;
}
.lms-stripe--idle .lms-stripe-bar { opacity: 0.45; }

.lms-stripe-text {
    display: flex;
    flex-direction: column;
    line-height: 1.1;
    gap: 2px;
}

.lms-stripe-left  .lms-stripe-text { text-align: left;  align-items: flex-start; }
.lms-stripe-right .lms-stripe-text { text-align: right; align-items: flex-end; }

.lms-stripe-team {
    font-size: 13px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.85);
}

.lms-stripe-event {
    font-size: 18px;
    font-weight: 800;
    color: #ffffff;
}

/* Player on the ball / involved in the event — parsed from the "/player"
 * segment of stnScout. Sits under the event headline on the stripe. */
.lms-stripe-player {
    font-size: 12px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.7);
    margin-top: 1px;
}

.lms-stripe-bar {
    width: 3px;
    align-self: stretch;
    min-height: 28px;
    border-radius: 2px;
    background: var(--lms-stripe-bar, #56d18d);
    box-shadow: 0 0 4px rgba(0, 0, 0, 0.4);
}

/* Bar on team's OUTER side: LEFT anchor → bar first; RIGHT → bar last */
.lms-stripe-right .lms-stripe-bar { order: 99; }

.lmst-show-all {
    display: block;
    margin: 0 auto 14px;
    background: none;
    border: none;
    color: var(--text-secondary);
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    padding: 6px 12px;
    border-radius: var(--radius-sm);
    text-decoration: underline;
    text-decoration-color: var(--accent-green);
    text-underline-offset: 4px;
}

.lmst-show-all:hover {
    color: var(--text-primary);
}

/* --- Permbledhje totals strip --- */
.lmst-totals {
    background: var(--bg-tertiary);
    border-radius: var(--radius-md);
    padding: 10px 12px;
    margin-bottom: 14px;
}

.lmst-totals-row {
    display: grid;
    grid-template-columns: 60px repeat(4, 1fr);
    gap: 8px;
    align-items: center;
    padding: 4px 0;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    text-align: center;
    color: var(--text-primary);
}

.lmst-totals-row.lmst-totals-head {
    font-weight: 500;
    color: var(--text-muted);
}

.lmst-totals-kit {
    display: flex;
    justify-content: center;
}

/* --- Permbledhje timeline --- */
.lmst-half {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-top: 6px;
}

.lmst-half-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 16px 0 8px;
}

.lmst-half-line {
    flex: 1;
    height: 1px;
    background: var(--border-color);
}

.lmst-half-title {
    font-weight: 700;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.lmst-tl-row {
    display: grid;
    grid-template-columns: 1fr auto 6px auto 1fr;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
}

.lmst-tl-cell {
    display: flex;
    align-items: center;
    gap: 6px;
    color: var(--text-secondary);
    font-size: 13px;
}

.lmst-tl-row-h .lmst-tl-label { justify-content: flex-end; }
.lmst-tl-row-a .lmst-tl-label { justify-content: flex-start; }

.lmst-tl-min {
    color: var(--text-primary);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.lmst-tl-row-h .lmst-tl-min { justify-content: flex-end; }
.lmst-tl-row-a .lmst-tl-min { justify-content: flex-start; }

.lmst-tl-center {
    width: 2px;
    height: 22px;
    background: var(--gold);
    border-radius: 1px;
}

/* Mini card icons used inside the timeline row */
.lmst-tl-card {
    display: inline-block;
    width: 10px;
    height: 14px;
    border-radius: 0;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
}

.lmst-tl-card-y { background: var(--gold); }
.lmst-tl-card-r { background: var(--accent-red); }

/* Center / milestone row (mt=12 race-to-N — no team side, neutral chip) */
.lmst-tl-row-c {
    display: flex;
    justify-content: center;
    padding: 4px 0;
}

.lmst-tl-cell-c {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 4px 10px;
    background: rgba(255, 255, 255, 0.03);
    border: 1px dashed rgba(0, 231, 1, 0.25);
    border-radius: var(--radius-sm);
    color: var(--text-secondary);
    font-size: 12px;
    font-weight: 600;
}

.lmst-tl-cell-c .lmst-tl-min {
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

@media (max-width: 600px) {
    .lmst-gauges {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 6px;
    }
    .lmst-gauge {
        gap: 4px;
    }
    .lmst-gauge-val {
        font-size: 14px;
        min-width: 18px;
    }
    .lmst-gauge-label {
        font-size: 11px;
    }
    .lmst-gauge-svg {
        width: 48px;
        height: 48px;
    }

    /* Keep the original horizontal 3-column layout — just shrink everything */
    .lmst-shots-row {
        grid-template-columns: auto 1fr auto;
        gap: 8px;
        padding-top: 14px;
        align-items: center;
    }
    .lmst-flank {
        gap: 2px;
    }
    .lmst-flank-icons,
    .lmst-flank-vals {
        gap: 4px;
        font-size: 12px;
    }
    .lmst-flank-vals {
        font-size: 13px;
    }
    .lmst-shots-val {
        font-size: 11px;
        min-width: 22px;
    }
    .lmst-shots-label {
        font-size: 11px;
    }
    .lmst-shots-bars {
        gap: 4px;
    }

    .lmst-totals-row {
        grid-template-columns: 44px repeat(4, 1fr);
        font-size: 13px;
    }
}

/* ============================================================================
 * LIVE-MATCH TIMELINE STATISTICS MODAL (used by My Bets → ticket detail)
 * Ported from the legacy WebForms `MatchStatistics.aspx` page.
 * Class names (`*_timeline` suffix) match the server-rendered HTML so we can
 * inject the SP-built string verbatim.
 * ========================================================================== */

/* Backdrop — dims the page and centres the modal */
.stat_timeline_overlay {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.55);
    display: none;
    align-items: center;
    justify-content: center;
    z-index: 9999;
}

.stat_timeline {
    position: relative;
    max-width: 480px;
    width: calc(100vw - 20px);
    min-height: 150px;
    max-height: calc(100dvh - 40px);
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    border-radius: 0;
    background-color: #f0f0f0;
    font-size: 15px;
    z-index: 10000;
    overflow: hidden;
}

/* Installed app on a phone: iOS 26/27 blurs a band about 50pt deep just below the status
   bar, and a long timeline grows this popup to 20px from the top, so its header (match
   and ×) sat in that band, blurred. Start the popup below it. env(safe-area-inset-top)
   can't do this: it is 0 with the "black" status bar style. */
@media (display-mode: standalone) and (max-width: 600px) {
    .stat_timeline_overlay { padding-top: 52px; box-sizing: border-box; }
    .stat_timeline { max-height: calc(100dvh - 92px); }
}

.stat_timeline_loading {
    padding: 40px 20px;
    text-align: center;
    color: var(--gray-mid);
    font-size: 14px;
}

.stat-no-info_timeline {
    padding: 30px 20px;
    text-align: center;
    color: var(--gray-mid);
    font-size: 14px;
}

/* Results card — shown instead of "No info" when there is no timeline (prematch legs,
   expired live feeds): the scores stored on the match row. */
.stat-res-when {
    padding: 10px 16px 0;
    color: var(--gray-mid);
    font-size: 13px;
    text-align: center;
}
.stat-res {
    width: calc(100% - 32px);
    margin: 12px 16px 20px;
    border-collapse: collapse;
    color: var(--gray-mid);
    font-size: 14px;
}
.stat-res th,
.stat-res td {
    padding: 9px 8px;
    border-bottom: 1px solid color-mix(in srgb, var(--gray-mid) 20%, transparent);
}
.stat-res thead th {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    text-align: center;
}
.stat-res tbody th { font-weight: 600; text-align: left; }
.stat-res td { font-weight: 700; text-align: center; font-variant-numeric: tabular-nums; }
.stat-res tbody tr:last-child th,
.stat-res tbody tr:last-child td { border-bottom: 0; }
.stat-res-live {
    margin-left: 8px;
    padding: 1px 6px;
    border-radius: var(--radius-sm);
    background: color-mix(in srgb, var(--accent-red) 15%, transparent);
    color: var(--accent-red-ink);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
}

/* Volleyball, table tennis, ice hockey in the same popup (mybets.js _liveSportModal): the live
   page's panels (js/livesports.js) on their own dark ground under the popup's light header, the
   tabs held at the top while the panel scrolls. */
.stat-mtl-scroll.mb-lvs { background: var(--bg-primary); }
.mb-lvs .stat-res-when { padding-bottom: 10px; color: var(--text-muted); }
.mb-lvs-tabs { position: sticky; top: 0; z-index: 1; }
.mb-lvs-panel { padding: 16px 12px 8px; color: var(--text-primary); }
.mb-lvs-panel[hidden] { display: none; }

.ml-StatButtons_Modal_timeline,
.ml-StatButtons_PopupContainer_timeline {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    align-items: stretch;
    width: 100%;
    margin: 0 auto;
    background: #f0f0f0;
}

.ml-StatButtons_Modal_timeline { max-width: 500px; }

.ml-StatPopupBase_Header_timeline {
    display: flex;
    align-items: center;
    min-height: 55px;
    border-bottom: 1px solid #ddd;
    justify-content: space-between;
}
.ml-StatPopupBase_Title_timeline {
    flex: 1 1 auto;
    color: var(--gray-mid);
    font-size: 15px;
    line-height: 18px;
    font-weight: 700;
    padding: 0 10px;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    word-break: break-word;
    display: -webkit-box;
    -webkit-box-orient: vertical;
}
.ml-StatPopupBase_Close_timeline {
    flex: 0 0 auto;
    width: 45px;
    align-self: stretch;
    background-image: url('/img/icons/close.svg');
    background-repeat: no-repeat;
    background-position: center;
    background-size: 12px;
    cursor: pointer;
}
/* Fallback if /img/icons/close.svg doesn't exist — render an × glyph */
.ml-StatPopupBase_Close_timeline::after {
    content: "×";
    display: block;
    text-align: center;
    line-height: 55px;
    color: var(--gray-mid);
    font-size: 24px;
}
.ml-StatPopupBase_Close_timeline { background-image: none; }

/* Totals board (corners / yellow / red / goals) */
.ml1-StatBoard_timeline,
.ml1-StatBoard_RowHeader_timeline {
    display: flex;
    color: #404040;
}
.ml1-StatBoard_timeline {
    flex: 0 0 auto;
    padding-top: 23px;
    margin: 0 auto;
    max-width: 450px;
    width: 100%;
}
.ml1-StatBoard_ht_timeline {
    display: flex;
    flex: 0 0 auto;
    padding-top: 0;
    margin: 0 auto;
    max-width: 450px;
    width: 100%;
}
.ml1-StatBoard_RowHeader_timeline {
    flex: 1 1 10%;
    align-items: center;
    justify-content: flex-end;
    flex-direction: column;
    font-size: 13px;
}
.ml1-StatBoard_HeadEmpty_timeline { height: 13px; width: 100%; margin-bottom: 6px; }
.ml1-StatBoard_Team_timeline {
    font-weight: 700;
    min-height: 25px;
    display: flex;
    align-items: center;
}
.ml1-StatBoardColumn_timeline {
    display: flex;
    flex: 1 1 10%;
    align-items: center;
    justify-content: flex-end;
    flex-direction: column;
    font-size: 13px;
    line-height: 1;
    color: #404040;
}
.ml1-StatBoardColumn_Icon_timeline {
    height: 13px;
    margin-bottom: 6px;
    width: 100%;
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
.ml1-StatBoardColumn_Data_timeline {
    min-height: 25px;
    display: flex;
    align-items: center;
}

.ml-StatButtons_Modal_ht_timeline {
    background: #dddddd;
    padding: 15px;
    position: relative;
    top: 10px;
    margin: 0 auto;
    width: 85%;
    border-radius: 0;
}

/* Icons (corners, yellow, red, goal) */
.ml1-StatBoardColumn_Icon-1_timeline,
.ml1-TimelineEvent_Team1_timeline.ml1-TimelineEvent_Icon2_timeline,
.ml1-TimelineEvent_Team2_timeline.ml1-TimelineEvent_Icon2_timeline,
.ml-SummaryRow_Icon-2_timeline {
    background-image: url('/img/icons/fotostatistike/soccerball-removebg-preview.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
.ml1-StatBoardColumn_Icon-2_timeline,
.ml-SummaryRow_Icon-1_timeline,
.ml-SummaryRow_Icon-7_timeline,
.ml-SummaryRow_Icon-27_timeline {
    background-image: url('/img/icons/fotostatistike/chjpdmf0zs9sci9pbwfnzxmvd2vic2l0zs8ymdiylta5l3jtntgxlwvszw1lbnqtmdkzxzeucg5n-removebg-preview.svg');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
.ml1-StatBoardColumn_Icon-3_timeline,
.ml-SummaryRow_Icon-4_timeline,
.ml-SummaryRow_Icon-24_timeline {
    background-image: url('/img/icons/fotostatistike/kartoni verdhe.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
.ml1-StatBoardColumn_Icon-4_timeline,
.ml-SummaryRow_Icon-5_timeline,
.ml-SummaryRow_Icon-25_timeline {
    background-image: url('/img/icons/fotostatistike/kartoni_kuq-removebg-preview.png');
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}

/* Progress bar */
.ml-Timeline_timeline {
    height: 25px;
    display: flex;
    align-items: center;
    margin: 12px 10px 25px;
    position: relative;
    z-index: 10;
}
.ml-Timeline_Bar_timeline {
    width: 100%;
    height: 8px;
    background-color: #757575;
    border-radius: 0;
    position: relative;
}
.ml-Timeline_BarFill_timeline {
    display: block;
    width: 0;
    height: 8px;
    position: absolute;
    top: 0;
    left: 0;
    border-radius: 0;
}
.ml1-SoccerTimeline_BarFill_timeline { background-color: var(--green-soft); }
.ml-Timeline_Time_timeline {
    background-color: #474747;
    font-size: 12px;
    font-weight: 700;
    color: #f0f0f0;
    width: 46px;
    height: 25px;
    line-height: 25px;
    border-radius: 0;
    text-align: center;
    position: absolute;
    top: 50%;
    left: 50%;
    margin: -12.5px 0 0 -23px;
}

/* Event list (scrollable) */
.ml-Summary-expandable_timeline {
    max-height: calc(100dvh - 320px);
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: none;
    scrollbar-width: thin;
    scrollbar-color: hsla(0, 0%, 65%, .5) #f0f0f0;
}

.ml-SummaryRow-eventrow_timeline {
    display: flex;
    flex: 0 0 100%;
    min-height: 30px;
    font-size: 12px;
    align-items: stretch;
    position: relative;
    margin-bottom: 1px;
    padding: 0 10px;
}
.ml1-SoccerSummaryRow_timeline.ml-SummaryRow-eventrow_timeline { padding: 0 20px; }
.ml-Summary-expandable_timeline .ml-SummaryRow-eventrow_timeline:last-child,
.ml-Summary-expandable_timeline .ml-SummaryRow-eventrow_timeline:nth-last-child(2) {
    margin-bottom: 15px;
}

.ml-SummaryRow_Empty_timeline,
.ml-SummaryRow_TextIcon_timeline {
    display: flex;
    flex: 0 1 50%;
    align-items: center;
    /* The event text and its wall-clock time are sibling spans: without a gap the
       home side read "10th Corner01:51:33". */
    gap: 6px;
}
.ml-SummaryRow_TextIcon-1_timeline { justify-content: flex-end; border-right: 2px solid currentColor; }
.ml-SummaryRow_TextIcon-2_timeline { border-left: 2px solid currentColor; }
.ml-SummaryRow_Icon_timeline {
    display: inline-flex;
    flex: 0 0 30px;
    height: 15px;
    background-position: 50%;
    background-repeat: no-repeat;
}
.ml-SummaryRow_Time_timeline {
    color: var(--gray-mid);
    display: flex;
    width: 40px;
    flex: 0 0 auto;
    justify-content: center;
    align-items: center;
    font-weight: 700;
}
.ml-SummaryRow_Text_timeline { color: var(--gray-mid); }
.ml-SummaryRow_Text_timeline.ml-SummaryRow_Text-1_timeline { text-align: right; }

.ml1-SoccerSummaryRow_GoalText_timeline { padding: 8px 0; line-height: 16px; font-size: 12px; }
.ml1-SoccerSummaryRow_GoalLabel_timeline { font-size: 12px; font-weight: 700; color: black; }

/* Score markers */
.score-first-half_timeline,
.score-full-time_timeline {
    font-size: 12px;
    font-weight: 600;
    display: flex;
    flex: 0 0 100%;
    min-height: 30px;
    align-items: center;
    position: relative;
    margin-bottom: 1px;
    padding: 0 10px;
    justify-content: center;
}
.score-first-half_timeline { margin-top: 15px; height: 5px; }

/* Make the match name in the My Bets ticket-detail selection rows look tappable */
.mybets-sel-match-clickable {
    cursor: pointer;
    text-decoration: underline;
    text-decoration-color: rgba(80, 80, 80, 0.35);
    text-underline-offset: 2px;
}
.mybets-sel-match-clickable:hover .mybets-sel-match-name {
    color: var(--accent-teal-light);
}

/* ============================================================================
 * MY BETS — toast
 * ========================================================================== */
/* Tiny toast for action feedback (success/error). Top-center, fades in/out. */
.mybets-toast {
    position: fixed;
    top: 24px;
    left: 50%;
    transform: translate(-50%, -20px);
    background: rgba(40, 40, 40, 0.95);
    color: #fff;
    padding: 10px 18px;
    border-radius: 0;
    font-size: 13px;
    z-index: 11000;
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s ease, transform .25s ease;
    max-width: calc(100vw - 32px);
}
.mybets-toast.mybets-toast-show {
    opacity: 1;
    transform: translate(-50%, 0);
}

/* ============================================================================
 * BETSLIP — locked odd (koefi == 1.0). Visually distinct from `.bs-sel-invalid`
 * (which means the SP didn't return the odd at all) — locked means the market
 * is suspended but the SP still echoed back the leg data.
 * ========================================================================== */
.bs-selection.bs-sel-locked {
    border: 1px solid rgba(255, 153, 0, 0.55);
    background-color: rgba(255, 153, 0, 0.08);
    position: relative;
}
.bs-selection.bs-sel-locked .bs-sel-koefi {
    color: #b56700;
    text-decoration: line-through;
    text-decoration-thickness: 1.5px;
    opacity: 0.85;
}
.bs-selection.bs-sel-locked .bs-sel-match,
.bs-selection.bs-sel-locked .bs-sel-market,
.bs-selection.bs-sel-locked .bs-sel-value {
    opacity: 0.7;
}
.bs-sel-lock-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    margin-left: 6px;
    border-radius: 50%;
    background: #ff9900;
    color: #fff;
    flex: 0 0 auto;
}

/* ============================================================================
 * BETSLIP — locked state (during place-bet → operator confirmation → 4s accepted window)
 * No ✕ button presses, no stake edits, no clear-all. Selections greyed out.
 * ========================================================================== */
.bs-content.bs-locked .bs-selection {
    opacity: 0.55;
    filter: grayscale(0.4);
    pointer-events: none;          /* defence-in-depth on top of the JS click guard */
    -webkit-user-select: none;
    user-select: none;
}
.bs-content.bs-locked .bs-sel-remove {
    pointer-events: none;
    opacity: 0;                    /* hide the × — visually communicates "locked" */
}
.bs-content.bs-locked .bs-clear-all {
    pointer-events: none;
    opacity: 0.4;
}
.bs-content.bs-locked .bs-stake-input {
    pointer-events: none;
    background: rgba(255, 255, 255, 0.04);
    color: rgba(255, 255, 255, 0.55);
}
.bs-content.bs-locked .bs-remember-toggle {
    pointer-events: none;
    opacity: 0.55;
}

/* Status 103 result message — same shape as success/error but neutral amber */
.bs-result-pending {
    background: rgba(255, 153, 0, 0.10);
    border: 1px solid rgba(255, 153, 0, 0.45);
    color: #ffb547;
}

/* ============================================================================
 * LIVE TOOLBAR — Search + Sort buttons live alongside the view-toggle on the right
 * side of the live-top-bar. Slide-down search input and floating sort menu below.
 * ========================================================================== */
/* Search + Sort share the .live-view-btn base styles; the 2×2 grid is set on the parent. */

/* ============================================================
   LATEST-GOALS TICKER (live overview, football)
   Horizontally scrolling cards for the most recent goals. Click a card to
   open that match. Collapse chevron on the left persists in localStorage.
   ============================================================ */
/* Registered so the edge-fade widths can TRANSITION (unregistered custom
 * properties jump instead of animating). Unsupported browsers simply snap —
 * the mask itself still works. */
@property --gf-l {
    syntax: '<length>';
    inherits: false;
    initial-value: 0px;
}
@property --gf-r {
    syntax: '<length>';
    inherits: false;
    initial-value: 0px;
}

.live-goals-strip {
    display: flex;
    flex-direction: column;
    background: var(--bg-secondary);
    /* border-bottom: 1px solid var(--border-color); */
    margin-bottom: 8px;
    border-radius: 0 0  var(--radius-md) var(--radius-md);
    /* Pinned under the fixed header so a goal stays visible no matter how far
     * down the match list the user has scrolled — same pattern as .content-tabs.
     * z-index 45 clears the match rows but stays under the stats popover (200),
     * the sort menu (9000) and the header (100). The background must stay
     * OPAQUE or rows would show through while it's pinned. */
    position: sticky;
    top: var(--header-height);
    z-index: 45;
    box-shadow: 0 6px 14px -8px rgba(0, 0, 0, 0.55);
}
.live-goals-strip[hidden] { display: none !important; }

/* Header bar — the whole row is the disclosure control, so the COLLAPSED state
 * is a deliberate summary bar (pulse + label + count) rather than a lone icon
 * floating in an empty band. A thin gradient rule under it ties the strip to
 * the scoreboard-yellow accent used by the goal chips. */
.live-goals-head {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    min-height: 40px;              /* comfortable touch target */
    padding: 8px 12px;
    background: transparent;
    border: none;
    color: var(--text-secondary);
    font: inherit;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    text-align: left;
    cursor: pointer;
    transition: color 0.18s ease, background 0.18s ease;
}
.live-goals-head:hover { 
    color: var(--text-primary); 
    /* background: rgba(255, 255, 255, 0.03); */
 }

/* Live pulse — same language as the LIVE badge, tinted scoreboard-yellow. */
.live-goals-head-dot {
    flex-shrink: 0;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #ffd000;
    box-shadow: 0 0 0 0 rgba(255, 208, 0, 0.55);
    animation: live-goals-dot 1.8s ease-out infinite;
}

@keyframes live-goals-dot {
    0%   { box-shadow: 0 0 0 0 rgba(255, 208, 0, 0.5); }
    70%  { box-shadow: 0 0 0 7px rgba(255, 208, 0, 0); }
    100% { box-shadow: 0 0 0 0 rgba(255, 208, 0, 0); }
}

.live-goals-head-title { flex: 1; min-width: 0; }

/* Count pill — the piece of information the collapsed state still conveys. */
.live-goals-count {
    flex-shrink: 0;
    min-width: 18px;
    padding: 1px 6px;
    border-radius: 999px;
    background: rgba(255, 208, 0, 0.14);
    color: #ffd000;
    font-size: 10px;
    font-weight: 800;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.live-goals-chev {
    flex-shrink: 0;
    transition: transform 0.22s ease;
}
/* Collapsed: chevron points right, rail hidden — the header alone remains. */
.live-goals-strip.collapsed .live-goals-chev { transform: rotate(-90deg); }
/* The whole RAIL, not just the scroller. Hiding only .live-goals-scroll left the
   rail and its two arrows in flow, and the arrows are revealed by
   `.live-goals-rail:has(.live-goals-scroll.fade-*)` — a class the scroller keeps
   while collapsed, since _updateGoalFade only re-runs on OPEN (and could not
   clear it anyway: a display:none element measures 0, so there is no scroll
   position to read). The result was a next-arrow floating over a collapsed
   header with nothing behind it to scroll. */
.live-goals-strip.collapsed .live-goals-rail { display: none; }

/* Wraps the scroller so the arrows can overlay its edges. */
.live-goals-rail {
    position: relative;
    min-width: 0;
}

.live-goals-arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(var(--bg-primary-rgb), 0.82);
    border: 1px solid var(--border-color, var(--border-color));
    color: var(--text-secondary);
    cursor: pointer;
    /* Hidden by default and revealed only when there IS something that way —
       driven off the SAME .fade-left / .fade-right classes Live._updateGoalFade
       already sets from the scroll position, so an arrow can never point at
       nothing and no new scroll listener is needed. */
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.15s;
}

.live-goals-arrow-prev { left: 4px; }
.live-goals-arrow-next { right: 4px; }

.live-goals-rail:has(.live-goals-scroll.fade-left) .live-goals-arrow-prev,
.live-goals-rail:has(.live-goals-scroll.fade-right) .live-goals-arrow-next {
    opacity: 1;
    pointer-events: auto;
}

.live-goals-arrow:hover {
    color: #fff;
    border-color: var(--accent-green);
}

/* Touch scrolls the rail directly; a floating arrow would just cover a card. */
@media (pointer: coarse) {
    .live-goals-arrow { display: none; }
}

.live-goals-scroll {
    display: flex;
    gap: 8px;
    min-width: 0;
    padding: 0 12px 8px;
    overflow-x: auto;
    scrollbar-width: none;
    /* Cards dissolve into whichever edge still has content off-screen, instead
       of being hard-cropped. Mask (not an overlay gradient) so it works over any
       page background. The .fade-left / .fade-right classes are toggled by
       Live._updateGoalFade from the scroll position — CSS alone can't know it.
       --gf-l / --gf-r are the fade widths, 0 when that side is at its end. */
    --gf-l: 0px;
    --gf-r: 0px;
    -webkit-mask-image: linear-gradient(to right,
        transparent 0, #000 var(--gf-l),
        #000 calc(100% - var(--gf-r)), transparent 100%);
    mask-image: linear-gradient(to right,
        transparent 0, #000 var(--gf-l),
        #000 calc(100% - var(--gf-r)), transparent 100%);
    transition: --gf-l 0.2s linear, --gf-r 0.2s linear;
    /* `pan-x pan-y` — bare `pan-x` would swallow vertical swipes starting on
       this rail and stop the page scrolling (see the mobile-drift rules). */
    touch-action: pan-x pan-y;
    -webkit-overflow-scrolling: touch;
}
.live-goals-scroll::-webkit-scrollbar { display: none; }
.live-goals-scroll.fade-left  { --gf-l: 40px; }
.live-goals-scroll.fade-right { --gf-r: 56px; }

/* ── Ticker instance #2: inside the football match-detail header ───────────
   The base .live-goals-strip is a PINNED bar for the match list — sticky at the
   header height, raised on z-index 45, with a drop shadow to lift it off the
   rows sliding under it. None of that survives the move into a header band:
   pinned, it would ride over the video player as soon as the page scrolled,
   which is the exact bug `position: static` fixes for the scout stripe on
   desktop. Unpinned, de-elevated and flattened into the band here.
   Everything else — cards, fades, arrows, collapse — is inherited unchanged. */
.live-goals-strip-md {
    position: static;
    z-index: auto;
    box-shadow: none;
    background: rgba(255, 255, 255, 0.035);
    border: 1px solid var(--border-color);
    margin: 0px 0 5px;
    border-radius: var(--radius-dec, 8px);
}

/* A size down from the list version: this is a secondary control inside a band
   that already carries the kits, the names and the score, and it must not
   compete with them. */
.live-goals-strip-md .live-goals-head {
    min-height: 34px;
    padding: 7px 10px;
    gap: 7px;
    font-size: 10px;
}
.live-goals-strip-md .live-goals-head-dot { width: 6px; height: 6px; }
.live-goals-strip-md .live-goals-scroll { padding: 0 10px 10px; }

/* The rail is inset from the band edge, so the arrows sit tighter than the
   list version's 4px or they overhang the strip's own border. */
.live-goals-strip-md .live-goals-arrow-prev { left: 2px; }
.live-goals-strip-md .live-goals-arrow-next { right: 2px; }

@media (prefers-reduced-motion: reduce) {
    .live-goals-head-dot { animation: none; }
}

/* Elapsed time since the goal ("just now" / "5m" / "1h 20m"), pushed to the
   card's trailing edge opposite the match minute. */
.live-goal-ago {
    margin-left: auto;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.3px;
    opacity: 0.75;
}

/* Card — soft top-lit gradient (reads as a lit scoreboard panel rather than a
 * flat grey box) with a scoreboard-yellow edge marking it as a goal event.
 * `overflow:hidden` keeps that edge inside the rounded corners. */
.live-goal-card {
    position: relative;
    flex: 0 0 auto;
    min-width: 168px;
    max-width: 220px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 7px 10px 7px 13px;
    background:
        linear-gradient(160deg, rgba(255, 255, 255, 0.085), rgba(255, 255, 255, 0.02) 55%),
        var(--bg-darkb, rgba(255, 255, 255, 0.04));
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md, 6px);
    overflow: hidden;
    color: var(--text-primary);
    text-align: left;
    font: inherit;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}
/* Left accent edge — the "goal" marker. */
.live-goal-card::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: linear-gradient(180deg, #ffd000, rgba(255, 208, 0, 0.25));
}
.live-goal-card:hover {
    background:
        linear-gradient(160deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0.03) 55%),
        var(--bg-darkb, rgba(255, 255, 255, 0.04));
    border-color: rgba(255, 208, 0, 0.5);
    transform: translateY(-1px);
}

/* A goal that just landed gets a brief yellow frame. */
.live-goal-card.is-new {
    /* border-color: #ffd000; */
    animation: live-goal-card-in 0.4s ease-out;
}

@keyframes live-goal-card-in {
    from { transform: translateY(-4px); opacity: 0; }
    to   { transform: translateY(0); opacity: 1; }
}

.live-goal-card-top {
    display: flex;
    align-items: center;
    gap: 5px;
    margin-bottom: 2px;
    font-size: 10px;
    color: var(--text-muted);
}

.live-goal-pulse {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #ffd000;
    animation: live-pulse 1.4s infinite;
}

.live-goal-minute {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.live-goal-line {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    font-size: 12px;
}

.live-goal-score {
    flex-shrink: 0;
    width: 12px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text-secondary);
}

/* Kit beside each side's name on a goal card. 16px, not the shared 20px
   .team-kit-sm — these lines run at font-size 12px and a 20px kit outweighs the
   name it is labelling. flex-shrink:0 so the kit keeps its size and the NAME
   takes the ellipsis, which is the half that can afford to lose characters. */
.live-goal-kit {
    width: 16px;
    height: 16px;
    object-fit: contain;
    flex-shrink: 0;
}

.live-goal-team {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The side that scored — highlighted in both the card and the row chip. */
.live-goal-team.scored { color: #ffd000; font-weight: 700; }

/* ---- Chalked-off goal (VAR / feed correction) --------------------------- */
/* The card stays on the rail carrying the CORRECTED score, but drops every
   gold "a goal happened" cue for a red retraction so it can't be misread as
   another goal. */
.live-goal-card.is-disallowed::before {
    background: linear-gradient(180deg, var(--accent-red, #e5484d), rgba(229, 72, 77, 0.25));
}
.live-goal-card.is-disallowed:hover {
    border-color: rgba(229, 72, 77, 0.5);
}
.live-goal-card.is-disallowed .live-goal-pulse {
    background: var(--accent-red, #e5484d);
    animation: none;
}
/* The side that lost the goal: struck through, not celebrated. */
.live-goal-card.is-disallowed .live-goal-team.scored {
    color: var(--accent-red, #e5484d);
    text-decoration: line-through;
    text-decoration-thickness: 1px;
}

.live-goal-var {
    flex-shrink: 0;
    padding: 0 4px;
    border: 1px solid rgba(229, 72, 77, 0.55);
    border-radius: 0;
    color: var(--accent-red, #e5484d);
    font-size: 9px;
    font-weight: 800;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    white-space: nowrap;
}

/* The retraction needs its own motion, distinct from a goal's drop-in — a
   short horizontal "no" shake reads as "that didn't count". */
.live-goal-card.is-disallowed.is-new {
    animation: live-goal-card-void 0.45s ease-out;
}

@keyframes live-goal-card-void {
    0%      { transform: translateX(0); opacity: 0.45; }
    25%     { transform: translateX(-4px); opacity: 1; }
    50%     { transform: translateX(3px); }
    75%     { transform: translateX(-2px); }
    100%    { transform: translateX(0); }
}

/* A finished match (ported from gli-33 7b0ad9c4).
   The card stays until its goal ages out, but reads as over: a grey edge, no pulse,
   "Finished" where the minute was — and it opens the result, not the live page the
   match no longer has. */
.live-goal-card.is-ended::before {
    background: linear-gradient(180deg, var(--text-muted), color-mix(in srgb, var(--text-muted) 25%, transparent));
}
.live-goal-card.is-ended:hover { border-color: color-mix(in srgb, var(--text-muted) 50%, transparent); }
.live-goal-card.is-ended .live-goal-pulse { background: var(--text-muted); animation: none; }
.live-goal-card.is-ended .live-goal-minute { color: var(--text-secondary); }

@media (prefers-reduced-motion: reduce) {
    .live-goal-card.is-new { animation: none; }
    .live-goal-pulse { animation: none; }
    .live-goal-card.is-disallowed.is-new { animation: none; }
}

/* Search bar — slides down under the top bar. `[hidden]` on the wrapper hides it; we use
   max-height transitions for a smooth open/close. */
.live-search-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border-color);
    animation: liveSearchSlideDown .18s ease;
    margin-bottom: 8px;
    border-radius: var(--radius-dec);
}
.live-search-bar[hidden] { display: none !important; }
@keyframes liveSearchSlideDown {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}
.live-search-bar-icon {
    color: var(--text-muted);
    flex: 0 0 auto;
}
#live-search-input {
    flex: 1 1 auto;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 0;
    color: #ffffff;
    padding: 6px 10px;
    font-size: 13px;
    outline: none;
    min-width: 0;
}
#live-search-input:focus {
    border-color: rgba(58, 165, 110, 0.55);
    background: rgba(255, 255, 255, 0.06);
}
.live-search-clear {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    border: none;
    background: rgba(255, 255, 255, 0.08);
    color: var(--text-light);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
    flex: 0 0 auto;
}
.live-search-clear:hover { background: rgba(255, 255, 255, 0.16); }

/* Sort menu — floating popover anchored under the sort button. JS computes its left/top. */
.live-sort-menu {
    position: absolute;
    z-index: 9000;
    min-width: 200px;
    max-width: 260px;
    background: var(--bg-secondary);
    border: 1px solid rgba(255, 255, 255, 0.10);
    border-radius: 0;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
    padding: 6px;
}
.live-sort-menu[hidden] { display: none; }
.live-sort-items {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 320px;
    overflow-y: auto;
}
.live-sort-item {
    text-align: left;
    background: transparent;
    border: none;
    color: var(--text-light);
    padding: 8px 10px;
    border-radius: 0;
    font-size: 13px;
    cursor: pointer;
}
.live-sort-item:hover { background: rgba(255, 255, 255, 0.06); }
.live-sort-item.active {
    background: rgba(58, 165, 110, 0.18);
    color: #ffffff;
    font-weight: 600;
}
.live-sort-dir-row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 4px;
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.live-sort-dir {
    border: 1px solid rgba(255, 255, 255, 0.08);
    background: rgba(255, 255, 255, 0.03);
    color: var(--text-light);
    border-radius: 0;
    padding: 6px 10px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
}
.live-sort-dir:hover { background: rgba(255, 255, 255, 0.08); }
.live-sort-dir.active {
    background: rgba(58, 165, 110, 0.18);
    border-color: rgba(58, 165, 110, 0.55);
    color: var(--green-soft);
}

/* ============================================================================
 * LIVE — Flat list mode (used when search or non-default sort is active).
 * Replaces the per-league grouped layout with one global sorted list. Each row
 * shows the league name as a subtitle so context isn't lost.
 * ========================================================================== */
.live-flat-list {
    display: flex;
    flex-direction: column;
}

/* Flat-mode column header — shown above the global sorted/filtered list so the user
 * still sees the 1 X 2 / O/U labels without per-league grouping headers. Mirrors
 * .live-league-header layout (right-aligned odds block) for column alignment. */
.live-flat-list-header {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding: 6px 12px;
    background: var(--bg-tertiary);
    height: 34px;   /* matches .live-league-header — see the dense-board note there */
}
.live-match-league {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-top: 2px;
    font-size: 11px;
    color: var(--text-muted);
}
.live-match-league-flag {
    display: inline-flex;
    align-items: center;
    flex: 0 0 auto;
}
.live-match-league-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

/* Filter-active highlight for toolbar buttons. `.active` (already used for the open/close
   state of the search bar) is distinct — `.live-toolbar-on` specifically signals that a
   filter is shaping the current list. */
.live-view-btn.live-toolbar-on {
    background: rgba(58, 165, 110, 0.18);
    border: 1px solid rgba(58, 165, 110, 0.55);
    color: var(--accent-green, var(--green-soft));
    /* Small dot indicator in the top-right corner — extra-redundant cue, very glanceable. */
    position: relative;
}
.live-view-btn.live-toolbar-on::after {
    content: '';
    position: absolute;
    top: 3px;
    right: 3px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--accent-green, var(--green-soft));
    box-shadow: 0 0 0 2px var(--bg-secondary, var(--bg-secondary));
}

/* Clear-sort row inside the sort menu — appears only when sort is custom. */
.live-sort-clear {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 100%;
    background: rgba(220, 70, 70, 0.10);
    border: 1px solid rgba(220, 70, 70, 0.45);
    color: #ff9a9a;
    border-radius: 0;
    padding: 7px 10px;
    margin-bottom: 6px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
}
.live-sort-clear:hover { background: rgba(220, 70, 70, 0.18); }

/* ============================================================================
 * PROFILE PAGE (#PR) — Account / contact info + password change
 * ========================================================================== */
.profile-page {
    max-width: 640px;
    margin: 0 auto;
    /* padding: 24px 16px 80px; */
}
.profile-page-title {
    margin: 0 0 20px;
    font-size: 24px;
    font-weight: 700;
    color: var(--text-primary);
}

.profile-section {
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 0;
    padding: 18px 18px 20px;
    margin-bottom: 18px;
}
.profile-section-title {
    margin: 0 0 4px;
    font-size: 16px;
    font-weight: 700;
    color: var(--text-primary);
}
.profile-help {
    margin: 4px 0 14px;
    color: var(--text-muted);
    font-size: 12px;
    line-height: 1.5;
}

.profile-form { display: flex; flex-direction: column; gap: 14px; }
/* Settings: a switch with its title and a line under it (the scout on the Live list). The
   track and knob stay round, as toggles do (DESIGN-SYSTEM.md). */
.settings-toggle { display: flex; align-items: center; gap: 14px; cursor: pointer; }
.settings-toggle-text { flex: 1; min-width: 0; }
.settings-toggle-title { display: block; font-size: 14px; font-weight: 600; color: var(--text-primary); }
.settings-toggle-sub { display: block; margin-top: 3px; font-size: 12px; line-height: 1.5; color: var(--text-muted); }
.settings-switch { position: relative; flex: 0 0 auto; width: 44px; height: 26px; }
.settings-switch input { position: absolute; inset: 0; margin: 0; opacity: 0; cursor: pointer; }
.settings-switch-track {
    position: absolute;
    inset: 0;
    border-radius: 999px;
    background: var(--bg-tertiary);
    transition: background-color .2s ease;
    pointer-events: none;
}
.settings-switch-track::before {
    content: "";
    position: absolute;
    top: 3px;
    left: 3px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--text-primary);
    transition: transform .2s ease;
}
.settings-switch input:checked + .settings-switch-track { background: var(--accent-green); }
.settings-switch input:checked + .settings-switch-track::before { transform: translateX(18px); background: var(--bg-primary); }
.settings-switch input:focus-visible + .settings-switch-track { outline: 2px solid var(--accent-green); outline-offset: 2px; }
.profile-field { display: flex; flex-direction: column; gap: 6px; }
.profile-field-row {
    flex-direction: row;
    gap: 12px;
}
.profile-field-row > div { flex: 1 1 50%; display: flex; flex-direction: column; gap: 6px; }
.profile-label {
    font-size: 12px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--text-muted);
}
.profile-input {
    width: 100%;
    padding: 10px 12px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 0;
    color: var(--text-primary);
    font-size: 14px;
    font-weight: 500;
    transition: border-color .15s ease, background .15s ease;
}
.profile-input:focus {
    outline: none;
    border-color: rgba(58, 165, 110, 0.55);
    background: rgba(255, 255, 255, 0.06);
}
/* Native <option> elements use the OS dropdown chrome. macOS inherits the
   select's styling, but Windows defaults to white background — combined with
   the app's near-white text color this made the option list look empty.
   Force a dark background + readable text for both <option> and <optgroup>. */
.profile-input option,
.profile-input optgroup {
    background: var(--bg-secondary);
    color: var(--text-primary);
}
.profile-input[readonly] {
    background: rgba(255, 255, 255, 0.02);
    color: var(--text-muted);
    cursor: not-allowed;
}

.profile-password-row {
    display: flex;
    align-items: stretch;
    gap: 6px;
}
.profile-password-row .profile-input { flex: 1 1 auto; }
.profile-pwd-toggle {
    flex: 0 0 auto;
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.08);
    color: var(--accent-green, var(--green-soft));
    border-radius: 0;
    padding: 0 12px;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
}
.profile-pwd-toggle:hover { background: rgba(58, 165, 110, 0.10); }

.profile-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}
.profile-btn {
    /* Safe default so a .profile-btn WITHOUT .profile-btn-primary can't fall
       through to the UA default (blue on iOS). -primary overrides it. */
    color: var(--text-primary);
    border: none;
    border-radius: 0;
    padding: 10px 22px;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    transition: background .15s ease;
}
.profile-btn-primary {
    background: var(--accent-green, var(--green-soft));
    /* MUST be explicit. With `color` commented out this inherited each browser's
       UA stylesheet default for <button>: near-black on desktop, SYSTEM BLUE on
       iOS — so the Save button read blue on iPhone and dark on a laptop off the
       same CSS. It looked like a stale cached file and wasn't. #0f212e is what
       .guest-btn-register already uses for text on the green accent. */
    color: var(--bg-deep);
}
.profile-btn-primary:hover { background: #2e8e5d; }
.profile-btn-primary:disabled { background: #5e9a7e; cursor: default; }

.profile-msg {
    font-size: 13px;
    font-weight: 600;
}
.profile-msg-ok  { color: var(--accent-green, var(--green-soft)); }
.profile-msg-err { color: var(--red-soft); }

/* Mobile — stack the name+surname row */
@media (max-width: 600px) {
    /* .profile-page { padding: 16px 12px 80px; } */
    .profile-field-row { flex-direction: column; gap: 14px; }
    .profile-field-row > div { flex: 1 1 100%; }
}

/* ============================================================================
 * MONEY TRANSFER (#MT) — user view (deposit/withdrawal forms + history) +
 * agent view (pending queue + history + manage accounts).
 * Reuses `.profile-page` / `.profile-section` / `.profile-input` for consistency.
 * ========================================================================== */
.mt-page { max-width: 720px; }

.mt-tabs {
    display: flex;
    gap: 6px;
    padding: 4px;
    background: var(--bg-input);
    border: 1px solid var(--bg-lightg);
    border-radius: 0;
    margin-bottom: 16px;
    overflow-x: auto;
    /* The bar scrolls only as a safety valve for long translations; the tabs
       are sized to fit, so the scrollbar itself is just noise. Hidden in all
       three engines. */
    scrollbar-width: none;
    -ms-overflow-style: none;
}
.mt-tabs::-webkit-scrollbar { display: none; }
.mt-tab {
    flex: 1 1 0;
    min-width: 110px;
    white-space: nowrap;
    text-align: center;
    background: transparent;
    border: none;
    color: var(--text-muted);
    padding: 9px 12px;
    font-size: 13px;
    font-weight: 600;
    border-radius: 0;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}
.mt-tab:hover  { color: var(--text-secondary); }
.mt-tab.active {
    background: rgba(58, 165, 110, 0.18);
    color: var(--text-primary);
}

.mt-body { display: flex; flex-direction: column; gap: 14px; }
.mt-loading, .mt-empty {
    padding: 32px 16px;
    text-align: center;
    color: var(--text-muted);
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 0;
}

.mt-form { display: flex; flex-direction: column; gap: 14px; padding: 14px 0; }
.mt-field { display: flex; flex-direction: column; gap: 6px; }
.mt-amount-row { display: flex; align-items: center; gap: 8px; }
.mt-amount-row .profile-input { flex: 1 1 auto; }
.mt-currency {
    flex: 0 0 auto;
    padding: 10px 12px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 0;
    color: var(--text-muted);
    font-size: 13px;
    font-weight: 600;
}

.mt-account-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 8px;
}
.mt-account-card {
    cursor: pointer;
    display: block;
    position: relative;
}
.mt-account-card input { position: absolute; opacity: 0; pointer-events: none; }
.mt-account-card-inner {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 0;
    transition: border-color .15s, background .15s;
}
.mt-account-card input:checked + .mt-account-card-inner {
    border-color: rgba(58, 165, 110, 0.55);
    background: rgba(58, 165, 110, 0.10);
}
.mt-account-logo { flex: 0 0 36px; }
.mt-account-meta { display: flex; flex-direction: column; min-width: 0; }
.mt-account-name { font-weight: 600; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mt-account-number { font-size: 12px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.mt-logo-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: rgba(58, 165, 110, 0.18);
    color: var(--accent-green, var(--green-soft));
    font-weight: 800;
    font-size: 13px;
    letter-spacing: -0.3px;
}

.mt-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

.mt-file-status { font-size: 12px; color: var(--text-muted); }
.mt-file-status.ok { color: var(--accent-green, var(--green-soft)); }
.mt-file-status.err { color: var(--red-soft); }

.mt-list { display: flex; flex-direction: column; gap: 10px; }
.mt-tx-card {
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 0;
    padding: 12px 14px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    transition: opacity .25s ease, transform .25s ease;
}
.mt-tx-card.mt-fading { opacity: 0; transform: translateY(-6px); }
.mt-tx-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.mt-tx-type { font-weight: 700; color: var(--text-primary); }
.mt-tx-user { font-size: 13px; color: var(--text-secondary); }
.mt-tx-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
.mt-tx-amount { font-size: 16px; font-weight: 700; color: var(--text-primary); }
.mt-tx-date { font-size: 12px; color: var(--text-muted); }
.mt-tx-meta { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-muted); }
.mt-tx-meta .mt-logo-chip { width: 24px; height: 24px; font-size: 10px; }
.mt-tx-ref, .mt-tx-note, .mt-tx-agent-note, .mt-tx-balance { font-size: 12px; color: var(--text-secondary); }
.mt-tx-proof img { max-width: 160px; max-height: 120px; border-radius: 0; }

.mt-pill {
    display: inline-block;
    font-size: 11px;
    font-weight: 700;
    padding: 3px 8px;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.06);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.3px;
    margin-left: auto;
}
.mt-pill.mt-status-pending { background: rgba(255, 153, 0, 0.18); color: #ffb547; }
.mt-pill.mt-status-ok       { background: rgba(58, 165, 110, 0.18); color: var(--green-soft); }
.mt-pill.mt-status-err      { background: rgba(220, 70, 70, 0.18);  color: var(--red-soft); }

.mt-tx-agent-row {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
    margin-top: 4px;
}
.mt-agent-note-input { flex: 1 1 200px; min-width: 0; }
.mt-btn-approve { background: var(--accent-green, var(--green-soft)); color: #fff; }
.mt-btn-approve:hover { background: #2e8e5d; }
.mt-btn-reject  { background: #b13a3a; color: #fff; }
.mt-btn-reject:hover  { background: #983131; }

.mt-account-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 0;
}
.mt-account-row.inactive { opacity: 0.55; }
.mt-account-row .mt-account-meta { flex: 1 1 auto; min-width: 0; }
.mt-icon-btn {
    width: 32px;
    height: 32px;
    border-radius: 0;
    border: 1px solid rgba(255, 255, 255, 0.08);
    background: rgba(255, 255, 255, 0.04);
    color: var(--text-primary);
    cursor: pointer;
    flex: 0 0 auto;
}
.mt-icon-btn:hover { background: rgba(255, 255, 255, 0.10); }
.mt-icon-danger:hover { background: rgba(220, 70, 70, 0.18); color: var(--red-soft); }

/* ============================================================================
 * MT — user view (mimics legacy user.aspx flow): step labels, instruction box,
 *      upload zone with valid/invalid states, success screen, toast.
 *      Kept on the dark theme — same visual identity as the rest of the app.
 *      (Re-added after a sync wiped the previous append.)
 * ========================================================================== */
.mt-user-form { gap: 18px; }
.mt-step { display: flex; flex-direction: column; gap: 10px; }
.mt-step-label {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.8px;
    color: var(--text-muted);
}
.mt-step-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--accent-green, var(--green-soft));
    color: #fff;
    font-size: 11px;
    font-weight: 700;
}

.mt-account-list { display: flex; flex-direction: column; gap: 8px; }
.mt-acc-card {
    background: var(--bg-secondary);
    border: 2px solid var(--border-color);
    border-radius: 0;
    padding: 12px 14px;
    display: flex;
    align-items: center;
    gap: 12px;
    cursor: pointer;
    transition: border-color .15s ease, background .15s ease;
    position: relative;
}
.mt-acc-card:hover    { border-color: rgba(58, 165, 110, 0.45); }
.mt-acc-card.selected { border-color: var(--accent-green, var(--green-soft)); background: rgba(58, 165, 110, 0.10); }
.mt-acc-card input    { position: absolute; opacity: 0; pointer-events: none; }
.mt-acc-card-inner    { display: flex; align-items: center; gap: 12px; width: 100%; }
.mt-acc-icon {
    flex: 0 0 40px;
    height: 40px;
    border-radius: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.06);
}
.mt-acc-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.mt-acc-name { font-weight: 600; font-size: 14px; color: var(--text-primary); }
.mt-acc-sub  { font-size: 12px; color: var(--text-muted); }
.mt-acc-number {
    font-family: 'SF Mono', 'Fira Mono', 'Courier New', monospace;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-secondary);
}

.mt-instruction-box {
    background: rgba(58, 165, 110, 0.08);
    border: 1px solid rgba(58, 165, 110, 0.35);
    border-radius: 0;
    padding: 14px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.mt-instruction-box[hidden] { display: none; }
.mt-instr-title { font-size: 13px; font-weight: 700; color: var(--text-primary); }
.mt-instr-row   { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.mt-instr-label { color: var(--text-muted); flex: 0 0 auto; }
.mt-instr-value { color: var(--text-primary); font-weight: 600; margin-left: auto; }
.mt-mono        { font-family: 'SF Mono', 'Fira Mono', 'Courier New', monospace; }
.mt-copy-btn {
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.08);
    color: var(--text-secondary);
    border-radius: 0;
    padding: 3px 8px;
    cursor: pointer;
    font-size: 14px;
}
.mt-copy-btn:hover { background: rgba(255, 255, 255, 0.10); }

.mt-currency-suffix { color: var(--text-muted); font-weight: 500; text-transform: none; letter-spacing: 0; }

#mt-step2[hidden] { display: none; }

.mt-upload-zone {
    position: relative;
    border: 2px dashed rgba(255, 255, 255, 0.10);
    border-radius: 0;
    padding: 22px 16px;
    text-align: center;
    cursor: pointer;
    transition: border-color .15s, background .15s;
    background: var(--bg-secondary);
}
.mt-upload-zone:hover  { border-color: rgba(58, 165, 110, 0.55); background: rgba(58, 165, 110, 0.06); }
.mt-upload-zone.valid  { border-style: solid; border-color: rgba(58, 165, 110, 0.55); background: rgba(58, 165, 110, 0.08); }
.mt-upload-zone.invalid{ border-style: solid; border-color: rgba(220, 70, 70, 0.55);  background: rgba(220, 70, 70, 0.08); }
.mt-upload-zone.loading{ border-color: rgba(255, 255, 255, 0.18); }
.mt-upload-zone input  { position: absolute; inset: 0; opacity: 0; cursor: pointer; }
.mt-upload-icon  { font-size: 26px; margin-bottom: 6px; }
.mt-upload-text  { font-size: 13px; color: var(--text-secondary); }
.mt-upload-zone.valid   .mt-upload-text { color: var(--accent-green, var(--green-soft)); font-weight: 600; }
.mt-upload-zone.invalid .mt-upload-text { color: var(--red-soft); font-weight: 600; }
.mt-upload-filename {
    font-size: 12px;
    color: var(--text-muted);
    margin-top: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.mt-preview-wrap { margin-top: 10px; position: relative; }
.mt-preview-wrap[hidden] { display: none; }
.mt-preview-wrap img {
    width: 100%;
    max-height: 200px;
    object-fit: cover;
    border-radius: 0;
    border: 2px solid var(--accent-green, var(--green-soft));
    display: block;
}
#mt-preview-remove {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: rgba(0, 0, 0, 0.55);
    color: #fff;
    border: none;
    cursor: pointer;
    font-size: 16px;
    line-height: 1;
}

.mt-submit-btn {
    width: 100%;
    height: 50px;
    background: var(--accent-green, var(--green-soft));
    /* MUST be explicit — same trap as .profile-btn-primary (fixed in aec8496)
       and it was still live here. With `color` commented out the label falls
       through to each browser's UA stylesheet default for <button>: near-black
       on desktop, SYSTEM BLUE on iOS. Identical CSS, different platform default,
       so it reads as a stale cache and isn't. #0f212e is what
       .guest-btn-register and .profile-btn-primary already use on this green. */
    color: var(--bg-deep);
    border: none;
    border-radius: 0;
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
    transition: background .15s ease, opacity .15s ease;
}
.mt-submit-btn:hover  { background: #2e8e5d; }
.mt-submit-btn:disabled { opacity: 0.55; cursor: not-allowed; }
.mt-submit-btn.loading::after { content: '…'; margin-left: 4px; }

.mt-submit-result {
    font-size: 13px;
    font-weight: 600;
    margin-top: 6px;
    min-height: 18px;
}
.mt-submit-result.profile-msg-ok  { color: var(--accent-green, var(--green-soft)); }
.mt-submit-result.profile-msg-err { color: var(--red-soft); }

.mt-success { text-align: center; padding: 50px 16px; }
.mt-success-icon {
    width: 70px;
    height: 70px;
    border-radius: 50%;
    background: rgba(58, 165, 110, 0.18);
    color: var(--accent-green, var(--green-soft));
    font-size: 36px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 16px;
}
.mt-success-title { font-size: 20px; font-weight: 700; margin-bottom: 8px; color: var(--text-primary); }
.mt-success-msg   { color: var(--text-muted); font-size: 14px; line-height: 1.5; margin-bottom: 18px; }
.mt-btn-again { width: auto; padding: 0 28px; }

.mt-toast {
    position: fixed;
    bottom: calc(20px + env(safe-area-inset-bottom, 0px));
    left: 50%;
    transform: translateX(-50%) translateY(20px);
    background: var(--bg-deep);
    color: #fff;
    padding: 10px 18px;
    border-radius: 0;
    font-size: 13px;
    font-weight: 500;
    opacity: 0;
    transition: opacity .2s, transform .2s;
    pointer-events: none;
    z-index: 999;
    white-space: nowrap;
}
.mt-toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ============================================================================
 * Basketball live match-detail stats panel — narrow-panel fix.
 * The 3-column flank · center · flank grid needs ~467px (each card is
 * min-width:48px + padding); below that the away flank is clipped off the right
 * edge. Stack vertically instead so each section gets full width.
 *
 * Keyed to the PANEL's width, not the viewport. As a `@media (max-width: 600px)`
 * this only knew about small phones, so the desktop rail — a 330px panel on a
 * 1400px window — kept the wide grid and lost the away flank entirely. The
 * panel's own width is the thing that actually decides whether the row fits.
 * ========================================================================== */
@container lmst (max-width: 600px) {
    .lmst-bb-stats {
        grid-template-columns: 1fr;
        gap: 12px;
    }
    .lmst-bb-flank {
        flex-wrap: wrap;
        gap: 6px;
    }
    .lmst-bb-card {
        min-width: 40px;
        padding: 4px 6px;
    }
    .lmst-bb-card-val { font-size: 16px; }
    /* Score table — also tight on small screens; reduce cell padding and font. */
    .lmst-bb-score th,
    .lmst-bb-score td {
        padding: 4px 4px;
        font-size: 13px;
    }
}

/* ============================================================================
 * Twemoji — inline emoji images served by `CountryFlags.getFlag()` when the
 * twemoji library is available. The library auto-adds `class="emoji"`.
 * ========================================================================== */
img.emoji {
    height: 1em;
    width:  1em;
    margin: 0 .05em 0 .1em;
    vertical-align: -0.15em;
    /* Twemoji asks for `draggable="false"` so users don't accidentally drag a flag */
    user-drag: none;
    -webkit-user-drag: none;
}

/* ============================================================================
 * Narrow-phone polish
 *   - Bottom-nav labels: force single line with ellipsis (Albanian "Bastet e Mia"
 *     was wrapping to two lines and breaking the vertical alignment of all 5 items).
 *   - Content-tabs strip: scroll-padding so the active tab can't be clipped on
 *     the left when the strip overflows.
 *   - Header wallet pill: drop the currency badge on very narrow screens; compact
 *     padding so the balance + avatar fit on a 360 px viewport.
 * ========================================================================== */
.bottom-nav-item > span,
.bottom-nav-item > a > span {
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
@media (max-width: 600px) {
    .bottom-nav-item {
        font-size: 11px;
        gap: 3px;
    }
    .bottom-nav-item > span,
    .bottom-nav-item > a > span {
        font-size: 11px;
        line-height: 1.1;
    }
}

/* Tab strip — leave a little extra room on the left so the active pill never gets
   clipped when the container overflows. */
.content-tabs {
    scroll-padding-inline: 4px;
}

/* Very-narrow header: kill the avatar's negative-space padding, tighten the wallet pill */
@media (max-width: 400px) {
    .top-header { padding: 0 8px; }
    .wallet-display { padding: 5px 8px; font-size: 12px; gap: 4px; }
    .currency-badge { display: none; }   /* "L" / "€" badge — the symbol is enough */

    /* Sign-in / Register overlapped the Kazino button on a 375px viewport: the
       Kazino glyph ended at x=230 and "Hyr" started at x=223, so the sign-in
       button was drawn ON TOP of it. (Pre-existing — it was a 12px overlap before
       the switch to Oxanium, which is marginally narrower here.)
       The cause is a width budget, not a stray offset. .header-right is
       `flex: 0 1 auto; min-width: 0`, so it shrank to the 137px the flex line had
       left while .guest-actions inside it needed 144px; the surplus spilled LEFT,
       because the group is right-aligned. Nothing was mispositioned — the row
       simply asked for 7px more than a 375px header has:
           logo 122 + toggle 92 + guest 144 + padding 16 = 374 of 375.
       So the fix is to give the 7px back. Trimming the two guest buttons is the
       cheapest place: they are text pills with the most padding to spare, and
       unlike the logo or the product toggle nothing about them is size-critical.
       (Hiding .product-toggle-label here would be a no-op — the 900px block
       already swaps these buttons to their icon-only `-mini` artwork.)
       The .guest-btn half of the fix lives with the other .guest-btn rules near
       the end of this file, NOT here: a `@media (max-width: 480px)` block down
       there sets the same property at the same specificity, and being later it
       would win. Same-specificity overrides have to be ordered, not just scoped. */
    .guest-actions { gap: 5px; }

    /* The wordmark is the one item in this row with slack. Everything else is
       either a tap target (the toggle, the two auth buttons) or the padding that
       makes the two groups read as groups; shrinking the logo costs legibility
       nothing and buys back the ~20px the rounded cards need at 375px. Measured
       after: the brand card ends before the auth card starts, with clearance to
       spare, and the document still does not scroll sideways. */
    .logo-img { height: 42px; }
}

/* ============================================================================
 * FINANCE (#FI) — win/loss reporting across product verticals.
 * Reuses `.profile-page` / `.profile-page-title` and mirrors the `.mt-*` tab
 * styling so the page looks at home next to Money Transfer.
 * ========================================================================== */
.fin-page { max-width: 720px; }

/* Quick-range presets — horizontally scrollable pill row sitting above the
 * date pickers. Visual language matches `.mybets-preset` so the two pages
 * feel like siblings; namespaced under `.fin-*` to keep selectors specific. */
.fin-quickranges {
    display: flex;
    gap: 4px;
    overflow-x: auto;
    scrollbar-width: none;
    scroll-behavior: smooth;
    margin-bottom: 10px;
}
.fin-quickranges::-webkit-scrollbar { display: none; }

.fin-quickrange {
    flex-shrink: 0;
    padding: 8px 14px;
    background: var(--bg-tertiary);
    border: 1px solid transparent;
    border-radius: 999px;
    color: var(--text-secondary);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease, border-color .15s ease;
    white-space: nowrap;
}
.fin-quickrange:hover {
    color: var(--text-primary);
    background: var(--bg-hover);
}
.fin-quickrange.active {
    background: var(--accent-odds);
    color: var(--bg-deep);
    border-color: var(--accent-odds);
}

/* Date range strip — two native HTML5 date inputs side-by-side. */
.fin-daterange {
    display: flex;
    gap: 12px;
    margin-bottom: 14px;
}
.fin-daterange-field {
    display: flex;
    flex-direction: column;
    gap: 4px;
    flex: 1 1 0;
    min-width: 0;
}
.fin-daterange-field > span {
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--text-muted);
}
.fin-daterange-field > input[type="date"] {
    padding: 9px 12px;
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 0;
    color: var(--text-primary);
    font-size: 14px;
    font-weight: 500;
    color-scheme: dark;   /* asks the browser to paint the native picker dark */
}
.fin-daterange-field > input[type="date"]:focus {
    outline: none;
    border-color: rgba(58, 165, 110, 0.55);
}

/* Tabs — same shape as `.mt-tabs` for visual consistency across account pages. */
.fin-tabs {
    display: flex;
    gap: 6px;
    padding: 4px;
    background: var(--bg-input);
    border: 1px solid var(--bg-lightg);
    border-radius: 0;
    margin-bottom: 16px;
    overflow-x: auto;
    /* Still swipeable on narrow phones, but no visible scrollbar. */
    scrollbar-width: none;
    -ms-overflow-style: none;
    touch-action: pan-x pan-y;
}
.fin-tabs::-webkit-scrollbar { display: none; }
.fin-tab {
    flex: 1 1 0;
    min-width: 110px;
    text-align: center;
    background: transparent;
    border: none;
    color: var(--text-muted);
    padding: 9px 12px;
    font-size: 13px;
    font-weight: 600;
    border-radius: 0;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}
.fin-tab:hover  { color: var(--text-secondary); }
.fin-tab.active {
    background: rgba(58, 165, 110, 0.18);
    color: var(--text-primary);
}

.fin-body { display: flex; flex-direction: column; gap: 14px; }
.fin-loading, .fin-empty {
    padding: 32px 16px;
    text-align: center;
    color: var(--text-muted);
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    border-radius: 0;
}


/* ==========================================
   PLAYER STATISTICS, LINEUPS, PLAYER CARD (playerstats.js)
   Two tabs in the live summary panel, both drawn from ndeshje.player_stats.
   ========================================== */
.ps-picker {
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 5px 6px;
    margin-bottom: 8px;
    background: var(--bg-odds);
    border-radius: var(--radius-md);
    /* Eight chips do not fit the side rail: the row scrolls instead of clipping xG,
       and playerstats.js carries the position across the poll re-renders. */
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
}
.ps-picker::-webkit-scrollbar { display: none; }
.ps-list-wrap { scrollbar-width: none; }
.ps-list-wrap::-webkit-scrollbar { display: none; }
.ps-pick {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 30px;
    background: none;
    border: 0;
    border-radius: 0;
    color: var(--text-muted);
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}
.ps-pick.active { background: var(--bg-tertiary); color: var(--accent-green); }
.ps-pick-gap { flex: 1; }
.ps-pick-xg { font-size: 12px; font-weight: 700; letter-spacing: 0.03em; }

/* --- split by side: one statistic, the two squads facing each other --- */
.ps-split-title {
    padding: 6px 4px;
    text-align: center;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.ps-split { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 14px; }
.ps-srow {
    display: flex;
    align-items: center;
    gap: 8px;
    height: 34px;
    border-top: 1px solid var(--border-subtle);
}
.ps-srow:first-child { border-top: 0; }
.ps-srow.ps-away { flex-direction: row-reverse; }
.ps-sname {
    flex: 1;
    min-width: 0;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--text-primary);
    text-align: right;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ps-srow.ps-away .ps-sname { text-align: left; }
.ps-sval {
    flex: none;
    width: 34px;
    height: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 0;
    background: rgba(192, 232, 73, 0.13);
    color: var(--accent-green);
    font-size: 12.5px;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}
.ps-sval.ps-wide { width: 42px; }
/* A zero loses its chip, so the players who did something read at a glance. */
.ps-sval.ps-zero { background: none; color: var(--text-muted); font-weight: 600; }

/* --- list: every column at once --- */
.ps-list-wrap { overflow-x: auto; }
.ps-list { width: 100%; border-collapse: collapse; }
.ps-list th, .ps-list td { padding: 0; }
/* The name column stays put while the statistics scroll under their heads. Its
   background matches the panel it sits on (--bg-secondary), or the numbers would
   slide through it. */
.ps-list .ps-th-name, .ps-list td:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
    background: var(--bg-secondary);
}
.ps-colh {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 30px;
    margin: 0 auto;
    background: none;
    border: 0;
    border-radius: 0;
    color: var(--text-muted);
    cursor: pointer;
}
.ps-colh.active { background: var(--bg-tertiary); color: var(--accent-green); }
.ps-list tbody tr { border-top: 1px solid var(--border-subtle); }
.ps-nm {
    display: flex;
    align-items: center;
    gap: 7px;
    height: 38px;
    padding-right: 8px;
    font-size: 12.5px;
    font-weight: 500;
}
.ps-nm-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ps-kit { width: 16px; height: 16px; object-fit: contain; flex-shrink: 0; }
.ps-v {
    width: 40px;
    text-align: center;
    font-size: 12.5px;
    font-weight: 600;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}
.ps-v.active { color: var(--text-primary); font-weight: 800; background: rgba(var(--bg-tertiary-rgb), 0.45); }
.ps-v-xg { width: 48px; color: var(--accent-odds); }

/* --- goals, assist and cards: the same marks on a row and on a shirt --- */
.ps-marks { display: inline-flex; align-items: center; gap: 4px; margin-left: 2px; }
.ps-mark { display: inline-flex; }
.ps-assist { color: var(--accent-green); }
.ps-card-y, .ps-card-r { display: inline-block; width: 7px; height: 10px; border-radius: 0; }
.ps-card-y { background: var(--gold); }
.ps-card-r { background: var(--accent-red); }

/* --- lineups --- */
.ps-team-tabs {
    display: flex;
    gap: 4px;
    padding: 3px;
    margin-bottom: 8px;
    background: var(--bg-input);
    border: 1px solid var(--border-subtle);
    border-radius: 0;
}
.ps-team-tab {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    height: 36px;
    padding: 0 8px;
    background: none;
    border: 0;
    border-radius: 0;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 700;
    cursor: pointer;
}
.ps-team-tab.active { background: var(--bg-tertiary); color: var(--text-primary); }
.ps-team-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Everything on the pitch is sized from the room the pitch actually has, never
   from the window. With the betslip open, a desktop's markets column is as narrow
   as a phone, and window breakpoints kept drawing desktop-sized players into it
   until their names ran over each other. The row is the container the layout
   switches read; the pitch is the one its players scale against. */
.ps-field-row { display: flex; gap: 6px; align-items: stretch; container-type: inline-size; }
.ps-subs-rail {
    flex: none;
    width: 50px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding-top: 6px;
    background: none;
    border: 0;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 10.5px;
    font-weight: 700;
    cursor: pointer;
}
.ps-subs-rail.active { color: var(--accent-green); }
/* Open, the bench takes the pitch's place: the panel sits in the detail page's
   side rail, where the two side by side left no room for either. */
.ps-bench {
    flex: 1;
    min-width: 0;
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px 4px;
    align-content: start;
    padding: 8px 2px;
}
.ps-sub {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    background: none;
    border: 0;
    padding: 0;
    color: inherit;
    cursor: pointer;
}
/* Bench dots are dimmed by a veil over the shirt colour, not by opacity on the
   dot: opacity would fade the goal / card marks that sit inside it too. */
.ps-sub .ps-dot::before {
    content: '';
    position: absolute;
    inset: -1px;
    border-radius: 50%;
    background: var(--bg-primary);
    opacity: 0.45;
}
.ps-sub.active .ps-dot::before { display: none; }
.ps-sub .ps-marks { z-index: 1; }
.ps-pitch {
    container-type: inline-size;
    position: relative;
    flex: 1;
    min-width: 0;
    aspect-ratio: 3 / 4;
    max-height: 430px;
    border-radius: var(--radius-md);
    background: #16302a;
    overflow: hidden;
}
.ps-lines { position: absolute; inset: 0; width: 100%; height: 100%; }
.ps-spot {
    position: absolute;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    /* As wide as the gap to the next player on his own line (--ps-span, set per
       spot by PlayerStats._pitch), so neighbours never touch and a short line
       gives its names the room a five-man line cannot. */
    width: clamp(30px, calc(var(--ps-span, 14) * 1cqw), 110px);
    padding: 0;
    background: none;
    border: 0;
    color: inherit;
    cursor: pointer;
}
.ps-dot {
    /* 16px on a phone's pitch, 24px on a wide one. */
    --ps-dot: clamp(16px, calc(9px + 2.3cqw), 24px);
    position: relative;
    width: var(--ps-dot);
    height: var(--ps-dot);
    border-radius: 50%;
    background: #fff;
    border: 1px solid rgba(0, 0, 0, 0.35);
}
.ps-spot.active .ps-dot, .ps-sub.active .ps-dot { box-shadow: 0 0 0 2px var(--accent-green); }
.ps-spot .ps-marks, .ps-sub .ps-marks { position: absolute; top: -4px; right: -9px; gap: 2px; margin: 0; }
.ps-spot-name {
    max-width: 100%;
    /* 9px on a phone's pitch, 12px on a wide one. */
    font-size: clamp(9px, calc(6.4px + 0.86cqw), 12px);
    font-weight: 600;
    color: var(--text-primary);
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* --- player card: his shirt number and the prices the match offers on him --- */
.ps-card { margin-top: 10px; border-top: 1px solid var(--border-subtle); }
.ps-card-empty { padding: 12px 4px; font-size: 12.5px; color: var(--text-muted); }
.ps-card-head { display: flex; align-items: center; gap: 10px; padding: 10px 2px; }
.ps-card-kit { position: relative; flex: none; width: 30px; height: 30px; }
.ps-card-kit .ps-kit { width: 30px; height: 30px; }
.ps-card-num {
    position: absolute;
    right: -5px;
    bottom: -3px;
    width: 18px;
    height: 18px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--bg-odds);
    border: 1px solid var(--border-color);
    font-size: 9.5px;
    font-weight: 800;
    color: var(--text-primary);
}
.ps-card-name { display: block; font-size: 14px; font-weight: 700; }
.ps-card-team { display: block; font-size: 11.5px; font-weight: 600; color: var(--text-muted); }
.ps-mkt-head { padding: 8px 2px 2px; font-size: 12px; font-weight: 700; }
.ps-mkt-odds { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ps-mkt-odds-one { grid-template-columns: minmax(0, 1fr); }

/* A two-leg tie's goals over both legs, after the team's name in a match row. */
.agg-leg {
    flex-shrink: 0;
    margin-left: 5px;
    color: var(--text-muted);
    font-size: 11.5px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* The operator's own stat icons keep their colours; only their size is ours. */
.ps-ico { width: 20px; height: 14px; object-fit: contain; display: block; }

/* Lineups as a market category: the markets column is wide, so the pitch lies
   flatter there and the bench spreads out. The view takes a card of its own,
   like the markets it replaces. */
.md-markets-lineups {
    background: var(--bg-secondary);
    border-radius: var(--radius-dec);
    padding: 10px 10px 4px;
}
.md-markets-lineups .ps-pitch { max-height: 560px; }
.md-markets-lineups .ps-card-name { font-size: 16px; }
/* Room enough to lie the pitch flat and spread the bench along one row. Read off
   the field row's width, so the betslip opening on a desktop folds it back up. */
@container (min-width: 600px) {
    .md-markets-lineups .ps-pitch { aspect-ratio: 16 / 11; }
    .md-markets-lineups .ps-bench { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

/* Aggregate over both legs (ndeshje.agg_score) — nothing is shown when the field
   is empty, which is every match that is not a two-leg tie. */
.live-md-agg,
.md-agg {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-top: 4px;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--bg-tertiary);
    color: var(--text-muted);
    font-size: 10.5px;
    font-weight: 700;
    white-space: nowrap;
}
.live-md-agg b,
.md-agg b { color: var(--text-primary); font-variant-numeric: tabular-nums; }

@media (max-width: 600px) {
    .ps-bench { flex-basis: 46%; gap: 8px 2px; }
}

/* ==========================================
   ACCOUNT VERIFICATION + KYC (GLI-33 Phase 1)
   ========================================== */
.kyc-loading, .kyc-error { color: var(--text-muted); font-size: 14px; padding: 8px 0; }
.kyc-error { color: var(--accent-red); }

.kyc-gate {
    border-radius: var(--radius-md);
    padding: 12px 14px;
    font-size: 14px;
    margin-bottom: 14px;
    font-weight: 600;
}
.kyc-gate-ok    { background: rgba(0, 231, 1, 0.12);  color: var(--accent-green); }
.kyc-gate-block { background: rgba(237, 65, 99, 0.12); color: #ffb3c1; }
/* Waiting on the review is not an error: the same amber as the pending badge. */
.kyc-gate-wait  { background: rgba(224, 163, 46, 0.12); color: var(--gold); }

.kyc-row {
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 14px;
    color: var(--text-primary);
    padding: 8px 0;
}
.kyc-badge {
    flex-shrink: 0;
    width: 22px; height: 22px;
    border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 12px; font-weight: 800;
}
.kyc-badge-ok       { background: var(--accent-green-grad); color: #06330c; }
.kyc-badge-warn,
.kyc-badge-rejected { background: var(--accent-red);  color: #fff; }
.kyc-badge-pending  { background: var(--amber); color: #3a2a06; }

.kyc-btn-link {
    margin-left: auto;
    background: none; border: none;
    color: var(--accent-green);
    font-size: 13px; font-weight: 700;
    cursor: pointer; padding: 4px 6px;
}
.kyc-btn-link:disabled { color: var(--text-muted); cursor: default; }

.kyc-reject-reason {
    background: var(--bg-tertiary);
    border-left: 3px solid var(--accent-red);
    border-radius: 0 var(--radius-md) var(--radius-md) 0;
    padding: 8px 12px; margin: 4px 0 8px;
    font-size: 13px; color: var(--text-muted);
}

.kyc-help { font-size: 13px; color: var(--text-muted); margin: 14px 0 10px; }

.kyc-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 12px;
}
.kyc-tile {
    background: var(--bg-tertiary);
    border-radius: var(--radius-md);
    padding: 14px;
    text-align: center;
}
.kyc-tile-label { font-size: 13px; font-weight: 600; color: var(--text-primary); margin-bottom: 10px; }
.kyc-upload-btn {
    display: inline-block;
    background: var(--accent-green-grad); color: #06330c;
    font-size: 13px; font-weight: 700;
    padding: 8px 18px; border-radius: var(--radius-md);
    cursor: pointer;
}
.kyc-tile-status { font-size: 12px; font-weight: 700; padding: 6px 0; }
.kyc-tile-pending  { color: var(--amber); }
.kyc-tile-approved { color: var(--accent-green); }
.kyc-tile-rejected { color: var(--accent-red); }
.kyc-msg { font-size: 13px; color: var(--text-muted); margin-top: 10px; min-height: 16px; }

/* App-wide email-verify banner — fixed bar directly below the fixed header.
   The header is position:fixed (z-index 100); this sits just under it at a
   fixed 44px height. When shown, body.has-verify-banner pushes .main-layout
   down by header + banner so nothing is hidden behind it. */
.verify-banner {
    position: fixed;
    top: var(--header-height);
    left: 0;
    right: 0;
    z-index: 99;
    height: 44px;
    box-sizing: border-box;
    display: flex; align-items: center; gap: 10px;
    background: var(--amber); color: #2a1e04;
    padding: 0 16px; font-size: 13px; font-weight: 600;
}
.verify-banner-icon {
    flex-shrink: 0;
    width: 20px; height: 20px; border-radius: 50%;
    background: #2a1e04; color: var(--amber);
    display: inline-flex; align-items: center; justify-content: center;
    font-weight: 800;
}
/* Single line so the bar height stays a predictable 44px on every screen;
   the text truncates before the always-visible "Verify now" button. */
.verify-banner-text {
    flex: 1; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.verify-banner-btn {
    flex-shrink: 0;
    background: #2a1e04; color: #fff;
    text-decoration: none; font-weight: 700;
    padding: 6px 14px; border-radius: var(--radius-md);
    white-space: nowrap;
}
/* Offset the page content for the 44px banner when it's visible. */
body.has-verify-banner .main-layout {
    margin-top: calc(var(--header-height) + 44px);
}

/* GLI-33 §2.5c register T&C checkbox + §2.1b forgot-password view */
.reg-terms {
    display: flex; align-items: flex-start; gap: 10px;
    font-size: 13px; line-height: 1.45; color: var(--text-muted);
    margin: 6px 0 4px; cursor: pointer;
}
.reg-terms input[type="checkbox"] { margin-top: 2px; flex-shrink: 0; width: 16px; height: 16px; accent-color: var(--accent-green); }
.forgot-title { font-size: 18px; font-weight: 700; color: var(--text-primary); margin: 0 0 6px; }
.forgot-help  { font-size: 13px; color: var(--text-muted); margin: 0 0 14px; line-height: 1.5; }

/* Responsible gambling — self-exclusion (GLI-33 §2.5) */
.rg-help { font-size: 13px; color: var(--text-muted); line-height: 1.55; margin: 0 0 14px; }
.rg-exclude-row { display: flex; gap: 10px; align-items: stretch; flex-wrap: wrap; }
.rg-period { flex: 1; min-width: 160px; }
.rg-exclude-btn {
    flex-shrink: 0;
    background: var(--accent-red); color: #fff;
    border: 0; font-weight: 700; font-size: 14px;
    padding: 10px 20px; border-radius: var(--radius-md);
    cursor: pointer;
}
.rg-exclude-btn:disabled { opacity: 0.6; cursor: default; }
.rg-excluded {
    background: rgba(237, 65, 99, 0.12); color: #ffb3c1;
    border-radius: var(--radius-md);
    padding: 12px 14px; font-size: 14px; font-weight: 600;
}

/* Responsible gambling — self-imposed limits (GLI-33 §2.5) */
.rg-sub-title { font-size: 14px; font-weight: 700; color: var(--text-primary); margin: 0 0 8px; }
.rg-divider { border-top: 1px solid var(--border-color); margin: 18px 0; }
.rg-limit-row { background: var(--bg-tertiary); border-radius: var(--radius-md); padding: 10px 12px; margin-bottom: 10px; }
.rg-limit-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; font-size: 13px; }
.rg-limit-name { font-weight: 600; color: var(--text-primary); }
.rg-limit-usage { color: var(--text-muted); white-space: nowrap; }
.rg-limit-bar { height: 6px; border-radius: 3px; background: rgba(255,255,255,0.08); margin-top: 8px; overflow: hidden; }
.rg-limit-bar-fill { height: 100%; border-radius: 0; background: var(--accent-green-grad); transition: width 0.3s ease; }
.rg-limit-bar-full { background: var(--accent-red); }
.rg-limit-pending { font-size: 12px; color: var(--amber); margin-top: 6px; }
.rg-limit-none { font-size: 13px; color: var(--text-muted); margin-bottom: 10px; }
.rg-limit-form { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 12px; }
.rg-limit-form input { grid-column: 1 / 2; }
.rg-limit-save {
    grid-column: 2 / 3;
    background: var(--accent-green-grad); color: #06330c;
    border: 0; font-weight: 700; font-size: 14px;
    padding: 10px 20px; border-radius: var(--radius-md); cursor: pointer;
}
.rg-limit-save:disabled { opacity: 0.6; cursor: default; }

/* MFA one-time-code input (GLI-33 §2.5e) */
.profile-otp { letter-spacing: 8px; font-weight: 700; font-size: 18px; text-align: center; max-width: 220px; }

/* Operator Reports — admin tooling (GLI-33 §2.9) */
.rpt-note { font-size: 13px; color: var(--text-muted); padding: 8px 0; }
.rpt-meta { font-size: 12px; color: var(--text-muted); margin: 10px 0 4px; }
.rpt-subhead { font-size: 13px; font-weight: 700; color: var(--text-secondary); margin: 14px 0 6px; }
.rpt-leg { font-size: 12px; color: var(--text-secondary); padding: 1px 0; }

/* Ops & Compliance dashboard (#OD) */
.od-controls { margin-bottom: 16px; }
.od-controls .rpt-meta { margin: 0; }   /* align inline with the interval chips */
.od-grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin: 14px 0; }
@media (max-width: 760px) { .od-grid2 { grid-template-columns: 1fr; } }
.od-spark { width: 100%; height: 90px; display: block; }
.od-spark-axis { display: flex; justify-content: space-between; font-size: 11px; color: var(--text-muted); margin-top: 4px; }
/* Player-account record (#OD §2.4) */
.od-profile { padding: 16px 18px; margin-bottom: 14px; }
.od-pf-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.od-pf-name { font-size: 16px; color: var(--text-primary); }
.od-pf-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 2px 18px; }
.od-pf-item { display: flex; justify-content: space-between; gap: 10px; font-size: 13px; padding: 5px 0; border-bottom: 1px solid var(--border-color); }
.od-pf-item > span { color: var(--text-muted); white-space: nowrap; }
.od-pf-item > strong { color: var(--text-secondary); font-weight: 600; text-align: right; }
.rpt-controls { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.rpt-intervals { display: flex; gap: 8px; }
.rpt-chip {
    background: var(--bg-tertiary); color: var(--text-primary);
    border: 0; font-size: 13px; font-weight: 700;
    padding: 8px 16px; border-radius: var(--radius-md); cursor: pointer;
}
.rpt-chip.active { background: var(--accent-green-grad); color: #06330c; }
.rpt-custom { display: flex; gap: 8px; align-items: center; }
.rpt-custom .profile-input { max-width: 150px; }
.rpt-sec-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.rpt-csv {
    background: none; border: 1px solid var(--accent-green); color: var(--accent-green);
    font-size: 12px; font-weight: 700; padding: 6px 12px;
    border-radius: var(--radius-md); cursor: pointer; white-space: nowrap;
}
.rpt-csv:disabled { opacity: 0.5; cursor: default; }
.rpt-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.rpt-table th, .rpt-table td { padding: 8px 10px; text-align: right; white-space: nowrap; }
.rpt-table th:first-child, .rpt-table td:first-child { text-align: left; }
.rpt-table thead th { color: var(--text-muted); font-weight: 600; border-bottom: 1px solid var(--border-color); }
.rpt-table tbody tr:nth-child(even) { background: rgba(255,255,255,0.03); }
.rpt-pos { color: var(--accent-green); font-weight: 700; }
.rpt-neg { color: var(--accent-red); font-weight: 700; }
.rpt-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-bottom: 14px; }
.rpt-kpi {
    background: var(--bg-tertiary); border-radius: var(--radius-md);
    padding: 10px 12px; display: flex; flex-direction: column; gap: 4px;
}
.rpt-kpi span { font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.rpt-kpi strong { font-size: 16px; color: var(--text-primary); }

/* Per-event report — fold-out market breakdown */
.rpt-markets-row td { padding: 0 10px 8px; text-align: left; }
.rpt-markets-row details summary {
    cursor: pointer; font-size: 12px; color: var(--text-muted);
    padding: 2px 0 6px; user-select: none;
}
.rpt-subtable { margin: 4px 0 6px 14px; width: calc(100% - 14px); }
.rpt-subtable thead th { font-size: 12px; }

/* Reports page is a data-dense operator tool — let it breathe wider than the
   640px profile card, and make every table horizontally scrollable inside its
   card so columns can never spill past the border / under the right rail. */
.profile-page.rpt-page { max-width: 1180px; }
.rpt-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.rpt-scroll .rpt-table { min-width: 720px; }
.rpt-warning {
    background: rgba(224, 163, 46, 0.14); color: var(--amber);
    border-left: 3px solid var(--amber); border-radius: 0 var(--radius-md) var(--radius-md) 0;
    padding: 10px 14px; font-size: 13px; font-weight: 600; margin-bottom: 12px;
}

/* ===== Shared admin tables (#AL, #EL, #IN, reports) — .sd-table ===== */
.sd-hint { font-size: 12px; color: var(--text-muted); margin: 0 0 16px; }
.sd-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.sd-table th {
    text-align: left; padding: 8px 10px; font-size: 11px; text-transform: uppercase;
    letter-spacing: .03em; color: var(--text-muted); background: var(--bg-tertiary);
}
.sd-table td { padding: 8px 10px; border-top: 1px solid var(--border-color); color: var(--text-secondary); }
.sd-table td code { font-size: 12px; color: var(--text-muted); }
.sd-empty { color: var(--text-muted); text-align: center; font-style: italic; }

/* ===== Tap-latency readout (perfhud.js, opt-in with ?perf=1) ===== */
#perf-hud {
    position: fixed; top: calc(env(safe-area-inset-top, 0px) + 4px); left: 4px; z-index: 100000;
    min-width: 150px; padding: 6px 8px; pointer-events: none;
    background: rgba(var(--bg-deep-rgb), 0.88); color: var(--text-secondary);
    border: 1px solid var(--border-color); border-radius: var(--radius-sm);
    font: 11px/1.35 ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
}
#perf-hud .ph-head { color: var(--text-muted); margin-bottom: 2px; }
#perf-hud .ph-row b { color: var(--accent-green); font-size: 13px; }
#perf-hud .ph-row.ph-warn b { color: var(--gold); }
#perf-hud .ph-row.ph-bad b { color: var(--accent-red); }
#perf-hud .ph-row span { color: var(--text-muted); }

/* ===== Live Diagnostics (#SD, admin-0) — socketdiag.js, prefix sdm- =====
   A monitoring page: status bar, section tabs, key figures, the tick budget, then one
   panel per table. Colour carries state only: accent = healthy, gold = busy / pinned /
   temporary, red = over budget or a destructive action. */
.profile-page.rpt-page:has(#sd-body) { max-width: 1400px; }
.sdm-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.sdm-bar {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px;
    padding-bottom: 14px; margin-bottom: 4px; border-bottom: 1px solid var(--border-color);
}
.sdm-bar-left, .sdm-bar-right { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.sdm-status {
    display: inline-flex; align-items: center; gap: 8px; padding: 5px 12px; border-radius: 999px;
    font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
}
.sdm-dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.sdm-status-ok   { color: var(--accent-green); background: color-mix(in srgb, var(--accent-green) 13%, transparent); }
.sdm-status-warn { color: var(--gold);         background: color-mix(in srgb, var(--gold) 14%, transparent); }
.sdm-status-over { color: var(--accent-red);   background: color-mix(in srgb, var(--accent-red) 14%, transparent); }
.sdm-status-ok .sdm-dot { animation: sdm-pulse 2s ease-in-out infinite; }
@keyframes sdm-pulse { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .sdm-status-ok .sdm-dot { animation: none; } }
.sdm-updated, .sdm-mono { font-family: ui-monospace, 'SF Mono', Menlo, Consolas, monospace; font-size: 12px; }
.sdm-updated { color: var(--text-muted); }
.sdm-filter input {
    min-height: 40px; width: 220px; max-width: 100%; padding: 0 12px; box-sizing: border-box;
    background: var(--bg-input); color: var(--text-primary); border: 1px solid var(--border-color);
    border-radius: var(--radius-sm); font: inherit; font-size: 13px;
}
.sdm-filter input:focus { outline: none; border-color: var(--accent-green); }
.sdm-btn {
    min-height: 40px; padding: 0 14px; display: inline-flex; align-items: center; gap: 8px;
    background: var(--bg-secondary); color: var(--text-primary); border: 1px solid var(--border-color);
    border-radius: var(--radius-sm); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.sdm-btn:hover { background: var(--bg-hover); }
.sdm-btn[aria-pressed="true"] { color: var(--gold); border-color: var(--gold); }
.sdm-btn-sm { min-height: 32px; padding: 0 12px; font-size: 12px; }
.sdm-tabs { display: flex; flex-wrap: wrap; gap: 2px; margin-bottom: 16px; border-bottom: 1px solid var(--border-subtle); }
.sdm-tabs button {
    padding: 11px 14px; background: none; border: 0; border-bottom: 2px solid transparent;
    color: var(--text-muted); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.sdm-tabs button:hover { color: var(--text-primary); border-bottom-color: var(--accent-green); }
.sdm-tabs button span { color: var(--text-primary); margin-left: 2px; }

#sdm-live { display: flex; flex-direction: column; gap: 14px; }
.sdm-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; }
.sdm-kpi {
    background: var(--bg-secondary); border: 1px solid var(--border-subtle); padding: 14px 16px;
    display: flex; flex-direction: column; gap: 6px; border-radius: var(--radius-md);
}
.sdm-kpi-lbl { font-size: 11px; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: .08em; }
.sdm-kpi-val { display: flex; align-items: baseline; gap: 6px; }
.sdm-kpi-val span { font-size: 28px; font-weight: 800; line-height: 1; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.sdm-kpi-accent .sdm-kpi-val span { color: var(--accent-green); }
.sdm-kpi-val small { font-size: 13px; font-weight: 600; color: var(--text-muted); }
.sdm-kpi-sub { font-size: 12px; color: var(--text-muted); }

.sdm-row { display: flex; flex-wrap: wrap; gap: 14px; }
.sdm-grow3 { flex: 3 1 520px; min-width: 0; }
.sdm-grow2 { flex: 2 1 340px; min-width: 0; }
.sdm-panel { background: var(--bg-secondary); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); scroll-margin-top: 80px; }
.sdm-ph {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 12px;
    padding: 13px 16px; border-bottom: 1px solid var(--border-color);
}
.sdm-ph h3 { margin: 0; font-size: 15px; font-weight: 700; color: var(--text-primary); }
.sdm-ph h3 .sdm-dim { font-weight: 500; }
.sdm-ph-tools { display: inline-flex; align-items: center; gap: 10px; }
.sdm-pb { padding: 18px 16px; display: flex; flex-direction: column; gap: 14px; }
.sdm-dim { color: var(--text-muted); font-size: 12px; }
.sdm-big { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; }
.sdm-big-num { font-size: 40px; font-weight: 800; line-height: 1; font-variant-numeric: tabular-nums; }
.sdm-big-num.sdm-ok { color: var(--text-primary); }
.sdm-big-num.sdm-warn { color: var(--gold); }
.sdm-big-num.sdm-over { color: var(--accent-red); }
.sdm-meter { display: flex; height: 18px; background: var(--bg-input); border: 1px solid var(--border-color); border-radius: var(--radius-sm); overflow: hidden; }
.sdm-meter span { display: block; height: 100%; transition: width .4s ease; }
.sdm-meter-ok { background: var(--accent-green); }
.sdm-meter-warn { background: var(--gold); }
.sdm-meter-over { background: var(--accent-red); }
.sdm-meter-derive { background: var(--accent-teal-light); }
.sdm-legend { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 20px; font-size: 13px; color: var(--text-secondary); }
.sdm-legend span { display: inline-flex; align-items: center; gap: 8px; }
.sdm-legend strong { color: var(--text-primary); }
.sdm-legend-end { margin-left: auto; }
.sdm-sw { display: inline-block; width: 10px; height: 10px; }
.sdm-sw-spare { background: var(--bg-input); border: 1px solid var(--border-color); box-sizing: border-box; }
.sdm-dl { margin: 0; padding: 4px 16px 10px; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 16px; }
.sdm-dl dt, .sdm-dl dd { padding: 10px 0; border-bottom: 1px solid var(--border-subtle); margin: 0; }
.sdm-dl dt:last-of-type, .sdm-dl dd:last-of-type { border-bottom: 0; }
.sdm-dl dt { color: var(--text-muted); }
.sdm-dl dd { text-align: right; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.sdm-tag {
    display: inline-block; padding: 2px 8px; font-size: 11px; font-weight: 700; letter-spacing: .05em;
    border-radius: var(--radius-sm); color: var(--text-secondary); background: var(--bg-tertiary);
}
.sdm-tag-ok { color: var(--accent-green); background: color-mix(in srgb, var(--accent-green) 13%, transparent); }
.sdm-tag-warn { color: var(--gold); background: color-mix(in srgb, var(--gold) 14%, transparent); }

.sdm-scroll { overflow-x: auto; }
.sdm-table { width: 100%; border-collapse: collapse; font-size: 13px; min-width: 760px; }
.sdm-table th {
    text-align: left; padding: 10px 16px; font-size: 11px; font-weight: 700; color: var(--text-muted);
    text-transform: uppercase; letter-spacing: .06em; white-space: nowrap;
}
.sdm-table td { padding: 11px 16px; border-top: 1px solid var(--border-color); color: var(--text-secondary); vertical-align: top; font-variant-numeric: tabular-nums; }
.sdm-table tbody tr:hover td { background: var(--live-row-hover); }
.sdm-table-matches { min-width: 940px; }
.sdm-strong { color: var(--text-primary); font-weight: 700; }
.sdm-sub { margin-top: 3px; font-size: 12px; color: var(--text-muted); }
.sdm-wide { width: 40%; }
.sdm-table td.sdm-empty { padding: 26px 16px; color: var(--text-muted); text-align: center; font-style: italic; }
.sdm-stale td { color: var(--text-muted); }
.sdm-note { display: block; margin-top: 2px; font-size: 11px; color: var(--gold); }
.sdm-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.sdm-chip {
    display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px; font-size: 12px; font-weight: 600;
    color: var(--text-primary); background: var(--bg-tertiary); border: 1px solid var(--border-color);
    border-radius: 999px; white-space: nowrap;
}
.sdm-chip small { font-size: 12px; font-weight: 500; color: var(--text-muted); }
.sdm-chip-staff {
    color: var(--accent-green); background: color-mix(in srgb, var(--accent-green) 10%, transparent);
    border-color: color-mix(in srgb, var(--accent-green) 35%, transparent);
}
.sdm-chip-guest { background: transparent; border-style: dashed; color: var(--text-secondary); }
.sdm-actions { white-space: nowrap; text-align: right; }
.sdm-act {
    min-height: 32px; padding: 0 10px; margin-left: 6px; display: inline-flex; align-items: center; gap: 6px;
    background: var(--bg-tertiary); color: var(--text-primary); border: 1px solid var(--border-color);
    border-radius: var(--radius-sm); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
}
.sdm-act:hover { background: var(--bg-hover); }
.sdm-act:disabled { opacity: .5; cursor: progress; }
.sdm-act-danger { color: var(--accent-red-soft); border-color: color-mix(in srgb, var(--accent-red) 45%, transparent); }
.sdm-act-danger:hover { background: color-mix(in srgb, var(--accent-red) 16%, transparent); }
@media (max-width: 600px) {
    .sdm-filter, .sdm-filter input { width: 100%; }
    .sdm-bar-right { width: 100%; }
    .sdm-legend-end { margin-left: 0; }
}

/* ===== Audit log (#AL, admin-0) — auditlog.js ===== */
.au-amt { white-space: nowrap; text-align: right; font-variant-numeric: tabular-nums; }

/* AG Grid (admin pages) — tint the Quartz theme to match the app's dark palette. */
.ag-theme-quartz.admin-grid {
    width: 100%;
    color-scheme: dark;
    --ag-background-color: var(--bg-secondary, var(--bg-secondary));
    --ag-foreground-color: var(--text-primary, #ffffff);
    --ag-header-background-color: var(--bg-primary, var(--bg-deep));
    --ag-header-foreground-color: var(--text-secondary, #b1bec9);
    --ag-border-color: var(--border-color, var(--border-color));
    --ag-row-border-color: var(--border-color, var(--border-color));
    --ag-row-hover-color: rgba(255, 255, 255, 0.045);
    --ag-odd-row-background-color: rgba(255, 255, 255, 0.02);
    --ag-control-panel-background-color: var(--bg-primary, var(--bg-deep));
    --ag-input-background-color: var(--bg-primary, var(--bg-deep));
    --ag-input-border-color: var(--border-color, var(--border-color));
    --ag-selected-row-background-color: rgba(0, 231, 1, 0.12);
    --ag-accent-color: var(--accent-green, #00e701);
    --ag-range-selection-border-color: var(--accent-green, #00e701);
    --ag-font-family: inherit;
    --ag-font-size: 13px;
    --ag-grid-size: 5px;
    --ag-borders: solid 1px;
}
.au-filters { display: flex; flex-wrap: wrap; gap: 12px; align-items: flex-end; margin-bottom: 14px; }
.au-filters label { display: flex; flex-direction: column; gap: 4px; font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: .03em; }
.au-filters input, .au-filters select {
    background: var(--bg-tertiary); border: 1px solid var(--border-color); color: var(--text-primary);
    border-radius: var(--radius-md); padding: 7px 10px; font-size: 13px; font-family: inherit;
}
.au-btn {
    background: var(--accent-green-grad); color: var(--bg-deep); border: 0; border-radius: var(--radius-md);
    padding: 9px 16px; font-weight: 700; font-size: 13px; cursor: pointer;
}
.au-btn-ghost { background: var(--bg-tertiary); color: var(--text-primary); border: 1px solid var(--border-color); }
.au-btn:hover { filter: brightness(1.05); }

/* ===== KYC review (#KR, admin-0) — kycreview.js ===== */
.au-btn-danger { background: var(--accent-red); color: #fff; }
.kr-card { background: var(--bg-tertiary); border: 1px solid var(--border-color); border-radius: var(--radius-md); padding: 14px 16px; margin-bottom: 12px; }
.kr-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; }
.kr-name { font-size: 15px; font-weight: 700; color: var(--text-primary); }
.kr-id { font-size: 12px; color: var(--text-muted); }
.kr-badge { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; padding: 3px 9px; border-radius: 999px; }
.kr-badge.kr-ok { background: rgba(0,231,1,.14); color: var(--accent-green); }
.kr-badge.kr-warn { background: rgba(237,65,99,.14); color: var(--accent-red); }
.kr-meta { font-size: 12px; color: var(--text-muted); margin: 6px 0 10px; }
.kr-docs { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
.kr-doc { display: flex; align-items: center; gap: 10px; background: var(--bg-secondary); border-radius: var(--radius-md); padding: 7px 10px; }
.kr-doc-type { font-size: 11px; font-weight: 700; text-transform: uppercase; color: var(--text-muted); min-width: 64px; }
.kr-doc-name { flex: 1; min-width: 0; font-size: 13px; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kr-doc-empty { font-size: 12px; color: var(--text-muted); font-style: italic; }
.kr-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.kr-note { flex: 1; min-width: 140px; background: var(--bg-secondary); border: 1px solid var(--border-color); color: var(--text-primary); border-radius: var(--radius-md); padding: 8px 10px; font-size: 13px; font-family: inherit; }
.kr-reviewed { font-size: 12px; color: var(--text-muted); }

/* Exclusion list (#EL) — reuses .au-filters / .au-btn / .sd-table. */
.el-table td { vertical-align: top; }
.el-type { display: inline-block; font-size: 11px; font-weight: 700; text-transform: uppercase; color: var(--text-muted); background: var(--bg-secondary); border-radius: var(--radius-sm); padding: 2px 6px; }
.el-dim { font-size: 11px; color: var(--text-muted); }
.el-removed { opacity: 0.55; }
.el-removed .el-type { text-decoration: line-through; }

/* Wagering kill-switch (#WS) — single status card + toggle. */
.ws-card { border: 1px solid var(--border-color); border-radius: var(--radius-lg, 12px); padding: 22px; max-width: 540px; background: var(--bg-secondary); }
.ws-card.ws-on { border-color: var(--accent-red, #ff4d4f); background: rgba(255,77,79,0.07); }
.ws-state { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.ws-dot { width: 12px; height: 12px; border-radius: 50%; background: var(--accent-green, var(--accent-green)); box-shadow: 0 0 0 3px rgba(0,231,1,0.15); flex: none; }
.ws-on .ws-dot { background: var(--accent-red, #ff4d4f); box-shadow: 0 0 0 3px rgba(255,77,79,0.18); }
.ws-label { font-size: 15px; font-weight: 700; color: var(--text-primary); letter-spacing: 0.2px; }
.ws-help { font-size: 13px; color: var(--text-muted); margin: 0 0 18px; line-height: 1.55; }

/* Control-program integrity (#IN) — status card + per-file hash table. */
.in-card { border: 1px solid var(--border-color); border-radius: var(--radius-lg, 12px); padding: 20px; background: var(--bg-secondary); margin-bottom: 16px; }
.in-card.in-ok   { border-color: var(--accent-green, var(--accent-green)); background: rgba(0,231,1,0.06); }
.in-card.in-bad  { border-color: var(--accent-red, #ff4d4f); background: rgba(255,77,79,0.07); }
.in-card.in-warn { border-color: #f0a020; background: rgba(240,160,32,0.07); }
.in-state { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.in-dot { width: 12px; height: 12px; border-radius: 50%; flex: none; background: var(--text-muted); }
.in-ok   .in-dot { background: var(--accent-green, var(--accent-green)); box-shadow: 0 0 0 3px rgba(0,231,1,0.15); }
.in-bad  .in-dot { background: var(--accent-red, #ff4d4f); box-shadow: 0 0 0 3px rgba(255,77,79,0.18); }
.in-warn .in-dot { background: #f0a020; box-shadow: 0 0 0 3px rgba(240,160,32,0.18); }
.in-label { font-size: 15px; font-weight: 700; color: var(--text-primary); letter-spacing: 0.2px; }
.in-meta { display: grid; gap: 6px; margin-bottom: 14px; }
.in-meta > div { display: flex; gap: 8px; flex-wrap: wrap; font-size: 13px; }
.in-k { color: var(--text-muted); min-width: 130px; }
.in-v { color: var(--text-primary); }
.in-v em { color: var(--text-muted); font-style: normal; }
.in-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 12px; }
.in-help { font-size: 12.5px; color: var(--text-muted); margin: 0; line-height: 1.55; }
.in-help code { background: var(--bg-tertiary); padding: 1px 5px; border-radius: 0; font-size: 12px; }
.in-table-wrap { max-height: 60vh; overflow: auto; }
.in-table { width: 100%; }
.in-table .in-file { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; word-break: break-all; }
.in-table .in-hash { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; color: var(--text-muted); }
.in-tag { display: inline-block; font-size: 10px; font-weight: 700; text-transform: uppercase; border-radius: var(--radius-sm, 4px); padding: 2px 7px; letter-spacing: 0.3px; }
.in-tag-ok { color: var(--accent-green, var(--accent-green)); background: rgba(0,231,1,0.12); }
.in-tag-modified, .in-tag-missing, .in-tag-added { color: var(--accent-red, #ff4d4f); background: rgba(255,77,79,0.12); }
.in-tag-unbaselined { color: #f0a020; background: rgba(240,160,32,0.14); }
.in-row-bad td { background: rgba(255,77,79,0.05); }
.in-row-warn td { background: rgba(240,160,32,0.05); }

/* ==========================================
   USER MENU — mobile-layout scroll fix
   The bottom-nav "mobile layout" appears at <=900px, but the earlier docked
   dropdown rule only kicked in at <=600px — so 601–900px wide devices (large
   phones, small tablets) got the desktop dropdown and its long admin list ran
   off the bottom of the screen with no way to scroll to "Sign Out".
   This rule (last in the file, so it wins the cascade) docks the menu to the
   right edge, caps it to the VISIBLE viewport via dvh, and scrolls the overflow
   across the whole mobile range. Every item stays reachable.
   ========================================== */
@media (max-width: 900px) {
    .user-dropdown {
        position: fixed;
        top: var(--header-height, 60px);
        right: 8px;
        left: auto;
        width: min(92vw, 360px);
        max-height: calc(100dvh - var(--header-height, 60px) - 80px);
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
        border-radius: 0;
        padding-bottom: env(safe-area-inset-bottom, 0);
    }

    /* Lock the page behind the open menu so it doesn't scroll along with the
       fixed dropdown. Toggled by JS (initUserMenu) via the body class. Scoped
       to the mobile range — on desktop the dropdown is short/anchored and a
       body lock would cause a scrollbar-width layout jump. */
    body.user-menu-open {
        overflow: hidden;
    }

    /* The dropdown is `position: fixed` but still lives INSIDE .top-header, which is a
       stacking context at z-index 100 — so it can never paint above anything OUTSIDE the
       header that has a higher z-index. On the Sports/Browse page that is
       `.browse-search-wrapper` (z-index: 202), which is why the search bar cut across the
       open menu there. Lift the whole header while the menu is open: 250 clears the search
       bar but stays under .bottom-nav (300), so the nav is still tappable — matching the
       intent of the bottom-nav rule. Reverts the moment the menu closes. */
    body.user-menu-open .top-header {
        z-index: 250;
    }
}

/* =====================================================================
   Operator dashboard tiles — shared by #AL (audit), #RT (reports), #EL
   (exclusion). Big-number KPI grid + light chart widgets that sit at the
   top of the page; the existing filter bar + tables render underneath.
   Sticks to the app's dark theme (no full gradients) but uses per-tile
   accent stripes so a row of 6 reads at a glance.
   ===================================================================== */
.dash-page-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
    flex-wrap: wrap;
}
.dash-page-head h2 {
    margin: 0;
    font-size: 22px;
    font-weight: 800;
    color: var(--text-primary);
    letter-spacing: -0.01em;
}
.dash-page-head .dash-page-sub {
    font-size: 12px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.dash-kpis {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 12px;
    margin: 0 0 18px;
}
.dash-kpi {
    position: relative;
    background: var(--bg-tertiary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg, 14px);
    padding: 14px 16px 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    overflow: hidden;
    transition: transform 0.12s ease, border-color 0.12s ease;
}
.dash-kpi:hover {
    transform: translateY(-1px);
    border-color: rgba(255, 255, 255, 0.14);
}
.dash-kpi::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 3px;
    background: var(--dash-accent, var(--accent-green));
    opacity: 0.85;
}
.dash-kpi-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: 11px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-weight: 600;
}
.dash-kpi-ico {
    width: 22px;
    height: 22px;
    border-radius: 0;
    background: rgba(255, 255, 255, 0.05);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--dash-accent, var(--accent-green));
}
.dash-kpi-value {
    font-size: 18px;
    font-weight: 800;
    color: var(--text-primary);
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}
.dash-kpi-sub {
    font-size: 12px;
    color: var(--text-muted);
    display: flex;
    align-items: center;
    gap: 6px;
}
.dash-kpi-sub.dash-pos { color: var(--accent-green); }
.dash-kpi-sub.dash-neg { color: var(--accent-red); }
/* Bare .dash-pos / .dash-neg had no colour of their own — only the compound
   .dash-kpi-sub form did — so every other caller (finance difference columns,
   the GGR figure in reports.js) rendered in plain body text. */
.dash-pos { color: var(--accent-green); }
.dash-neg { color: var(--accent-red); }
.dash-zero { color: var(--text-muted); }
/* `.mgt-table td { color: var(--text-primary) }` is more specific than a bare
   .dash-* class, so inside a table the difference column rendered plain white.
   Same weight needed here as for .mgt-r and the tree indent. */
.mgt-table td.dash-pos  { color: var(--accent-green); }
.mgt-table td.dash-neg  { color: var(--accent-red); }
.mgt-table td.dash-zero { color: var(--text-muted); }

/* Accent variants — borrowed colour ROLES from the photo (one tile per
   colour for at-a-glance differentiation) but kept inside dark surfaces
   so they sit naturally in the existing theme. */
.dash-kpi--green  { --dash-accent: #16c784; }
.dash-kpi--blue   { --dash-accent: #2d8cf0; }
.dash-kpi--cyan   { --dash-accent: #29b6f6; }
.dash-kpi--violet { --dash-accent: #8a6cff; }
.dash-kpi--amber  { --dash-accent: #f0a920; }
.dash-kpi--red    { --dash-accent: var(--accent-red); }
/* NGR sits beside GGR on the reports page — a distinct hue so the two aren't
   read as the same figure, but kept in the green family since it is the same
   kind of measure (revenue), just net of the operator's own costs. */
.dash-kpi--teal   { --dash-accent: #14b8a6; }

/* Horizontal-bar chart widget — used for "events by type", "exclusions
   by match type", etc. Cheap to render, no chart library needed. */
.dash-panel {
    background: var(--bg-tertiary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-lg, 14px);
    padding: 14px 16px;
    margin-bottom: 18px;
}
.dash-panel-title {
    font-size: 13px;
    font-weight: 700;
    color: var(--text-primary);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin: 0 0 12px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}
.dash-panel-title .dash-panel-sub {
    font-size: 11px;
    font-weight: 500;
    color: var(--text-muted);
    text-transform: none;
    letter-spacing: 0;
}
.dash-bars {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.dash-bar-row {
    display: grid;
    grid-template-columns: minmax(120px, 28%) 1fr 56px;
    align-items: center;
    gap: 10px;
    font-size: 12px;
}
.dash-bar-label {
    color: var(--text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.dash-bar-track {
    height: 8px;
    background: rgba(255, 255, 255, 0.05);
    border-radius: 999px;
    overflow: hidden;
}
.dash-bar-fill {
    height: 100%;
    background: var(--dash-accent, var(--accent-green));
    border-radius: 999px;
    transition: width 0.3s ease;
}
.dash-bar-count {
    text-align: right;
    color: var(--text-primary);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* Tighter spacing on small screens — KPI tiles drop to 2-up. */
@media (max-width: 700px) {
    .dash-kpis { grid-template-columns: repeat(2, 1fr); gap: 10px; }
    .dash-kpi { padding: 12px 12px 14px; }
    .dash-kpi-value { font-size: 22px; }
    .dash-bar-row { grid-template-columns: minmax(90px, 36%) 1fr 44px; }
}

/* ==========================================
   GUEST BROWSING — header actions + auth-required modal
   ========================================== */
/* Log in + Sign up read as one unit in a recessed track, matching the product
   toggle on the other side of the header — the two are the same kind of thing
   (a small group of header controls) and were drawn in two different idioms.
   Grouping also removes the outlined-button-next-to-filled-button pattern, where
   the outline competes with the primary action it is supposed to defer to. */
.guest-actions {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 4px;
    border-radius: 999px;
    /* Same surface as .header-left — the two floating groups must be the same
       material, or the header reads as two different components that happen to
       share a row. */
    background: var(--bg-secondary);
}

.guest-btn {
    position: relative;
    padding: 8px 16px;
    border-radius: 999px;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    transition: opacity 0.15s, background-color 0.15s, color 0.15s;
    white-space: nowrap;
}

/* Hyr / Regjistrohu draw 31px tall; the tap area reaches 45px (the touch-target
   guideline) without changing the pill. Up and down only: they sit side by side. */
.guest-btn::after {
    content: '';
    position: absolute;
    inset: -7px 0;
}

/* Secondary action: no border. Inside the shared track the grouping already
   frames it, so the outline was a second frame around the first. */
.guest-btn-login {
    background: transparent;
    color: var(--text-secondary);
    border: none;
}

.guest-btn-login:hover {
    color: var(--text-primary);
    background: rgba(255, 255, 255, 0.07);
}

.guest-btn-register {
    background: var(--accent-green-grad);
    color: var(--bg-deep);
    border: none;
    border-radius: 999px;
}

.guest-btn-register:hover {
    opacity: 0.9;
}

@media (max-width: 480px) {
    .guest-btn { padding: 8px 12px; font-size: 12px; }
}

/* 375px and below: the last 7px that stop Sign-in overlapping the Kazino button.
   See the note in the `max-width: 400px` header block for the width arithmetic —
   the pair lives here rather than there because the 480px rule above sets the same
   property at the same specificity and would otherwise win on source order. */
@media (max-width: 400px) {
    .guest-btn { padding: 8px 9px; }
}

/* Continue-browsing link on the login card */
.login-browse-footer {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid rgba(255, 255, 255, 0.07);
}

/* ---- Auth-required modal ---- */
.auth-modal {
    position: fixed;
    inset: 0;
    z-index: 1100;   /* above the user menu (z 110) and exchange modal (1000) */
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}

.auth-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(var(--bg-deep-rgb), 0.72);
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}

.auth-modal-card {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 400px;
    padding: 36px 28px 28px;
    text-align: center;
    border-radius: 0;
    border: 1px solid rgba(255, 255, 255, 0.09);
    background:
        radial-gradient(120% 90% at 50% 0%, rgba(0, 231, 1, 0.10) 0%, rgba(0, 231, 1, 0) 55%),
        linear-gradient(160deg, var(--bg-secondary) 0%, var(--bg-secondary) 100%);
    box-shadow: 0 28px 70px rgba(0, 0, 0, 0.55);
    animation: exchangeModalIn 0.22s ease;   /* reuse the modal entrance */
}

.auth-modal-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: linear-gradient(90deg, transparent, var(--accent-green) 50%, transparent);
}

.auth-modal-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.1);
    color: var(--text-secondary);
    cursor: pointer;
    transition: background 0.15s, color 0.15s;
}

.auth-modal-close:hover {
    background: rgba(255, 255, 255, 0.12);
    color: var(--text-primary);
}

.auth-modal-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 64px;
    height: 64px;
    margin: 0 auto 16px;
    border-radius: 50%;
    color: var(--accent-green);
    background: rgba(0, 231, 1, 0.1);
    border: 1px solid rgba(0, 231, 1, 0.25);
}

.auth-modal-title {
    font-size: 19px;
    font-weight: 800;
    color: var(--text-primary);
    margin: 0 0 8px;
}

.auth-modal-msg {
    font-size: 13px;
    line-height: 1.55;
    color: var(--text-muted);
    margin: 0 0 22px;
}

.auth-modal-actions {
    display: flex;
    flex-direction: column;
    gap: 10px;
}

/* The same pair inside My Bets' guest prompt — narrower than the modal, centred. */
.mybets-empty .auth-modal-actions {
    width: 100%;
    max-width: 260px;
    margin: 14px auto 0;
}

.auth-modal-login {
    width: 100%;
    padding: 13px;
    background: var(--accent-green-grad);
    color: var(--bg-deep);
    border: none;
    border-radius: var(--radius-md);
    font-size: 15px;
    font-weight: 700;
    cursor: pointer;
    transition: opacity 0.15s;
}

.auth-modal-login:hover { opacity: 0.9; }

.auth-modal-register {
    width: 100%;
    padding: 12px;
    background: transparent;
    color: var(--text-secondary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: border-color 0.15s, color 0.15s;
}

.auth-modal-register:hover {
    color: var(--text-primary);
    border-color: var(--accent-green);
}

/* ==========================================
   USER MENU — language flag row (header toggle removed)
   ========================================== */
.dropdown-lang-row {
    display: flex;
    justify-content: center;
    gap: 6px;
    padding: 10px 14px;
}

.dropdown-lang-flag {
    width: 38px;
    height: 30px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-input);
    border: 2px solid transparent;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s;
}

.dropdown-lang-flag:hover {
    background: var(--bg-hover);
}

.dropdown-lang-flag.active {
    border-color: var(--accent-green-neon);
}

.dropdown-lang-flag img {
    width: 20px;
    height: 20px;
    display: block;
}

/* ============================================================================
   Branded display face (Futura PT Cond) — applied ONLY here, per request:
   the jackpot 777 branding + the Bet Boost team names. The general UI stays on
   the default font (--font-display). Placed last so it wins over the earlier
   var(--font-display) declarations on the jackpot elements. Every selector here
   is already font-weight >=700, which the bold-only Futura cut requires.
   ============================================================================ */
.bs-jp-jack,
.bs-jp-tier,
.bs-jp-win-title,
.bs-jp-win-amount,
.bs-jp-win-collect,
.bs-jp-reveal-label b,
.bs-stake-jp-badge,
.bs-stake-jp-add,
.bb-teams-name {
    font-family: var(--font-brand);
}

/* ==========================================
   REGISTER — iOS date input (Datëlindja) normalization
   iOS WebKit gives <input type="date"> its own native pill (light background,
   centered value, intrinsic sizing) and ignores the shared field styling until
   appearance is stripped. Flatten it to match the other .reg-field inputs.
   NOTE: kept at the END of the file — a concurrent editing session twice
   reverted this rule when it lived inside the .reg-field block around line 960.
   ========================================== */
.reg-field input[type="date"] {
    -webkit-appearance: none;
    appearance: none;
    display: flex;              /* iOS: vertically centers the value text */
    align-items: center;
    /* iOS collapses the height when empty (date inputs have no placeholder) —
       pin it to the same ~45px the text inputs get from padding + font. */
    min-height: 45px;
    width: 100%;
    background: var(--bg-input);
    color: var(--text-primary);
    font-size: 14px;
    color-scheme: dark;         /* dark native wheel/calendar overlay */
    text-align: left;
}

/* The value itself is a shadow pseudo-element on iOS — centered by default. */
.reg-field input[type="date"]::-webkit-date-and-time-value {
    text-align: left;
    margin: 0;
    font-size: 14px;
}

/* ==========================================
   PULL-TO-REFRESH (standalone home-screen app only — js/pullrefresh.js)
   ========================================== */
#ptr-indicator {
    position: fixed;
    top: calc(var(--header-height) + 6px);
    left: 50%;
    transform: translateX(-50%) translateY(-56px);
    z-index: 1200;
    opacity: 0;
    transition: transform 0.15s ease-out, opacity 0.15s;
    pointer-events: none;
}

#ptr-indicator.ptr-visible {
    opacity: 1;
    transform: translateX(-50%) translateY(calc(var(--ptr-pull, 0px) - 48px));
}

.ptr-disc {
    width: 38px;
    height: 38px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.45);
    color: var(--text-muted);
    transition: color 0.15s, transform 0.15s;
}

#ptr-indicator.ptr-armed .ptr-disc {
    color: var(--accent-green);
    transform: rotate(180deg);
}

#ptr-indicator.ptr-loading .ptr-disc {
    color: var(--accent-green);
    animation: ptr-spin 0.7s linear infinite;
}

@keyframes ptr-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

/* ==========================================
   BETSLIP — clear-all relocated into the mobile overlay header
   The body render still emits its own .bs-header-row (used by the desktop
   panel); inside the overlay we hide it so the header copy is the only one.
   ========================================== */
.betslip-overlay-body .bs-header-row {
    display: none;
}

.bs-clear-all-header {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-right: 4px;
    padding: 7px 12px;
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    color: var(--text-secondary);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: color 0.15s, border-color 0.15s;
}

.bs-clear-all-header:hover {
    color: var(--text-primary);
    border-color: var(--accent-red);
}

.bs-clear-all-header svg {
    flex-shrink: 0;
}

/* ==========================================
   BETSLIP OVERLAY — animated open / close (mobile bottom sheet)
   `display` can't be transitioned, so App._showBetslipOverlay/_hideBetslipOverlay
   toggle these classes around it: the panel slides up from translateY(100%) and
   the backdrop fades. `bs-overlay-anim` is only present DURING the animation, so
   no stray transform is left on the panel afterwards (a lingering transform would
   make it the containing block for any fixed-position descendant).
   ========================================== */
.betslip-overlay.bs-overlay-anim {
    opacity: 0;
    transition: opacity 300ms ease-in-out;
}

.betslip-overlay.bs-overlay-anim.bs-overlay-open {
    opacity: 1;
}

/* The panel already carries `transition: all 300ms ease-in-out`, so transform animates. */
.betslip-overlay.bs-overlay-anim .betslip-overlay-panel {
    transform: translateY(100%);
}

.betslip-overlay.bs-overlay-anim.bs-overlay-open .betslip-overlay-panel {
    transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
    .betslip-overlay.bs-overlay-anim,
    .betslip-overlay.bs-overlay-anim .betslip-overlay-panel {
        transition: none;
    }
}

/* Reports — player lookup suggestion chips (no exact username match) */
.rpt-sugg {
    margin: 4px 4px 0 0;
}

.rpt-sugg-id {
    opacity: 0.6;
    font-size: 11px;
}

/* ==========================================
   LIVE SUMMARY — period breakdown (basketball quarters / tennis sets)
   Football keeps its event timeline; every other sport now gets this in the
   Summary tab. Real <table> markup, so the numbers read correctly to a screen
   reader while the bar is purely decorative (aria-hidden in the JS).
   ========================================== */
.lmst-pb {
    width: 100%;
    border-collapse: collapse;
    font-variant-numeric: tabular-nums;   /* live values must not jitter on update */
}

.lmst-pb-cap {
    caption-side: top;
    text-align: left;
    padding: 2px 2px 10px;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.lmst-pb thead th {
    padding: 0 6px 8px;
    font-size: 11px;
    font-weight: 600;
    color: var(--text-muted);
    border-bottom: 1px solid var(--border-color);
}

.lmst-pb-team {
    max-width: 90px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Visually-hidden "vs" — keeps the header row meaningful without adding noise. */
.lmst-pb-sr {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

.lmst-pb-row > * {
    padding: 7px 6px;
}

.lmst-pb-lbl {
    width: 46px;
    text-align: left;
    font-size: 12px;
    font-weight: 700;
    color: var(--text-secondary);
}

.lmst-pb-val {
    width: 34px;
    font-size: 14px;
    font-weight: 700;
    color: var(--text-secondary);
    text-align: center;
}

/* The side that won the period — the whole point of the panel at a glance. */
.lmst-pb-val.is-lead {
    color: var(--accent-green);
}

.lmst-pb-barcell {
    width: auto;
}

.lmst-pb-bar {
    display: flex;
    height: 6px;
    border-radius: 999px;
    overflow: hidden;
    background: rgba(255, 255, 255, 0.06);
}

.lmst-pb-bar-h,
.lmst-pb-bar-a {
    display: block;
    height: 100%;
    /* Explicit property (never `transition: all`) so only width animates. */
    transition: width 300ms ease-in-out;
}

.lmst-pb-bar-h { background: var(--accent-green-grad); }
.lmst-pb-bar-a { background: rgba(255, 255, 255, 0.28); }

.lmst-pb-total > * {
    padding-top: 10px;
    border-top: 1px solid var(--border-color);
}

.lmst-pb-total .lmst-pb-val {
    font-size: 16px;
    color: var(--text-primary);
}

.lmst-pb-total .lmst-pb-val.is-lead {
    color: var(--accent-green);
}

.lmst-pb-empty {
    padding: 18px 4px;
    text-align: center;
    font-size: 13px;
    color: var(--text-muted);
}

@media (prefers-reduced-motion: reduce) {
    .lmst-pb-bar-h,
    .lmst-pb-bar-a {
        transition: none;
    }
}

/* ---- Cricket variant of the period-breakdown table + live chase tiles ---- */
.lmst-pb-lbl-wide {
    width: auto;
    max-width: 150px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--text-primary);
}

/* Batting-side marker next to the team name. */
.lmst-ck-bat {
    color: var(--accent-green);
    font-size: 9px;
    vertical-align: middle;
}

.lmst-pb-ck .lmst-pb-val {
    width: 62px;
    color: var(--text-primary);
}

/* Cricket rows carry full team names, and `max-width` on a <th> is ignored in
   auto table layout — the name column grew to ~280px and squeezed the run-share
   bar down to ~20px. Pin the bar column so the comparison stays readable. */
.lmst-pb-ck .lmst-pb-barcell {
    width: 36%;
    min-width: 84px;
}

.lmst-pb-tiles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(64px, 1fr));
    gap: 8px;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--border-color);
}

.lmst-pb-tile {
    text-align: center;
    padding: 8px 4px;
    border-radius: var(--radius-sm);
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.07);
}

.lmst-pb-tile-val {
    font-size: 16px;
    font-weight: 800;
    color: var(--accent-green);
    font-variant-numeric: tabular-nums;
}

.lmst-pb-tile-lbl {
    margin-top: 2px;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-muted);
}

/* ============================================================
   COLLAPSIBLE LEAGUE GROUPS  (js/leaguecollapse.js)
   Shared by the prematch lists (.league-group) and the live overview
   (.live-league-group). The header is the toggle; the group gets .collapsed
   and the body rows are hidden by the rules below.
   ============================================================ */

/* Header reads as interactive. */
.league-group-header,
.live-league-header {
    cursor: pointer;
    user-select: none;
}
/* background-COLOR, never the `background` shorthand. .live-league-header paints
   its per-sport tint as a background-IMAGE (the --lg-tint gradient), and the
   shorthand resets background-image to `none` — so hovering a football header did
   not lighten it, it stripped the green off it and left flat --bg-tertiary. Worse,
   --bg-hover holds the SAME value as --bg-tertiary, so wiping the tint was the
   rule's only visible effect.
   Gated on (hover: hover) because iOS latches :hover after a tap and keeps it until
   you touch something else — on a phone this read as "the league header changes
   colour when I press it, and stays that way". Touch devices now get no hover
   state at all, which is correct: the header is a toggle and the chevron plus the
   collapse animation already confirm the tap. */
@media (hover: hover) {
    .league-group-header:hover,
    .live-league-header:hover {
        background-color: color-mix(in srgb, var(--bg-tertiary, var(--bg-tertiary)) 90%, #ffffff);
    }
}

/* Keyboard focus (the headers get role=button + tabindex from JS). */
.league-group-header:focus-visible,
.live-league-header:focus-visible {
    outline: 2px solid var(--accent-odds, #7ee06b);
    outline-offset: -2px;
}

/* Chevron affordance. Placed on the LEFT cluster of each header — putting it
   at the trailing edge of the live header would sit inside the 1/X/2 + O/U
   column strip and push those headers out of alignment with the rows below.
   NOTE for the live row it hangs off .live-league-header-left, NOT
   .live-league-name: that span is `overflow:hidden` + ellipsis, which CLIPS a
   ::after away entirely as soon as the league name is long (i.e. usually). */
.league-group-title::before,
.live-league-header-left::after {
    content: '';
    flex: 0 0 auto;
    width: 6px;
    height: 6px;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    opacity: 0.65;
    transform: rotate(45deg);          /* pointing DOWN = expanded */
    transition: transform 0.18s ease;
}
.league-group-title::before      { margin-right: 2px; }
.live-league-header-left::after  { margin-left: 2px; }

/* Collapsed: chevron points RIGHT and the body is hidden. */
.league-group.collapsed .league-group-title::before,
.live-league-group.collapsed .live-league-header-left::after {
    transform: rotate(-45deg);
}

.league-group.collapsed .league-date-group { display: none; }
.live-league-group.collapsed .live-match-row { display: none; }

/* With no rows on screen the 1/X/2 + O/U column headers are meaningless — and
   worse, they imply content that isn't there. Hide them while collapsed. */
.live-league-group.collapsed .live-league-odds-header,
.live-league-group.collapsed .live-league-ou-header,
.live-league-group.collapsed .live-league-cou-header { display: none; }

/* A collapsed live group is just its header — drop the thick divider that
   normally separates the header from its rows. */
.live-league-group.collapsed .live-league-header { border-bottom-width: 1px; }

/* Collapse/expand-all button — lives in the sport-detail header (prematch)
   and the live top bar. Mirrors the .live-view-btn pill styling. */
.lc-toggle-all {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    flex-shrink: 0;
    height: 34px;
    padding: 0 10px;
    background: var(--bg-tertiary);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm, 6px);
    color: var(--text-secondary);
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease;
}
.lc-toggle-all:hover { color: var(--text-primary); background: var(--bg-hover, var(--bg-lightg)); }
.lc-toggle-all svg { flex-shrink: 0; transition: transform 0.18s ease; }
/* Flip the icon when everything is collapsed, so the button shows what it
   will DO next (expand) rather than the current state. Keyed off the DATA
   ATTRIBUTE, not the .lc-toggle-all class — the button is styled differently
   per page and a class-only rule silently missed the live one. */
[data-lc-toggle-all].is-collapsed svg { transform: scaleY(-1); }

/* Icon-only variant — the live toolbar, where it sits beside the (fixed 2x2,
   80px tall) .live-view-toggle pill rather than inside it. */
.lc-toggle-icon {
    width: 38px;
    height: 80px;
    padding: 0;
    align-self: center;
    background: var(--bg-secondary);
}

@media (max-width: 640px) {
    .lc-toggle-all .lc-toggle-text { display: none; }   /* icon-only on phones */
    .lc-toggle-all { padding: 0 8px; }
}

/* "Go to this league" — replaces the old "View All" text link in the league
   group header. An arrow-with-shaft (not a bare chevron) so it reads as
   NAVIGATION and stays visually distinct from the hairline collapse chevron on
   the other side of the same header. Sits in a chip that lifts on hover. */
.league-go {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.06);
    color: var(--text-secondary);
    transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease;
}
.league-go:hover {
    background: var(--accent-green, #4caf50);
    color: var(--bg-secondary);
    transform: translateX(2px);
}
.league-go:focus-visible {
    outline: 2px solid var(--accent-odds, #7ee06b);
    outline-offset: 2px;
}

/* ==========================================================================
   PWA INSTALL INVITATION
   Redesigned around one idea: show the OUTCOME (the app sitting on a home
   screen) instead of describing it. Structure is deliberately three tiers —
   hero → pitch → action zone — because the old flat stack of two identical
   lists gave the eye nothing to land on.
   Bottom sheet on phones (thumb reach), centred card from 600px.
   ========================================================================== */

.pwa-dialog {
    padding: 0;
    border: none;
    background: transparent;
    max-width: none;
    max-height: none;
    width: 100%;
    margin: 0 auto auto;
    color: var(--text-primary);
    overscroll-behavior: contain;
}

.pwa-dialog::backdrop {
    background: rgba(var(--bg-deep-rgb), 0.72);
    -webkit-backdrop-filter: blur(3px);
    backdrop-filter: blur(3px);
    opacity: 0;
    transition: opacity 0.24s ease;
}

.pwa-dialog.pwa-dialog-in::backdrop { opacity: 1; }

.pwa-sheet {
    position: relative;
    overflow: hidden;
    padding: 0 20px 0;   /* .pwa-act is full-bleed and owns the bottom inset */
    /* The brand's own surface with a faint glow of its accent behind the icon — both
       tokens, so a domain's brand.css recolours the sheet with the rest of the site. */
    background:
        radial-gradient(120% 90% at 50% 0%, color-mix(in srgb, var(--accent-green) 13%, transparent) 0%, transparent 58%),
        var(--bg-secondary);
    border: 1px solid rgba(255, 255, 255, 0.10);
    text-align: center;
    transform: translateY(16px);
    opacity: 0;
    transition: transform 0.3s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.24s ease;
}

.pwa-dialog-in .pwa-sheet { transform: translateY(0); opacity: 1; }

@media (max-width: 599px) {
    .pwa-dialog { margin: auto 0 0; }
    .pwa-sheet {
        border-radius: 0;
        border-bottom: none;
        transform: translateY(100%);
    }
}

@media (min-width: 600px) {
    .pwa-dialog { margin: auto; max-width: 396px; }
    .pwa-sheet { border-radius: 0; }
}

/* Drag affordance — a bottom sheet without one reads as stuck. */
.pwa-grab {
    width: 38px;
    height: 4px;
    margin: 10px auto 0;
    border-radius: 2px;
    background: rgba(255, 255, 255, 0.22);
}

@media (min-width: 600px) { .pwa-grab { display: none; } }

.pwa-close {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 44px;                       /* 44px minimum touch target */
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: none;
    border: none;
    border-radius: 0;
    color: var(--text-muted);
    cursor: pointer;
    touch-action: manipulation;
    z-index: 1;
}

.pwa-close svg { width: 18px; height: 18px; }
.pwa-close:hover { color: var(--text-primary); background: rgba(255, 255, 255, 0.06); }

/* ---- tier 1: the payoff ------------------------------------------------ */
/* The real app icon sitting between two dimmed tiles reads instantly as
   "your home screen, with this on it" — far more persuasive than a bullet
   list, and it uses the actual brand mark rather than a generic graphic. */
.pwa-hero {
    display: flex;
    justify-content: center;
    padding: 22px 0 18px;
}

.pwa-tiles {
    display: flex;
    align-items: center;
    gap: 10px;
}

.pwa-tile {
    width: 38px;
    height: 38px;
    border-radius: 9px;
    background: rgba(255, 255, 255, 0.07);
    flex-shrink: 0;
}

.pwa-tile-app {
    width: 62px;
    height: 62px;
    border-radius: 14px;   /* a home-screen icon is a rounded square */
    background: none;
    box-shadow: 0 8px 22px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(255, 255, 255, 0.09);
}

/* ---- tier 2: the pitch -------------------------------------------------- */
.pwa-h {
    font-size: 21px;
    line-height: 1.25;
    letter-spacing: -0.01em;
    text-wrap: balance;      /* no widow on the headline */
    margin: 0 0 7px;
    color: var(--text-primary);
}

.pwa-p {
    font-size: 13.5px;
    line-height: 1.5;
    color: var(--text-muted);
    margin: 0 auto 16px;
    max-width: 30ch;
}

/* Three benefits as one compact strip — same information as the old
   full-width bullets in a third of the height, and it reads as a spec
   line rather than filler copy. */
.pwa-chips {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 7px;
    list-style: none;
    margin: 0 0 18px;
    padding: 0;
}

.pwa-chips li {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 6px 11px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-primary);
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.07);
    border-radius: 999px;
    white-space: nowrap;
}

.pwa-chips svg {
    width: 13px;
    height: 13px;
    color: var(--accent-green-neon);
    flex-shrink: 0;
}

/* ---- tier 3: the action zone ------------------------------------------- */
/* Separated by a full-bleed rule so "why" and "how" stop competing. */
.pwa-act {
    margin: 0 -20px;
    padding: 16px 20px calc(12px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid rgba(255, 255, 255, 0.07);
    background: rgba(0, 0, 0, 0.14);
}

.pwa-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    width: 100%;
    min-height: 50px;
    padding: 13px 18px;
    font-size: 15.5px;
    font-weight: 700;
    font-family: inherit;
    border: none;
    border-radius: 0;
    cursor: pointer;
    text-decoration: none;
    touch-action: manipulation;
}

.pwa-btn svg { width: 20px; height: 20px; flex-shrink: 0; }

.pwa-btn-primary {
    background: var(--accent-green);
    color: var(--bg-deep);
    box-shadow: 0 6px 18px color-mix(in srgb, var(--accent-green) 22%, transparent);
}

.pwa-btn-primary:disabled { opacity: 0.75; cursor: default; box-shadow: none; }

/* Secondary actions sit on one row so neither outranks the primary. */
.pwa-act-sub {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    margin-top: 4px;
}

.pwa-link,
.pwa-later {
    min-height: 44px;                  /* was ~34-38px — below the 44px minimum */
    display: inline-flex;
    align-items: center;
    padding: 0 14px;
    font-size: 13.5px;
    font-weight: 600;
    font-family: inherit;
    background: none;
    border: none;
    border-radius: 0;
    cursor: pointer;
    touch-action: manipulation;
    text-decoration: none;
}

.pwa-link { color: var(--accent-green-neon); }
.pwa-later { color: var(--text-muted); }
.pwa-link:hover, .pwa-later:hover { color: var(--text-primary); }

.pwa-act-sep { color: rgba(255, 255, 255, 0.2); font-size: 12px; }

/* ---- iOS: the steps ARE the install, so they get the focal treatment --- */
.pwa-steps {
    counter-reset: pwastep;
    list-style: none;
    margin: 0 0 12px;
    padding: 14px 15px;
    display: grid;
    gap: 12px;
    text-align: left;
    background: rgba(255, 255, 255, 0.045);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 0;
}

.pwa-steps li {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    font-size: 13.5px;
    line-height: 1.45;
    color: var(--text-primary);
}

.pwa-steps li::before {
    counter-increment: pwastep;
    content: counter(pwastep);
    flex-shrink: 0;
    width: 21px;
    height: 21px;
    margin-top: 1px;
    border-radius: 50%;
    background: var(--accent-green-grad);
    color: #06231a;
    font-size: 11.5px;
    font-weight: 800;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* The Share glyph inline in step 1 — for most people it IS the instruction. */
.pwa-share-glyph {
    display: inline-flex;
    width: 16px;
    height: 16px;
    vertical-align: -3px;
    margin: 0 1px;
    color: #3b9bff;
}

.pwa-share-glyph svg { width: 100%; height: 100%; }

/* Non-Safari iOS: installing is genuinely impossible — say so plainly. */
.pwa-blocked {
    font-size: 13px;
    line-height: 1.55;
    text-align: left;
    margin: 0 0 12px;
    padding: 13px 15px;
    color: var(--text-primary);
    background: rgba(255, 255, 255, 0.045);
    border-left: 3px solid var(--accent-green-neon);
    border-radius: 0;
}

/* ---- focus + motion ---------------------------------------------------- */
.pwa-btn:focus-visible,
.pwa-close:focus-visible,
.pwa-link:focus-visible,
.pwa-later:focus-visible {
    outline: 2px solid var(--accent-green-neon);
    outline-offset: 2px;
}

/* Install icon: the arrow falls into the phone while installing, so the
   button reads as working rather than stuck. */
@keyframes pwa-arrow-drop {
    0%   { transform: translateY(-3px); opacity: 0.35; }
    45%  { transform: translateY(1px);  opacity: 1; }
    100% { transform: translateY(-3px); opacity: 0.35; }
}

.pwa-btn-working .pwa-ico-arrow { animation: pwa-arrow-drop 1.05s ease-in-out infinite; }

@media (prefers-reduced-motion: reduce) {
    .pwa-dialog::backdrop,
    .pwa-sheet { transition: none; }
    .pwa-btn-working .pwa-ico-arrow { animation: none; }
}

/* ==========================================================================
   Chat — floating panel (announcements + player lobby) and the #CH admin page.
   The panel only exists in the DOM when an admin has enabled chat, so none of
   this costs anything while the feature is off.
   ========================================================================== */

/* The FAB shares the betslip's column on the right. Desktop has no betslip FAB
   (the slip is a sidebar), so chat sits low; in the 601-1100px band the betslip
   FAB is visible and chat stacks directly above it; below 900px that FAB is
   hidden in favour of the bottom nav, so chat takes its slot. */
#chat-root {
    position: fixed;
    right: 16px;
    bottom: 30px;
    z-index: 99;
    /* Matches the slip's own width transition so the two move together. */
    transition: right 0.3s ease;
}

/* The desktop slip is an in-flow right COLUMN, but #chat-root is fixed to the
   viewport edge — so the FAB lands on top of the slip's content, right where the
   ticket totals and payout sit. Step it clear of the column while the slip is open.
   Scoped above 1100px on purpose: below that the panel is display:none yet can
   still carry .open, and the FAB would slide left for a column that isn't there. */
@media (min-width: 1101px) {
    body:has(.betslip-panel.open) #chat-root {
        right: calc(var(--betslip-width) + 16px);
    }
}

.chat-fab, #chat-fab {
    position: relative;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    border: 1px solid var(--accent-green-neon, #3aa56e);
    background: var(--bg-secondary);
    color: var(--text-primary);
    display: grid;
    place-items: center;
    cursor: pointer;
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
    transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}
#chat-fab:hover { border-color: var(--accent-green-neon, #3aa56e); transform: translateY(-1px); }

.chat-badge {
    position: absolute;
    top: -4px;
    right: -4px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    border-radius: 9px;
    background: var(--accent-red, #e5484d);
    color: #fff;
    font-size: 10px;
    font-weight: 800;
    line-height: 18px;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

/* Bottom sheet, same shape and motion as the betslip overlay. */
.chat-overlay {
    position: fixed;
    inset: 0;
    z-index: 200;
    background: rgba(0, 0, 0, 0.6);
    display: flex;
    align-items: flex-end;
    justify-content: center;
}

.chat-overlay-panel {
    width: 95%;
    max-width: 500px;
    /* dvh, not vh — the iOS URL bar doesn't shrink vh and the composer clips. */
    height: min(70dvh, 560px);
    display: flex;
    flex-direction: column;
    background: var(--bg-secondary);
    border-radius: 0;
    overflow: hidden;
    box-shadow: 0 -8px 32px rgba(0, 0, 0, 0.45);
}

/* Standard bottom-sheet grabber — signals "this is a sheet you can dismiss". */
.chat-grab {
    flex: 0 0 auto;
    width: 36px;
    height: 4px;
    border-radius: 999px;
    background: var(--text-muted);
    opacity: 0.45;
    margin: 8px auto 2px;
}

/* `chat-overlay-anim` is present only DURING the animation, so no transform
   lingers on the panel afterwards (a transform would become the containing
   block for any fixed-position descendant). */
.chat-overlay.chat-overlay-anim {
    transition: background 300ms ease-in-out;
    background: rgba(0, 0, 0, 0);
}
.chat-overlay.chat-overlay-anim.chat-overlay-open {
    background: rgba(0, 0, 0, 0.6);
}
.chat-overlay.chat-overlay-anim .chat-overlay-panel {
    transition: transform 300ms ease-in-out;
    transform: translateY(100%);
}
.chat-overlay.chat-overlay-anim.chat-overlay-open .chat-overlay-panel {
    transform: translateY(0);
}

.chat-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 2px 10px 10px 14px;   /* grabber above provides the top breathing room */
    border-bottom: 1px solid var(--border-color);
    flex: 0 0 auto;
}
/* Identity block: bubble icon in brand green + short title. */
.chat-head-title {
    display: flex;
    align-items: center;
    gap: 7px;
    flex: 0 0 auto;
    font-size: 13px;
    font-weight: 800;
    color: var(--text-primary);
    letter-spacing: 0.2px;
}
.chat-head-title svg { color: var(--accent-green-neon, #3aa56e); flex: 0 0 auto; }
/* Rooms as a SEGMENTED CONTROL: an inset track, active room = solid green
   segment (same treatment as the send button, so "selected" reads instantly). */
.chat-tabs {
    display: flex;
    gap: 3px;
    min-width: 0;
    margin-left: auto;              /* track sits right, next to the close chip */
    padding: 3px;
    background: var(--bg-primary);
    border: 1px solid var(--border-color);
    border-radius: 999px;
    overflow-x: auto;
    scrollbar-width: none;          /* many rooms → track scrolls, no scrollbar chrome */
    touch-action: pan-x pan-y;
}
.chat-tabs::-webkit-scrollbar { display: none; }
.chat-tabs:empty { display: none; }  /* no rooms yet → no empty pill husk */
.chat-tab {
    padding: 7px 14px;
    border: 0;
    border-radius: 999px;
    background: transparent;
    color: var(--text-secondary);
    font: inherit;
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.15s, color 0.15s;
}
.chat-tab:hover { color: var(--text-primary); }
.chat-tab.active {
    background: var(--accent-green-neon, #3aa56e);
    color: #06210f;
}
.chat-close {
    width: 34px;
    height: 34px;
    border: 0;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.05);
    color: var(--text-secondary);
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
    flex: 0 0 auto;
    transition: background 0.15s, color 0.15s;
}
.chat-close:hover { color: var(--text-primary); background: rgba(255, 255, 255, 0.12); }

.chat-msgs {
    flex: 1 1 auto;
    min-height: 0;              /* so the flex child can actually scroll */
    overflow-y: auto;
    overscroll-behavior: contain;   /* don't chain the scroll to the page */
    touch-action: pan-y;
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.chat-empty { margin: auto; color: var(--text-muted); font-size: 12px; }

/* Bottom-anchor the conversation: newest message sits next to the composer
   (chat convention) instead of the log floating at the top of an empty sheet.
   margin-top:auto on the FIRST message keeps scrolling correct — unlike
   justify-content:flex-end, which breaks scroll-to-top in some engines. */
.chat-msgs > .chat-msg:first-child { margin-top: auto; }

/* Speech bubbles, not settings cards: subtler fill, one squared corner as the
   tail cue, self-sizing width instead of full-width slabs. */
.chat-msg {
    align-self: flex-start;
    max-width: 88%;
    min-width: 180px;
    padding: 7px 11px 8px;
    border-radius: 0;
    background: var(--bg-darkb, rgba(255, 255, 255, 0.04));
    border: 1px solid rgba(255, 255, 255, 0.05);
}
/* Staff messages read as official, not as another player talking. */
.chat-msg.is-staff {
    background: rgba(58, 165, 110, 0.10);
    border-color: rgba(58, 165, 110, 0.30);
    border-left: 3px solid rgba(58, 165, 110, 0.75);
}
.chat-msg-top {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 2px;
}
.chat-msg-name {
    font-size: 11px;
    font-weight: 800;
    color: var(--accent-green-neon, #3aa56e);
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.chat-msg.is-staff .chat-msg-name::after {
    content: '★';
    margin-left: 4px;
    font-size: 9px;
}
.chat-msg-time {
    flex: 0 0 auto;
    font-size: 11px;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}
.chat-msg-text {
    font-size: 13px;
    line-height: 1.35;
    color: var(--text-primary);
    overflow-wrap: anywhere;    /* a pasted 400-char token can't widen the panel */
}

.chat-error {
    flex: 0 0 auto;
    padding: 6px 10px;
    background: rgba(229, 72, 77, 0.12);
    color: var(--accent-red, #e5484d);
    font-size: 11px;
    font-weight: 600;
}
.chat-error[hidden] { display: none; }

.chat-compose {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px;
    border-top: 1px solid var(--border-color);
}
/* One 42px control row — input and button height-matched, pill-shaped. */
.chat-input {
    flex: 1 1 auto;
    min-width: 0;
    height: 42px;
    padding: 0 16px;
    border: 1px solid var(--accent-green-neon);
    border-radius: 999px;
    background: var(--bg-primary);
    color: var(--text-primary);
    font: inherit;
    font-size: 13px;
}
.chat-input:focus { outline: 2px solid rgba(58, 165, 110, 0.5); outline-offset: -1px; }
.chat-send, .chat-login {
    flex: 0 0 auto;
    height: 42px;
    padding: 0 18px;
    border: 0;
    border-radius: 999px;
    background: var(--accent-green-neon, #3aa56e);
    color: #06210f;
    font: inherit;
    font-size: 12px;
    font-weight: 800;
    cursor: pointer;
    font-variant-numeric: tabular-nums;
    transition: filter 0.15s;
}
.chat-send:hover:not(:disabled) { filter: brightness(1.08); }
.chat-send:disabled { opacity: 0.55; cursor: default; }
.chat-login { width: 100%; }
.chat-readonly {
    width: 100%;
    text-align: center;
    font-size: 11px;
    color: var(--text-muted);
}

/* Stack above the betslip FAB where that FAB exists (601-1100px)... */
@media (max-width: 1100px) {
    #chat-root { bottom: calc(90px + 52px + 12px + env(safe-area-inset-bottom, 0px)); }
}
/* ...and take its slot below 900px, where the bottom nav replaces it. */
@media (max-width: 900px) {
    #chat-root { bottom: calc(90px + env(safe-area-inset-bottom, 0px)); }
    /* End the sheet ON the bottom nav rather than under it — same offset the
       betslip overlay uses, so the composer is never hidden behind the nav. */
    .chat-overlay { bottom: calc(var(--bottom-nav-height) - 8px) ; 
    
    }
}

@media (prefers-reduced-motion: reduce) {
    .chat-overlay.chat-overlay-anim,
    .chat-overlay.chat-overlay-anim .chat-overlay-panel { transition: none; }
}

@media (prefers-reduced-motion: reduce) {
    #chat-fab { transition: none; }
}

/* ---- #CH admin page ---- */
.ch-grid {
    display: grid;
    gap: 10px;
    margin: 14px 0;
}
.ch-opt {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 12px;
    border: 1px solid var(--border-color);
    border-radius: 0;
    background: var(--bg-secondary);
    cursor: pointer;
}
.ch-opt input { margin-top: 2px; flex: 0 0 auto; }
.ch-opt span { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ch-opt small { color: var(--text-muted); font-size: 11px; }
.ch-num {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 12px;
    border: 1px solid var(--border-color);
    border-radius: 0;
    background: var(--bg-secondary);
    font-size: 13px;
}
.ch-num input {
    width: 90px;
    padding: 6px 8px;
    border: 1px solid var(--border-color);
    border-radius: 0;
    background: var(--bg-primary);
    color: var(--text-primary);
    font: inherit;
    font-variant-numeric: tabular-nums;
}
.ch-h { margin: 20px 0 8px; font-size: 14px; color: var(--text-primary); }
.ch-compose { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.ch-compose textarea {
    width: 100%;
    padding: 10px;
    border: 1px solid var(--border-color);
    border-radius: 0;
    background: var(--bg-primary);
    color: var(--text-primary);
    font: inherit;
    font-size: 13px;
    resize: vertical;
}
.ch-msg { margin-top: 8px; font-size: 12px; font-weight: 600; }
.ch-msg.good { color: var(--accent-green-neon, #3aa56e); }
.ch-msg.bad  { color: var(--accent-red, #e5484d); }
.ch-msg[hidden] { display: none; }
.ch-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border: 1px solid var(--border-color);
    border-radius: 0;
    background: var(--bg-secondary);
    margin-bottom: 8px;
}
.ch-item-main { flex: 1 1 auto; min-width: 0; }
.ch-item-text { font-size: 13px; color: var(--text-primary); overflow-wrap: anywhere; }
.ch-item-meta { font-size: 11px; color: var(--text-muted); margin-top: 2px; }
.ch-del { flex: 0 0 auto; }

/* Emoji picker — a fixed palette in a popover above the composer. */
.chat-compose { position: relative; }

.chat-emoji-btn {
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    align-self: center;
    border: 1px solid var(--border-color);
    border-radius: 0;
    background: var(--bg-primary);
    font-size: 17px;
    line-height: 1;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.chat-emoji-btn:hover { border-color: var(--accent-green-neon, #3aa56e); }

.chat-emoji-pop {
    position: absolute;
    left: 8px;
    right: 8px;
    bottom: calc(100% + 6px);
    z-index: 2;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(36px, 1fr));
    gap: 2px;
    max-height: 168px;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 6px;
    background: var(--bg-primary);
    border: 1px solid var(--border-color);
    border-radius: 0;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.45);
}
.chat-emoji-pop[hidden] { display: none; }

.chat-emoji {
    /* 36px keeps the tap target usable on a phone without a scroll-heavy grid. */
    width: 36px;
    height: 36px;
    border: 0;
    border-radius: 0;
    background: transparent;
    font-size: 19px;
    line-height: 1;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.chat-emoji:hover { background: rgba(255, 255, 255, 0.08); }

/* ============================================================================
   DISPLAY TYPE — Futura PT Cond on headings, scores, minutes and prices.
   Restored 2026-08-03 per the design review ("no display face, so there is no
   hierarchy"): before this, page titles, section heads, the wallet balance and
   every price rendered in the body face at body weight, so the page was one flat
   texture. The cut is BOLD-ONLY, so this list is deliberately limited to text
   that is already >=700 — body copy stays on the system stack. The narrow digits
   also fix the truncated-balance problem noted in the header CSS.
   ========================================================================== */
.section-header h3,
.profile-page-title,
.rpt-sec-head,
.chat-head-title {
    font-family: var(--font-head);
    letter-spacing: 0.2px;
}

/* Oxanium is a wider face than the Futura PT Cond it replaced here, so the old
   20px would have grown every section head by roughly a fifth. 19px lands the
   heading at close to its previous optical width — the change reads as a change
   of voice, not a change of size. */
.section-header h3 {
    font-size: 19px;
}

@media (max-width: 600px) {
    /* Phone heads step DOWN, not up. The old mobile rule went the other way
       (23px vs 20px on desktop) to buy Futura PT Cond some presence; on a wider
       face that only steals room from the "view all" link sharing the row. */
    .section-header h3 {
        font-size: 18px;
    }
}

/* Scores + clock — big numbers are where a condensed face earns the most. */
.live-match-score,
.live-now-score,
.live-md-score,
.live-match-minute,
.live-now-minute,
.live-md-minute,
.minute-pill {
    font-family: var(--font-display);
    letter-spacing: 0.2px;
}

/* Prices. `.live-odd-btn` is the button itself (live list); the other surfaces
   hold the number in an inner span. Tabular figures keep columns aligned.

   The list below was audited against the rendered homepage on 2026-08-22 and
   two of its entries — `.odd-value` and `.bb-odd-value` — matched NOTHING; the
   classes had been renamed and the selectors never followed. Meanwhile the four
   busiest price surfaces on that page had never been listed at all, so they had
   been rendering in the plain body face the whole time:
       .odd-btn-inline      96 on the homepage — the pre-match league rows
       .odd-btn-card-value  30 — featured-match cards
       .bb-odd-new/-old     20 each — Bet Boost
       .hero-odd-value       9 — the featured-match hero
   That is why prices looked like they came from two different products depending
   on which strip you were reading. Add new price surfaces HERE when they appear.
   The label above each price (`1` / `X` / `2`, the O/U line) is included too: a
   number in one face captioned in another is the same split one row down. */
.live-odd-btn,
.live-odd-cap,
.md-odd-value,
.lno-value,
.hero-odd,
.hero-odd-value,
.hero-odd-label,
.bb-odd,
.bb-odd-new,
.odd-btn-card,
.odd-btn-card-label,
.odd-btn-card-value,
.odd-btn-inline,
#user-balance,
#dropdown-balance {
    font-family: var(--font-odds);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.2px;
}

/* ============================================================================
   Live match detail — desktop two-column layout.
   Markets fill the main column; the live scout pitch and the stats/summary
   panel sit in a sticky rail beside them, so a market list that runs to
   thousands of rows no longer pushes the live picture off the top of the page.
   ========================================================================== */
.live-md-cols {
    display: grid;
    /* Markets get a floor and the growth; the rail yields first. Without the
       400px floor on the main track the rail held its width and the MARKETS
       ended up narrower than the side panel (346 vs 380 on a 1020px window),
       which is backwards — the odds are what the page is for. */
    grid-template-columns: minmax(400px, 1fr) minmax(280px, 430px);
    /* Both tracks are card surfaces, so a hairline gutter reads as a seam down
       the middle of one panel rather than as two columns. Kept in a variable
       because the mobile stack below has to cancel this exact value to hold the
       scout stripe flush against the pitch — a literal in two places drifts the
       moment one of them changes. */
    --md-col-gap: 20px;
    gap: var(--md-col-gap);
    align-items: start;   /* NOT stretch: a stretched side rail is as tall as the
                             markets, and sticky on a full-height element is a
                             no-op — the classic reason "position: sticky does
                             nothing" in a flex/grid row. */
}

/* minmax(0, 1fr) above rather than 1fr, and this, so the market tables and the
   category tab strip can shrink instead of forcing the grid wider than the page. */
.live-md-main {
    min-width: 0;
}

/* The hero is full-bleed via negative side margins, which was right when it
   spanned the page. Inside the left column those margins made it overhang its
   track by 20px a side and lap 8px OVER the rail. Neutralised here only — the
   single-column layout below 1100px keeps the bleed. */
.live-md-cols .match-detail-top {
    margin-left: 0;
    margin-right: 0;
    /* Top too: the hero bleeds upward as well, which left the rail starting 12px
       BELOW it instead of level. Zeroing all three keeps the two columns sharing
       one top edge, which is the whole point of the layout. */
    margin-top: 0;
    margin-bottom: 8px;
}

.live-md-side {
    min-width: 0;
    position: sticky;
    top: calc(var(--header-height, 60px) + 8px);
    align-self: start;
    /* The scout pitch + stats can exceed the viewport on short screens; scroll
       the rail itself rather than letting it push past the fold. */
    max-height: calc(100dvh - var(--header-height, 60px) - 16px);
    overflow-y: auto;
    scrollbar-width: none;
}

.live-md-side::-webkit-scrollbar { display: none; }

/* The rail's panels were sized for a full-width parent; in a 360px column they
   simply take the column. */
.live-md-side .live-md-scout,
.live-md-side .live-md-summary {
    width: 100%;
}

/* The desktop rail as bet365's right-hand column: the pitch / video icons on top, the pitch - or
   the video in its place - under them, and the pitch module's statistics bar and panel under
   that. The video comes before the module, which keeps all but its pitch while the video is in
   front (live.js _applyMediaView). Flex for the order alone: nothing shrinks, the rail scrolls.
   The zone's wrappers have no box here (display: contents), so these are the rail's items. */
@media (min-width: 981px) {
    #page-live-match .live-md-side { display: flex; flex-direction: column; }
    #page-live-match .live-md-side #live-md-view-tabs,
    #page-live-match .live-md-side #live-md-media-switch,
    #page-live-match .live-md-side #live-md-row,
    #page-live-match .live-md-side #live-md-scout,
    #page-live-match .live-md-side #live-md-scout-stripe,
    #page-live-match .live-md-side #live-md-row-toggle,
    #page-live-match .live-md-side #live-md-summary { flex-shrink: 0; }
    #page-live-match .live-md-side #live-md-media-switch { order: -1; }
    #page-live-match .live-md-side #live-md-scout,
    #page-live-match .live-md-side #live-md-scout-stripe,
    #page-live-match .live-md-side #live-md-row-toggle,
    #page-live-match .live-md-side #live-md-summary { order: 1; }
}

/* Below the two-column threshold, fall back to the original single stack with
   the live picture ABOVE the markets — the order it has always had on mobile. */
@media (max-width: 980px) {
    /* Single column — and the two wrappers dissolve so their children can be
       interleaved back into the ORIGINAL reading order. `order: -1` on the whole
       rail used to do this, but that was written while the hero still sat
       OUTSIDE the grid; once the hero moved into .live-md-main, hoisting the
       rail dragged the pitch and stats above the hero and left the scoreboard
       stranded below them. Ordering the children individually is the only way to
       get hero -> pitch -> stats -> markets when hero and markets share a
       wrapper. */
    .live-md-cols {
        display: flex;
        flex-direction: column;
        /* MUST be re-stated. The grid above sets `align-items: start` so the
           sticky rail isn't stretched to the markets' height — but in a COLUMN
           flex container the same value means "shrink every child to its content
           width". Most children survived that because their content is naturally
           wide; the two that have no intrinsic width did not:
             - the video stage is `width: 100%` of a shrink-to-fit parent, i.e.
               a percentage of an indefinite size -> 0, so the player mounted and
               rendered 2x2 px. That is the whole "livestream doesn't work on
               mobile" bug; `.live-md-row { display: block }` was necessary but
               not sufficient, because the row is still the flex item.
             - the category tab strip is a horizontal scroller with min-width: 0,
               so it collapsed to 136px in a 375px viewport.
           The media switch stays centred at its own width regardless: auto cross
           margins take priority over stretch. */
        align-items: stretch;
        /* Stacked cards want a tighter rhythm than the desktop column gutter,
           and the stripe's flush pull below is keyed off this. */
        --md-col-gap: 3px;
    }
    .live-md-main,
    .live-md-side {
        display: contents;
    }
    /* One column again — the hero goes back to spanning the page edge to edge. */
    .live-md-cols .match-detail-top {
        margin-left: revert;
        margin-right: revert;
        margin-top: revert;
        order: 1;
    }
    /* The switch leads the pitch on mobile — it always has, and the pitch's
       stripe is pinned to the pitch's own bottom edge, so anything placed
       between them lands in the middle of that card. (Desktop keeps the switch
       BELOW the pitch in the rail; these are different layouts, not one order.)
       Giving scout/stripe/switch a single `order` let DOM order decide and put
       the switch last, which is the version that looked wrong. */
    /* The goals ticker sits immediately under the header, where it was when it
       lived INSIDE it. It has to be said explicitly: .live-md-main is
       `display: contents`, so its children are hoisted into this flex container
       and every one of them carries an explicit `order` — a new child with no
       rule defaults to 0 and jumps ABOVE the header, which is exactly what it
       did. Order 1 ties with #live-md-detail-top and same-order items fall back
       to DOM order, where the wrap is the header's next sibling. */
    .live-md-goals-wrap   { order: 1; }

    #live-md-media-switch,
    #live-md-row-toggle   { order: 2; }

    /* `display: contents` removed the wrapper that used to centre these, so they
       sat hard against the left edge. They centre themselves now. */
    #live-md-media-switch { justify-content: center; margin-left: auto; margin-right: auto; }
    #live-md-scout,
    #live-md-scout-stripe,
    #live-md-row          { order: 3; }

    /* Stripe flush under the pitch, same as the desktop rail — it reads as the
       pitch's caption, not a second card. Here the space is the column's own
       12px `gap` rather than a margin, so it has to be pulled back. Needs the
       three-part selector to outrank `.live-md-side #live-md-scout-stripe`
       further down the file, which zeroes this margin for the rail. */
    .live-md-cols .live-md-side #live-md-scout-stripe {
        margin-top: calc(-1 * var(--md-col-gap));
    }
    #live-md-summary      { order: 4; }
    .live-md-cols .md-categories-wrapper,
    .live-md-cols .md-search-bar,
    .live-md-cols .md-markets { order: 5; }

    /* `order` reorders things VISUALLY, but scroll anchoring walks the DOM. These
       three are DOM-early and visually LAST, so once the hero scrolled off the
       top the browser picked the market tab strip as its anchor — an element
       BELOW the rail it was anchoring against. Expanding the stats panel then
       made Chrome scroll down to hold the tab strip still, which threw the
       panel's own header off the top of the screen: the div appeared to open
       UPWARDS instead of pushing the page down.
       Excluding them (and their descendants) lets the anchor fall to the hero or
       to the rail, both of which sit ABOVE the panel, so a panel that grows
       pushes content down the way a disclosure is supposed to. Nothing is lost:
       the market list is only ever rebuilt wholesale (`_renderDetailMarkets` on
       a market-set change), which destroys the anchor node anyway — in-place odds
       patches don't change height, so there is no jump left to absorb. */
    .live-md-cols .md-categories-wrapper,
    .live-md-cols .md-search-bar,
    .live-md-cols .md-markets { overflow-anchor: none; }

    /* `display: contents` above dissolves .live-md-main — and with it the
       `min-width: 0` these relied on to shrink. Without it the category tab strip
       sized to its content (419px in a 375px viewport) and pushed the page into
       horizontal scroll. Re-declared on the children that actually need it. */
    .live-md-cols .md-categories-wrapper,
    .live-md-cols .md-search-bar,
    .live-md-cols .md-markets,
    .live-md-cols #live-md-categories {
        min-width: 0;
        max-width: 100%;
         margin-top: 0px;
    }
}

/* The stats panel was sized for a full-width parent. In the rail its flanking
   numbers overlapped the gauge dials, so it steps down inside the rail only —
   the mobile/full-width rendering is untouched. */
@media (min-width: 981px) {
    .live-md-side .lmst-gauges     { gap: 6px; }
    .live-md-side .lmst-gauge-col  { gap: 4px; }
    .live-md-side .lmst-gauge      { gap: 4px; }
    .live-md-side .lmst-gauge-label { font-size: 10.5px; }
    .live-md-side .lmst-gauge-val  { font-size: 14px; min-width: 18px; }
    .live-md-side .lmst-gauge-svg  { width: 34px; height: 34px; }
}

/* The stripe is the pitch's caption, so it must sit FLUSH against the pitch's
   bottom edge — a gap made it read as a separate floating card. Its own -10px
   pull wasn't enough once the pitch moved into the rail. */
.live-md-side #live-md-scout { margin-bottom: 0; }
.live-md-side #live-md-scout-stripe {
    margin-top: -5px;
    border-top-left-radius: 0;
    border-top-right-radius: 0;
}

/* ============================================================================
   Live match header — compact.
   The stacked hero ran 341px (kit over form over name over score, twice, plus
   the minute and the stat chips) before a single market was on screen. The
   reference puts the kit BESIDE the name and brings the two scores together in
   the middle — the same information in roughly a third of the height.

   Keyed to the HEADER's own width, not the viewport: it lives in the left column
   of the two-column layout, so the viewport says nothing useful about how much
   room it actually has. Below the threshold it keeps the stack, just tighter.
   ========================================================================== */
#live-md-detail-top {
    container-type: inline-size;
    container-name: mdtop;
    border-bottom: 1px solid var(--border-color, #3aa56e);
    border-radius: var(--border-radius, 8px);
}

/* Tighter in BOTH layouts. Scoped to .live-md-team so the pre-match header,
   which shares .md-kit, keeps its own sizing. */
.live-md-hero { gap: 6px; }
/* Dialled down from 64. At 48 the kit still dominated a header this compact;
   40 reads as a crest beside the name rather than the headline of the page. */
.live-md-team .md-kit,
.live-md-team .md-kit .team-kit-lg { width: 40px; height: 40px; }
.live-md-team-name { font-size: 14px; }
.live-md-form      { margin-top: -5px; margin-bottom: 0; }

/* Scoreboard digits: each score sits in its own recessed tile so the pair reads
   as one scoreboard rather than two loose numbers. min-width keeps 1 and 10 the
   same width, so the tiles don't jump as the score climbs. */
.live-md-score {
    font-size: 26px;
    min-width: 42px;
    padding: 4px 10px;
    border-radius: 0;
    text-align: center;
    background: rgba(0, 0, 0, 0.38);
    border: 1px solid rgba(255, 255, 255, 0.10);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.45);
}

/* Cards + corners for ONE team, sitting under that team's name. */
.live-md-team-stats {
    display: flex;
    align-items: center;
    gap: 9px;
    font-size: 12px;
    line-height: 1;
    color: var(--text-secondary);
    font-variant-numeric: tabular-nums;
}

.lmts-item {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}

/* No opacity here: it made the corner flag read as a paler green than the two
   cards beside it, which are at full strength. Every glyph in this strip is one
   fixed colour on both sides — see .is-zero below. */
.lmts-item .live-md-stat-icon { flex: none; width: 10px; height: 10px; }

/* The three icons were three different sizes: cards 10x14 from their old
   full-width-chip context, the corner glyph 12x12. Normalised to one optical
   weight here — 9x12 keeps the cards' 3:4 card shape against a 10px square
   flag. `.live-md-card` also carries `margin-right: 2px` from that old context,
   which stacked on top of the row's 4px gap and left the cards sitting further
   from their number than the flag does; the flex gap is the only spacing here. */
.lmts-item .live-md-card {
    width: 9px;
    height: 12px;
    margin-right: 0;
}

/* A stat reading zero is context, not news — dimmed so the one that isn't zero
   carries the row. Class is set in _renderStats; CSS can't test text content.
   Dims the COUNT ONLY, never the glyph: when this sat on `.lmts-item` it faded
   the icon too, so a 0-card team's yellow rendered olive against a 1-card
   team's full yellow and the two sides looked like different icons. The card
   colours are identifying marks — a referee's yellow is the same yellow whether
   it's been shown yet or not. */
.lmts-item.is-zero .live-md-stat-val { opacity: 0.4; }

/* Live minute: a pulsing dot beside a condensed red clock, per the match-live
   design — it reads as "running" at a glance where a bare number doesn't. */
.live-md-minute::before {
    content: "";
    display: inline-block;
    width: 5px;
    height: 5px;
    margin-right: 5px;
    vertical-align: 0.12em;
    border-radius: 50%;
    background: currentColor;
    animation: liveMdPulse 1.6s ease-in-out infinite;
}
/* Half-time, full-time and the non-clock sports get no dot: nothing is running,
   and a pulse there says the opposite. */
.live-md-minute:empty::before { display: none; }

@keyframes liveMdPulse {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.35; }
}

@media (prefers-reduced-motion: reduce) {
    .live-md-minute::before { animation: none; }
}

/* Kit ABOVE the name, score tile at the inner edge — one layout at every width,
   phone included, so there is no breakpoint where the header rearranges itself.
   The kit-beside-name variant this replaces read as busy: three things on one
   line, and it forced the name into a column narrow enough that tennis players
   wrapped to five lines.

   .live-md-teams stays a 2-col grid, so the two score tiles land either side of
   the centre line and the minute (above) and half-time line (below) centre on
   the same axis. */
/* Three columns: team | centre | team. The clock, the scoreline and the
   half-time line are all children of the CENTRE column now — as full-width rows
   above and below the band, each was charging a whole line of header height to
   render one short string. */
.live-md-teams {
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    gap: 5px;
    /* start, not center: the two team columns are not the same height (only one
       side usually has form pills), and centring each one independently left the
       kits, names and stat rows sitting at different heights across the band —
       which is what made it read as crowded rather than tabular. Aligning from
       the top edge lines the rows up whatever each side happens to carry. */
    align-items: start;
}

/* Reserve the form row's height even when a side has no form data, so the name
   and stat rows still line up across the band. */
.live-md-team > .live-md-form { min-height: 16px; }

.live-md-team {
    display: flex;
    flex-direction: column;
    align-items: center;
    /* 4px stacked the kit, name and stat row almost edge to edge. The band is
       three tight rows of small type; it needs the rhythm more than it needs
       the 6px back. */
    gap: 7px;
    min-width: 0;
    text-align: center;
}

.live-md-centre {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 7px;
}

/* Reserve both lines of the name. It is clamped to two, but a side whose name
   fits on ONE line pulled its stat row up level with the other side's second
   line — so the two stat rows sat at different heights and the band read as
   ragged rather than crowded. Reserving the space keeps the rows level however
   long each name happens to be. */
.live-md-team .live-md-team-name { min-height: 2.4em; }

/* A little air under the band before whatever follows it. */
.live-md-hero { padding-bottom: 4px; }

/* Kits to the OUTER edges — home left, away right — while the names and stat
   rows stay centred under them. The column is centred as a whole, so this is an
   align-self opt-out on the two kits only. */
.live-md-teams > .live-md-team:first-child > .md-kit-wrap,
.live-md-teams > .live-md-team:first-child > .live-md-form,
.live-md-teams > .live-md-team:first-child > .live-md-team-stats { align-self: flex-start; }

.live-md-teams > .live-md-team:last-child  > .md-kit-wrap,
.live-md-teams > .live-md-team:last-child  > .live-md-form,
.live-md-teams > .live-md-team:last-child  > .live-md-team-stats { align-self: flex-end; }

/* Name text to the outer edge too — home reads left, away reads right, so each
   name starts where its own kit is. The name box still spans the column (it has
   to, for the two-line clamp), so this is text-align, not a layout change: the
   form pills and stat row stay centred under it. */
.live-md-teams > .live-md-team:first-child .live-md-team-name { text-align: left; }
.live-md-teams > .live-md-team:last-child  .live-md-team-name { text-align: right; }

/* text-align alone only moves a name that FILLS its box. `.live-md-name-row
   .live-md-team-name` sets `width: auto`, so a short name ("Nigeria (W)") is a
   content-sized box that the row then centres — it looked centred while a long
   name that wrapped to the full column looked correctly aligned. The row has to
   place the box too. */
.live-md-teams > .live-md-team:first-child .live-md-name-row { justify-content: flex-start; }
.live-md-teams > .live-md-team:last-child  .live-md-name-row { justify-content: flex-end; }

.live-md-scoreline {
    display: flex;
    align-items: center;
    gap: 6px;
}

.live-md-score-sep {
    font-size: 18px;
    font-weight: 700;
    color: var(--text-muted);
}

.live-md-gamepts-row {
    display: flex;
    align-items: center;
    gap: 6px;
}
/* The row collapses to nothing on sports without game points, so it costs no
   height when both pills are hidden. */
.live-md-gamepts-row:empty { display: none; }
.live-md-gamepts { margin-top: 0; }

/* The half-time chip kept the padding and 20px bottom margin it needed as a
   full-width row of its own. Inside the centre column that is 32px of dead
   height under the score. */
.live-md-centre .live-md-stats {
    padding: 0;
    margin-bottom: 0;
}

/* ---- Header variant: periods (tennis sets, basketball quarters) ---------- */
.lmhp-status {
    font-size: 12.5px;
    font-weight: 700;
    color: var(--accent-green-neon, #56d18d);
    font-variant-numeric: tabular-nums;
    margin-bottom: 6px;
}

/* grid-template-columns is set by _renderPeriodsHeader — the column count is
   match data. A flat grid (no row wrappers) so every cell aligns without
   subgrid or `display: contents`. */
.lmhp-grid {
    display: grid;
    align-items: center;
    row-gap: 2px;
    /* No column gap: the numeric cells are shaded, and a gap between them would
       break the shading into loose tiles instead of continuous columns. */
    column-gap: 0;
    margin-bottom: 5px;
}

.lmhp-h {
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.lmhp-h-total { color: var(--text-secondary); }

/* The name column is `1fr` and the text doesn't fill it, so the numbers sit out
   at the right — correct for a scoreboard, but with nothing between them the
   span read as dead space rather than structure. Shading the numeric block
   turns that distance into columns you can track a row across. */
.lmhp-h:not(.lmhp-h-name):not(.lmhp-h-total),
.lmhp-v {
    background: rgba(255, 255, 255, 0.035);
}
.lmhp-h:not(.lmhp-h-name):not(.lmhp-h-total) { padding: 3px 0; }
.lmhp-v { padding: 5px 0; }

/* Round the outer edges of the shaded block so it reads as one panel. */
.lmhp-h:not(.lmhp-h-name):not(.lmhp-h-total):first-of-type { border-radius: 0; }
.lmhp-v:first-of-type { border-radius: 0; }

.lmhp-team {
    display: flex;
    align-items: center;
    gap: 7px;
    min-width: 0;
}

.lmhp-kit { flex: none; display: inline-flex; width: 22px; height: 22px; }
.lmhp-kit .lmhp-kit-img { width: 22px; height: 22px; object-fit: contain; }

/* Serving indicator — the reference marks the server with a dot beside the
   name rather than a ball on the racket, which reads at a glance in a table. */
/* Always in flow so both names share a left edge — only the ball's visibility
   changes. `display: none` here shifted the serving player's name across by the
   ball's width and broke the alignment between the two rows. */
.lmhp-serve {
    flex: none;
    display: inline-flex;
    align-items: center;
    line-height: 1;
    visibility: hidden;
}
.lmhp-serve.is-serving { visibility: visible; }

.lmhp-name {
    font-size: 14px;
    font-weight: 700;
    color: var(--text-primary);
    line-height: 1.2;
    min-width: 0;
    /* A long name wraps onto a second line instead of being cut with "…"; only a
       name longer than two lines is clipped. */
    overflow: hidden;
    overflow-wrap: break-word;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
}

.lmhp-v {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-secondary);
    text-align: center;
    font-variant-numeric: tabular-nums;
}
/* Current game points are the live number in a tennis row — the sets are
   history by comparison. */
.lmhp-pts { color: var(--accent-green-neon, #56d18d); font-weight: 800; }

.lmhp-total {
    justify-self: end;
    /* Column gap is 0 for the shaded block, so the total buys its own breathing
       room here rather than gapping every column. */
    margin-left: 8px;
    min-width: 34px;
    padding: 4px 8px;
    border-radius: 0;
    text-align: center;
    font-size: 16px;
    font-weight: 800;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    background: rgba(0, 0, 0, 0.38);
    border: 1px solid rgba(255, 255, 255, 0.10);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.45);
}

/* The old two-line reservation kept the scores aligned when one name wrapped;
   the scores aren't under the names any more, so it was only adding height.
   Clamped to two lines instead — "Isis Louise Van den Broek" in a narrow column
   ran to five. `overflow-wrap: anywhere` is what stops a long single-word player
   name (tennis is full of them) from overflowing onto the kit. */
.live-md-team-name {
    min-height: 0;
    width: 100%;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    overflow-wrap: anywhere;
    text-align: center;
}

/* ...and in the desktop rail it must stop being sticky.
   `.lms-stripe` is `position: sticky; top: 60px; z-index: 90` — written when the
   stripe lived in the single-column page and was meant to pin under the app
   header as you scrolled the markets. In the rail it now sits directly ABOVE the
   video, so the moment anything scrolls it pins and the player slides underneath
   it — the stripe painting over the top of the picture. Worse on sports with no
   pitch (tennis, basketball), where the stripe is the first thing in the rail and
   lands squarely across the video.
   The rail is itself sticky and scrolls as one unit, so the stripe has nothing
   left to pin against here. Mobile keeps the pinning behaviour. */
@media (min-width: 981px) {
    .live-md-side #live-md-scout-stripe {
        position: static;
    }
}

/* ============================================================================
   CRYPTO CASHIER  (js/cryptopay.js — the 'Crypto' tab inside Money Transfer)
   Sits on top of the .mt-* cashier styles and reuses .mt-form / .mt-input /
   .mt-submit-btn, so the two rails look like one cashier. Every colour and
   radius goes through a token — see DESIGN-SYSTEM.md.
   ========================================================================== */

.cp-wrap { display: flex; flex-direction: column; gap: 16px; }

/* Deposit / Withdrawal toggle inside the tab */
.cp-seg {
    display: flex;
    gap: 4px;
    padding: 4px;
    background: var(--bg-input);
    border-radius: var(--radius-md);
}
.cp-seg-btn {
    flex: 1;
    min-width: 0;                       /* let the label ellipsize instead of forcing width */
    padding: 9px 12px;
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--color-transparent);
    color: var(--text-secondary);
    font-family: var(--font-body);
    font-size: 14px;
    font-weight: 600;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}
.cp-seg-btn:hover  { color: var(--text-primary); }
.cp-seg-btn.active { background: var(--bg-tertiary); color: var(--text-primary); }

/* Saved (permanent) deposit addresses */
.cp-saved { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
.cp-saved-title { font-size: 12px; color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; }
.cp-saved-list { display: flex; flex-wrap: wrap; gap: 8px; }
.cp-saved-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 7px 11px;
    border: 1px solid var(--border-subtle);
    border-radius: 999px;
    background: var(--bg-card);
    color: var(--text-primary);
    font-size: 13px;
    cursor: pointer;
    transition: border-color .15s ease;
}
.cp-saved-chip:hover { border-color: var(--green-soft); }
.cp-saved-cur  { font-weight: 700; }
.cp-saved-addr { color: var(--text-muted); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }

/* Coin picker */
.cp-search { margin: 12px 0 10px; }
.cp-search-input {
    width: 100%;
    padding: 11px 13px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-input);
    color: var(--text-primary);
    font-family: var(--font-body);
    font-size: 14px;
}
.cp-search-input::placeholder { color: var(--text-muted); }
.cp-search-input:focus { outline: none; border-color: var(--green-soft); }

.cp-coin-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(215px, 1fr));
    gap: 8px;
    max-height: 52vh;
    overflow-y: auto;
    padding-right: 2px;
}
.cp-coin {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    min-width: 0;                        /* so .cp-coin-name can ellipsize */
    padding: 10px 12px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--bg-card);
    cursor: pointer;
    text-align: left;
    transition: border-color .15s ease, background .15s ease;
}
.cp-coin:hover { border-color: var(--green-soft); background: var(--bg-hover); }

.cp-coin-icon { width: 28px; height: 28px; flex: 0 0 28px; border-radius: 50%; object-fit: contain; }
.cp-coin-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.cp-coin-name {
    color: var(--text-primary);
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* The network is load-bearing, not decoration: usdttrc20 and usdterc20 are both
   "Tether", and picking the wrong chain loses the transfer. So this line WRAPS
   rather than ellipsizing — a truncated "USDCBSC · Bi…" hides the one field the
   player has to get right. */
.cp-coin-net {
    color: var(--text-muted);
    font-size: 10.5px;
    line-height: 1.35;
    text-transform: uppercase;
    letter-spacing: .02em;
    white-space: normal;
    overflow-wrap: anywhere;
}
.cp-badge-stable {
    flex: 0 0 auto;
    margin-top: 1px;
    padding: 2px 6px;
    border-radius: 999px;
    background: var(--bg-green-deep);
    color: var(--green-soft);
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
}

/* Chosen coin header + back link */
.cp-chosen {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--bg-card);
}
.cp-back {
    align-self: flex-start;
    padding: 6px 2px;
    border: 0;
    background: var(--color-transparent);
    color: var(--text-secondary);
    font-family: var(--font-body);
    font-size: 13px;
    cursor: pointer;
}
.cp-back:hover { color: var(--text-primary); }

.cp-form  { display: flex; flex-direction: column; gap: 14px; }
.cp-mono  { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 13px; }
.cp-hint  { display: block; margin-top: 5px; color: var(--text-muted); font-size: 12px; }
.cp-hint-warn { color: var(--amber); }
.cp-note  { margin: 0; color: var(--text-muted); font-size: 12.5px; line-height: 1.5; }

.cp-error {
    padding: 10px 12px;
    border: 1px solid var(--accent-red);
    border-radius: var(--radius-md);
    background: var(--bg-input);
    color: var(--red-soft);
    font-size: 13px;
}

/* Address screen */
.cp-amount-due {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 14px;
    border-radius: var(--radius-md);
    background: var(--bg-green-deep);
    border: 1px solid var(--green-soft);
}
.cp-amount-label { color: var(--text-muted); font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
.cp-amount-value { color: var(--text-primary); font-size: 21px; font-weight: 700; word-break: break-all; }

.cp-addr-block {
    display: flex;
    flex-direction: column;
    gap: 7px;
    padding: 13px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--bg-card);
}
.cp-addr-block-warn { border-color: var(--amber); }
.cp-addr-label { color: var(--text-muted); font-size: 12px; text-transform: uppercase; letter-spacing: .04em; }
.cp-addr-row { display: flex; align-items: center; gap: 10px; }
.cp-addr {
    flex: 1;
    min-width: 0;
    color: var(--text-primary);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 13px;
    line-height: 1.45;
    /* An address must be readable in full — never truncated. Wrapping mid-string
       is correct here; an ellipsis would hide characters the player must check. */
    word-break: break-all;
}
.cp-copy {
    flex: 0 0 auto;
    padding: 8px 14px;
    border: 1px solid var(--green-soft);
    border-radius: var(--radius-sm);
    background: var(--color-transparent);
    color: var(--green-soft);
    font-family: var(--font-body);
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}
.cp-copy:hover, .cp-copy.copied { background: var(--green-soft); color: var(--bg-primary); }

.cp-warn {
    padding: 11px 13px;
    border-radius: var(--radius-md);
    background: var(--bg-input);
    border-left: 3px solid var(--amber);
    color: var(--text-light);
    font-size: 12.5px;
    line-height: 1.5;
}
.cp-warn strong { color: var(--text-primary); }

/* Live status pill */
.cp-status {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 13px;
    border: 1px solid var(--border-subtle);
    border-radius: var(--radius-md);
    background: var(--bg-card);
    color: var(--text-secondary);
    font-size: 13px;
}
.cp-status-dot {
    width: 9px;
    height: 9px;
    flex: 0 0 9px;
    border-radius: 50%;
    background: var(--text-muted);
    animation: cp-pulse 1.6s ease-in-out infinite;
}
.cp-status.busy .cp-status-dot { background: var(--amber); }
.cp-status.ok   { border-color: var(--green-soft); color: var(--text-primary); }
.cp-status.ok   .cp-status-dot { background: var(--green-soft); animation: none; }
.cp-status.bad  { border-color: var(--accent-red); color: var(--red-soft); }
.cp-status.bad  .cp-status-dot { background: var(--accent-red); animation: none; }

@keyframes cp-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .3; } }

@media (prefers-reduced-motion: reduce) {
    .cp-status-dot { animation: none; }
}

/* Withdrawal submitted */
.cp-done { align-items: center; text-align: center; padding: 26px 16px; gap: 10px; }
.cp-done-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 54px;
    height: 54px;
    border-radius: 50%;
    background: var(--bg-green-deep);
    color: var(--green-soft);
    font-size: 27px;
}
.cp-done-title  { color: var(--text-primary); font-size: 17px; font-weight: 700; }
.cp-done-amount { color: var(--green-soft); font-size: 23px; font-weight: 700; }

@media (max-width: 480px) {
    .cp-coin-grid  { grid-template-columns: 1fr 1fr; max-height: none; }
    .cp-coin       { padding: 9px 10px; }
    .cp-addr-row   { flex-direction: column; align-items: stretch; }
    .cp-copy       { width: 100%; padding: 10px; }
}


/* ── Crypto coin select ────────────────────────────────────────────────────
   Replaces the old card grid: 159 coins never fitted a grid, and the network
   line kept getting squeezed. A select + search scales, and keeps the network
   on its own uncramped line where a player can actually read it. */

.cp-field { display: flex; flex-direction: column; gap: 8px; position: relative; }
.cp-field-label {
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 600;
}

.cp-select {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 12px 14px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-card);
    color: var(--text-primary);
    font-family: var(--font-body);
    text-align: left;
    cursor: pointer;
    transition: border-color .15s ease;
}
.cp-select:hover, .cp-select.open { border-color: var(--green-soft); }
.cp-select-face { display: flex; align-items: center; gap: 12px; flex: 1; min-width: 0; }
.cp-select-placeholder { color: var(--text-muted); font-size: 14px; }

.cp-chevron { width: 20px; height: 20px; flex: 0 0 20px; color: var(--text-muted); transition: transform .18s ease; }
.cp-select.open .cp-chevron { transform: rotate(180deg); }

/* Dropdown panel — absolute so it overlays rather than shoving the form down. */
.cp-select-panel {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 30;
    margin-top: 6px;
    padding: 10px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-md);
    background: var(--bg-deep);
    box-shadow: 0 12px 32px rgba(0, 0, 0, .45);
}
.cp-select-panel[hidden] { display: none; }

.cp-select-list {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 300px;
    overflow-y: auto;
    scrollbar-width: thin;
}

.cp-opt {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    padding: 9px 10px;
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--color-transparent);
    text-align: left;
    cursor: pointer;
    transition: background .12s ease;
}
.cp-opt:hover    { background: var(--bg-hover); }
.cp-opt.selected { background: var(--bg-green-deep); }

.cp-opt-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.cp-opt-name {
    color: var(--text-primary);
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Network wraps rather than truncating — see the note on .cp-coin-net. */
.cp-opt-net {
    color: var(--text-muted);
    font-size: 11.5px;
    line-height: 1.35;
    white-space: normal;
    overflow-wrap: anywhere;
}

.cp-icon {
    width: 32px;
    height: 32px;
    flex: 0 0 32px;
    border-radius: 50%;
    object-fit: contain;
    background: var(--bg-input);
}
.cp-icon-fallback {
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text-secondary);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: -.02em;
}

@media (max-width: 480px) {
    /* Four tabs share the width instead of overflowing into a scrollbar. */
    .mt-tab { min-width: 0; padding: 9px 4px; font-size: 12px; }
    .cp-select-list { max-height: 46vh; }
}

/* ── Crypto cashier: focus, touch, scroll containment ──────────────────────
   Every control here is a custom-styled <button> on a dark surface, where the
   UA's default focus ring is effectively invisible — without these the whole
   cashier is unusable by keyboard. :focus-visible so pointer users don't get a
   ring on click. */
.cp-select:focus-visible,
.cp-opt:focus-visible,
.cp-copy:focus-visible,
.cp-seg-btn:focus-visible,
.cp-saved-chip:focus-visible,
.cp-back:focus-visible,
.cp-search-input:focus-visible {
    outline: 2px solid var(--accent-green-neon);
    outline-offset: 2px;
    border-radius: var(--radius-sm);
}

/* Removes the 300ms tap delay and the grey flash on the coin list. */
.cp-select,
.cp-opt,
.cp-copy,
.cp-seg-btn,
.cp-saved-chip,
.cp-back {
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
}

/* Scrolling to the end of the coin list must not start scrolling the page. */
.cp-select-list {
    overscroll-behavior: contain;
}

/* Amounts line up digit-for-digit when they change during polling. */
.cp-amount-value,
.cp-done-amount {
    font-variant-numeric: tabular-nums;
}

.cp-list-more {
    padding: 9px 10px;
    color: var(--text-muted);
    font-size: 12px;
    text-align: center;
}

/* Group headers inside the coin list ("Suggested" / "All cryptocurrencies"). */
.cp-list-head {
    padding: 10px 10px 5px;
    color: var(--text-muted);
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .06em;
}
.cp-list-head:first-child { padding-top: 2px; }

/* Tab labels now carry an icon. Column on narrow screens so four tabs still fit
   without the label shrinking to nothing. */
.mt-tab {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
}
.mt-tab-icon { width: 16px; height: 16px; flex: 0 0 16px; opacity: .75; }
.mt-tab.active .mt-tab-icon { opacity: 1; }

@media (max-width: 560px) {
    .mt-tab { flex-direction: column; gap: 3px; padding: 7px 3px; font-size: 11px; line-height: 1.2; }
    .mt-tab-icon { width: 18px; height: 18px; flex: 0 0 18px; }
}

/* The crypto form reuses .profile-input / .profile-label from the bank form —
   the earlier .mt-input/.mt-label were invented and matched nothing, which is
   why the amount box rendered as a raw browser input. */
.cp-currency-suffix { color: var(--text-muted); font-weight: 600; }
.cp-form .profile-input,
.cp-wrap .profile-input { width: 100%; }
.cp-wrap .mt-field { margin-bottom: 2px; }

/* "Add your email" nudge in the crypto cashier. */
.cp-nudge {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 13px;
    border: 1px solid var(--border-subtle);
    border-left: 3px solid var(--amber);
    border-radius: var(--radius-md);
    background: var(--bg-card);
}
.cp-nudge-text { flex: 1; min-width: 0; color: var(--text-light); font-size: 12.5px; line-height: 1.5; }
.cp-nudge-actions { display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }
.cp-nudge-link {
    color: var(--green-soft);
    font-size: 12.5px;
    font-weight: 700;
    text-decoration: none;
    white-space: nowrap;
}
.cp-nudge-link:hover { text-decoration: underline; }
.cp-nudge-x {
    border: 0;
    background: var(--color-transparent);
    color: var(--text-muted);
    font-size: 19px;
    line-height: 1;
    cursor: pointer;
    padding: 0 2px;
    touch-action: manipulation;
}
.cp-nudge-x:hover { color: var(--text-primary); }
.cp-nudge-link:focus-visible, .cp-nudge-x:focus-visible {
    outline: 2px solid var(--accent-green-neon);
    outline-offset: 2px;
}

/* QR of the deposit address. Always on a white plate with a quiet zone —
   scanners need the light background and the margin regardless of page theme,
   and a QR rendered straight onto the dark surface often will not read. */
[data-cp-addr-slot] {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.cp-qr {
    align-self: center;
    width: fit-content;
    margin-inline: auto;
    padding: 16px;
    background: #ffffff;          /* spec requirement, not a theme colour */
    border-radius: 0;
    line-height: 0;
    box-shadow: 0 10px 28px rgba(0, 0, 0, .32), 0 0 0 1px rgba(255, 255, 255, .06);
}
.cp-qr-inner { position: relative; display: block; }
.cp-qr svg { display: block; width: 196px; height: 196px; }

/* Coin logo knocked into the middle. Sized at 20% — verified decodable to 32%
   (see cryptopay.js), so this keeps real-world margin. The white pad is what
   makes it legible without eating extra modules. */
.cp-qr-logo {
    position: absolute;
    inset: 0;
    margin: auto;
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 5px;
    background: #ffffff;
    border-radius: 0;
    line-height: 0;
}
.cp-qr-logo .cp-icon {
    width: 100%;
    height: 100%;
    flex: none;
    background: transparent;
}

/* Icon-only copy button. */
.cp-copy {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    border: 1px solid var(--green-soft);
    border-radius: var(--radius-sm);
    background: var(--color-transparent);
    color: var(--green-soft);
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}
.cp-copy:hover { background: var(--green-soft); color: var(--bg-primary); }
.cp-copy-i, .cp-copy-ok { width: 18px; height: 18px; }
.cp-copy-ok { display: none; }
.cp-copy.copied { background: var(--green-soft); color: var(--bg-primary); }
.cp-copy.copied .cp-copy-i  { display: none; }
.cp-copy.copied .cp-copy-ok { display: block; }

@media (max-width: 480px) {
    .cp-qr svg { width: 168px; height: 168px; }
    /* The address wraps onto its own line, so the button keeps its square shape
       rather than stretching full width as the old text button did. */
    .cp-addr-row { flex-direction: row; align-items: center; }
    .cp-copy { width: 44px; height: 44px; }   /* comfortable touch target */
}


/* The withdrawal confirmation replaces a tall form, so on a phone it can render
   entirely above the current scroll position — the player sees the footer and
   assumes nothing happened. Scrolled into view by cryptopay.js; this keeps the
   sticky header from covering it when it lands. */
.cp-done {
    scroll-margin-top: calc(var(--header-height, 60px) + 12px);
}

/* ==========================================================================
   Management (#MG) — operator back-office. MANAGEMENT-PORT-PLAN.md §5.
   Extends the existing dash- / rpt- vocabulary rather than starting a second
   one. Every colour is a token; the legacy evo365 stylesheet is not ported.
   ========================================================================== */

/* Stands alone rather than extending .profile-page, whose 640px cap squeezed
   the tree, the finance board and the ticket list into half the desktop width.
   Centring and the page title style are supplied here instead. */
.mg-page { max-width: 1200px; margin: 0 auto; }
.mg-page .profile-page-title { margin: 0 0 20px; font-size: 24px; font-weight: 700; }

.mg-head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 16px; flex-wrap: wrap; margin-bottom: 4px;
}
.mg-title { margin-bottom: 4px; }
.mg-sub { font-size: 13px; color: var(--text-secondary); display: flex; align-items: center; gap: 8px; }

/* Role identity. One hue per level, reused by the chip and the tree avatar so
   a manager reads the same everywhere. Administrator and supermanager share
   the shield glyph, so the tint is what separates them. */
.mg-role-administrator { --mg-role: var(--accent-red); }
.mg-role-supervisor    { --mg-role: var(--accent-odds); }
.mg-role-supermanager  { --mg-role: var(--accent-orange); }
.mg-role-manager       { --mg-role: var(--accent-green); }
.mg-role-agent         { --mg-role: var(--accent-blue); }
.mg-role-player        { --mg-role: var(--text-muted); }

.mg-role-chip {
    display: inline-flex; align-items: center; padding: 2px 10px;
    border-radius: 999px; font-size: 11px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .04em;
    color: var(--mg-role, var(--text-secondary));
    background: color-mix(in srgb, var(--mg-role, var(--text-muted)) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--mg-role, var(--text-muted)) 35%, transparent);
}

/* --- tabs ---------------------------------------------------------------- */
.mg-tabs {
    display: flex; gap: 4px; margin: 16px 5px; padding: 4px;
    background: var(--bg-input); border-radius: 0;
    overflow-x: auto; scrollbar-width: none;
}
.mg-tabs::-webkit-scrollbar { display: none; }
.mg-tab {
    flex: 0 0 auto; padding: 15px 10px; border: 0; border-radius: 0;
    background: transparent; color: var(--text-muted);
    font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap;
    transition: background .15s, color .15s;
}
.mg-tab:hover { color: var(--text-primary); background: var(--bg-hover); }
.mg-tab.active { color: var(--text-primary); background: var(--bg-tertiary); }

/* --- toolbar ------------------------------------------------------------- */
.mg-toolbar { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.mg-input, .mg-select {
    padding: 9px 12px; border-radius: 0;
    border: 1px solid var(--border-color); background: var(--bg-input);
    color: var(--text-primary); font-size: 13px; font-family: inherit;
}
.mg-input { flex: 1 1 220px; min-width: 0; }
.mg-input::placeholder { color: var(--text-muted); }
.mg-input:focus, .mg-select:focus { outline: 2px solid var(--accent-green); outline-offset: -1px; }

/* --- tree ---------------------------------------------------------------- */
/* Depth is a custom property so one rule handles every level, and the indent
   can be capped on narrow screens without touching the markup. */
.mg-tree { display: flex; flex-direction: column; gap: 2px; }
.mg-node { display: flex; flex-direction: column; }

.mg-row {
    --mg-indent: calc(var(--mg-depth, 0) * 22px);
    display: grid;
    /* The balances column was `auto`, which wins over a 1fr sibling when it has
       content — an account with eight funded currencies collapsed the NAME to
       0px. Both flexible now, with a floor under the name so it can never
       vanish; the chips wrap instead. */
    grid-template-columns: 28px 34px minmax(150px, 1.1fr) minmax(0, 1.6fr) auto;
    align-items: center; gap: 10px;
    padding: 10px 12px 10px calc(12px + var(--mg-indent));
    background: var(--bg-secondary); border-radius: 0;
    border-left: 3px solid transparent;
}
.mg-row:hover { background: var(--bg-hover); }
.mg-row.is-open { border-left-color: var(--mg-role, var(--border-color)); }

.mg-chev {
    display: grid; place-items: center; width: 28px; height: 28px;
    border: 0; border-radius: 0; padding: 0; cursor: pointer;
    background: var(--bg-tertiary); color: var(--text-secondary);
    transition: transform .15s, background .15s;
}
.mg-chev svg { width: 14px; height: 14px; }
.mg-chev:hover { background: var(--bg-darkb); color: var(--text-primary); }
.mg-chev.is-leaf { background: transparent; cursor: default; pointer-events: none; }
.mg-row.is-open .mg-chev { transform: rotate(90deg); }

.mg-avatar {
    display: grid; place-items: center; width: 34px; height: 34px;
    border-radius: 50%; color: var(--mg-role, var(--text-muted));
    background: color-mix(in srgb, var(--mg-role, var(--text-muted)) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--mg-role, var(--text-muted)) 35%, transparent);
}
.mg-avatar svg { width: 17px; height: 17px; }

/* min-width:0 so a long name ellipsises instead of forcing the grid wider. */
.mg-ident { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mg-name {
    font-size: 14px; font-weight: 600; color: var(--text-primary);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mg-role {
    font-size: 11px; font-weight: 600; letter-spacing: .03em;
    color: var(--mg-role, var(--text-muted)); text-transform: uppercase;
}
.mg-count { color: var(--text-muted); }

/* Columns are pinned rather than auto-placed. An account with no funded
   currency has its balances cell removed by the :empty rule below, and
   auto-placement would then slide the status pill up into the balances column —
   leaving it stranded mid-row on exactly those accounts. */
.mg-balances { grid-column: 4; display: flex; gap: 4px; flex-wrap: wrap; justify-content: flex-end; }
.mg-bal {
    font-size: 11px; font-weight: 600; padding: 3px 8px; border-radius: 0;
    background: var(--bg-input); color: var(--text-secondary);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mg-bal.is-zero { color: var(--text-muted); opacity: .55; }

.mg-status {
    grid-column: 5; justify-self: end;   /* pinned — see .mg-balances above */
    font-size: 10px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .04em; padding: 3px 9px; border-radius: 999px; white-space: nowrap;
}
.mg-status.is-active    { color: var(--accent-green);  background: color-mix(in srgb, var(--accent-green) 14%, transparent); }
.mg-status.is-suspended { color: var(--accent-orange); background: color-mix(in srgb, var(--accent-orange) 14%, transparent); }
.mg-status.is-deleted   { color: var(--accent-red);    background: color-mix(in srgb, var(--accent-red) 14%, transparent); }

/* An author `display` beats the UA stylesheet's `[hidden] { display: none }`,
   so a flex container toggled with el.hidden would never actually hide. Both
   collapsible containers here need the attribute selector spelled out. */
.mg-children { display: flex; flex-direction: column; gap: 2px; margin-top: 2px; }
.mg-children[hidden] { display: none; }

.mg-more {
    align-self: flex-start;
    margin: 4px 0 4px calc(12px + var(--mg-depth, 0) * 22px);
    padding: 7px 14px; border-radius: 0; cursor: pointer;
    border: 1px dashed var(--border-color); background: transparent;
    color: var(--text-secondary); font-size: 12px; font-weight: 600; font-family: inherit;
}
.mg-more:hover:not(:disabled) { background: var(--bg-hover); color: var(--text-primary); }
.mg-more:disabled { opacity: .6; cursor: default; }

.mg-child-loading, .mg-child-empty { padding-left: 34px; }

/* --- states -------------------------------------------------------------- */
.mg-empty, .mg-placeholder {
    padding: 28px 20px; text-align: center;
    color: var(--text-secondary); font-size: 13px;
    background: var(--bg-secondary); border-radius: 0;
}
.mg-placeholder-title {
    font-size: 15px; font-weight: 700; color: var(--text-primary); margin-bottom: 6px;
}
.mg-muted { color: var(--text-muted); font-size: 12px; }
.mg-error { color: var(--accent-red); }

/* An account with no funded currency renders no chips at all; collapsing the
   slot keeps rows to one line instead of leaving a stray placeholder. */
.mg-balances:empty { display: none; }

/* --- narrow screens ------------------------------------------------------ */
@media (max-width: 720px) {
    /* Cap the indent: five levels at 22px pushes the name off a phone. */
    .mg-row {
        --mg-indent: calc(min(var(--mg-depth, 0), 3) * 12px);
        grid-template-columns: 26px 30px minmax(0, 1fr) auto;
        row-gap: 6px;
        padding-top: 8px; padding-bottom: 8px;
    }
    /* Place explicitly: without this the status pill is a 5th child in a
       4-column grid and wraps to a third line, tripling the row height. */
    .mg-chev     { grid-column: 1; grid-row: 1; }
    .mg-avatar   { grid-column: 2; grid-row: 1; width: 30px; height: 30px; }
    .mg-ident    { grid-column: 3; grid-row: 1; }
    .mg-status   { grid-column: 4; grid-row: 1; }
    .mg-balances { grid-column: 3 / -1; grid-row: 2; justify-content: flex-start; }
    .mg-more { margin-left: calc(12px + min(var(--mg-depth, 0), 3) * 12px); }
}

/* --- management detail panel --------------------------------------------- */
/* Right-side drawer on desktop, bottom sheet on mobile. 100dvh, not 100vh —
   the iOS URL bar doesn't shrink vh and the footer would clip. */
/* Centred modal on desktop, bottom sheet on mobile (see the 900px query).
   It was a right-hand drawer, which pinned the account against one edge and
   left the tree behind it stranded in dead space. */
.mgp-scrim {
    position: fixed; inset: 0; z-index: 1200;
    background: rgba(0, 0, 0, .6);
    display: flex; align-items: center; justify-content: center; padding: 24px;
    opacity: 0; pointer-events: none; transition: opacity .18s;
}
.mgp-scrim.is-open { opacity: 1; pointer-events: auto; }

.mgp {
    display: flex; flex-direction: column;
    /* Wider than the old 440px drawer: the two-column field grid gets room, so
       labels and values stop wrapping. Capped so the body never over-scrolls. */
    width: min(620px, 100%); max-height: min(86dvh, 900px);
    background: var(--bg-primary);
    border: 1px solid var(--border-color); border-radius: 0;
    box-shadow: 0 24px 64px rgba(0, 0, 0, .5);
    overflow: hidden;                       /* keeps the rounded corners */
    transform: translateY(8px) scale(.99); transition: transform .18s;
}
.mgp-scrim.is-open .mgp { transform: none; }

.mgp-head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 12px; padding: 18px 18px 14px;
    border-bottom: 1px solid var(--border-color);
}
.mgp-ident { min-width: 0; }
.mgp-name {
    font-size: 17px; font-weight: 700; color: var(--text-primary);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mgp-role {
    font-size: 11px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .04em; margin-top: 3px; color: var(--mg-role, var(--text-muted));
}
.mgp-close {
    flex: 0 0 auto; display: grid; place-items: center;
    width: 32px; height: 32px; border: 0; border-radius: 0; cursor: pointer;
    background: var(--bg-tertiary); color: var(--text-secondary);
}
.mgp-close:hover { background: var(--bg-hover); color: var(--text-primary); }
.mgp-close svg { width: 16px; height: 16px; }

.mgp-body { flex: 1 1 auto; overflow-y: auto; padding: 14px 18px 20px; }

.mgp-sec { margin-bottom: 18px; }
.mgp-sec-title {
    font-size: 11px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .06em; color: var(--text-muted); margin-bottom: 8px;
}
.mgp-grid {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px;
    background: var(--border-color); border-radius: 0; overflow: hidden;
}
.mgp-field {
    display: flex; flex-direction: column; gap: 3px; min-width: 0;
    padding: 10px 12px; background: var(--bg-secondary);
}
.mgp-label { font-size: 11px; color: var(--text-muted); }
.mgp-value {
    font-size: 13px; font-weight: 600; color: var(--text-primary);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.mgp-na { color: var(--text-muted); font-weight: 500; }

.mgp-bals { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
.mgp-bal {
    display: flex; align-items: baseline; justify-content: space-between; gap: 8px;
    padding: 9px 12px; border-radius: 0; background: var(--bg-secondary);
}
.mgp-bal span { font-size: 11px; font-weight: 700; color: var(--text-muted); }
.mgp-bal b {
    font-size: 13px; color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    overflow: hidden; text-overflow: ellipsis;
}

.mgp-flag { font-size: 11px; font-weight: 700; text-transform: uppercase; }
.mgp-flag.is-on  { color: var(--accent-green); }
.mgp-flag.is-off { color: var(--text-muted); }

.mgp-foot {
    flex: 0 0 auto; padding: 11px 18px;
    border-top: 1px solid var(--border-color);
    background: var(--bg-input);
    font-size: 11px; color: var(--text-muted); text-align: center;
}

/* The tree row is clickable, so give it a focus ring for keyboard users. */
.mg-row { cursor: pointer; }
.mg-row:focus-visible { outline: 2px solid var(--accent-green); outline-offset: -2px; }

/* The drawer flips to a bottom sheet at 900px, not 720px like the tree rows:
   a 440px side drawer leaves too little of the tree readable below that. Two
   different concerns, so two different breakpoints. */
@media (max-width: 900px) {
    .mgp-scrim { align-items: flex-end; justify-content: stretch; padding: 0; }
    .mgp {
        width: 100%; height: 88dvh; max-height: 88dvh;
        border: 0; border-top: 1px solid var(--border-color);
        border-radius: 0; box-shadow: none;
        transform: translateY(16px);
    }
    .mgp-grid, .mgp-bals { grid-template-columns: minmax(0, 1fr); }
}

/* --- management: sub-tabs, date range, finance, transactions ------------- */
.mg-subtabs { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }
.mg-subtab {
    padding: 6px 14px; border-radius: 999px; cursor: pointer; font-family: inherit;
    border: 1px solid var(--border-color); background: transparent;
    color: var(--text-secondary); font-size: 12px; font-weight: 600;
}
.mg-subtab:hover { background: var(--bg-hover); color: var(--text-primary); }
.mg-subtab.active {
    background: var(--accent-green); border-color: var(--accent-green); color: var(--bg-primary);
}

.mg-range {
    display: flex; gap: 10px; flex-wrap: wrap; align-items: center;
    justify-content: space-between; margin-bottom: 12px;
}
.mg-range-chips { display: flex; gap: 4px; flex-wrap: wrap; }
.mg-chip { font-family: inherit; }
.mg-range-dates { display: flex; align-items: center; gap: 6px; }
.mg-date { padding: 7px 10px; font-size: 12px; }
.mg-range-sep { color: var(--text-muted); }

/* Wide content scrolls inside its own container — the page body never does. */
.mg-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.mgf-totals {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 8px; margin-bottom: 14px;
}
.mgf-total { padding: 12px 14px; border-radius: 0; background: var(--bg-secondary); }
.mgf-total-cur {
    font-size: 11px; font-weight: 700; letter-spacing: .06em;
    color: var(--text-muted); text-transform: uppercase; margin-bottom: 8px;
}
.mgf-total-line {
    display: flex; justify-content: space-between; gap: 8px;
    font-size: 12px; padding: 2px 0; color: var(--text-secondary);
}
.mgf-total-line b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
/* Same weight as the rule above, or the totals card's Difference stays white. */
.mgf-total-line b.dash-pos  { color: var(--accent-green); }
.mgf-total-line b.dash-neg  { color: var(--accent-red); }
.mgf-total-line b.dash-zero { color: var(--text-muted); }
.mgf-total-line.is-diff {
    margin-top: 6px; padding-top: 7px; border-top: 1px solid var(--border-color);
}

/* The converted grand total. Marked out from the per-currency cards beside it
   because it is the one figure on the board that is DERIVED rather than
   reported — the accent border is the tell that a rate was applied. */
.mgf-total.is-eur {
    border: 1px solid var(--accent-green);
    background: var(--bg-hover);
}
.mgf-total.is-eur .mgf-total-cur { color: var(--accent-green); }
/* The rate's own date. Not decoration: a converted total is only as true as the
   rate behind it, so the date travels with the number. */
.mgf-total-asof {
    display: block; margin-top: 3px;
    font-size: 10px; font-weight: 600; letter-spacing: .02em;
    color: var(--text-muted); text-transform: none;
}
/* Currencies the rate table could not price. Named rather than folded in at
   1:1, so the total never quietly swallows money it could not convert. */
.mgf-total-missing {
    margin-top: 7px; padding-top: 6px; border-top: 1px dashed var(--border-color);
    font-size: 10.5px; line-height: 1.35; color: var(--text-muted);
}

.mgf-table { display: flex; flex-direction: column; gap: 2px; }
.mgf-head, .mgf-row, .mgf-cur-row {
    display: grid; grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr));
    gap: 10px; align-items: center; padding: 9px 12px;
}
.mgf-head {
    font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
    color: var(--text-muted); padding-bottom: 4px;
}
.mgf-head span:not(:first-child), .mgf-num { text-align: right; }
.mgf-row { background: var(--bg-secondary); border-radius: 0; }
.mgf-row.has-more { cursor: pointer; }
.mgf-row.has-more:hover { background: var(--bg-hover); }
.mgf-name {
    display: flex; align-items: center; gap: 7px; min-width: 0;
    font-size: 13px; font-weight: 600; color: var(--text-primary);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mgf-chev { display: inline-block; color: var(--text-muted); transition: transform .15s; }
.mgf-row.is-open .mgf-chev { transform: rotate(90deg); }
.mgf-badge {
    font-size: 10px; font-weight: 700; padding: 1px 6px; border-radius: 999px;
    background: var(--bg-tertiary); color: var(--text-muted);
}
.mgf-num { font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.mgf-cur { display: flex; flex-direction: column; gap: 1px; margin: 1px 0 3px; }
.mgf-cur[hidden] { display: none; }   /* see .mg-children[hidden] */
.mgf-cur-row { background: var(--bg-input); border-radius: 0; padding: 7px 12px 7px 30px; }
.mgf-cur-code { font-size: 11px; font-weight: 700; color: var(--text-muted); }

.mgt-table { width: 100%; border-collapse: collapse; font-size: 12.5px; min-width: 620px; }
.mgt-table th {
    text-align: left; padding: 8px 10px; white-space: nowrap;
    font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
    color: var(--text-muted); border-bottom: 1px solid var(--border-color);
}
.mgt-table td {
    padding: 9px 10px; border-bottom: 1px solid var(--border-color);
    color: var(--text-primary); white-space: nowrap;
}
.mgt-table td:last-child { white-space: normal; min-width: 180px; }
/* `.mgt-table td { color: var(--text-primary) }` is (0,1,1) and `.mg-muted` is
   (0,1,0), so the muted class silently did NOTHING inside any management table:
   dates, currencies and secondary counts all rendered at full white and
   competed with the values that matter. Same specificity family as the
   `td:last-child` and `.mgt-r` traps in 14b. */
.mgt-table td.mg-muted { color: var(--text-muted); }
.mgt-table tbody tr:hover { background: var(--bg-hover); }
/* `.mgt-table th { text-align: left }` is MORE specific than a bare `.mgt-r`,
   so right-aligned headers sat left over right-aligned numbers — the header
   and its column visibly out of line. Match the weight. */
.mgt-r { text-align: right; }
.mgt-table th.mgt-r, .mgt-table td.mgt-r { text-align: right; }
.mgt-amt { font-variant-numeric: tabular-nums; font-weight: 600; }
.mgt-table tr.is-pos .mgt-amt { color: var(--accent-green); }
.mgt-table tr.is-neg .mgt-amt { color: var(--accent-red); }

.mgt-pager {
    display: flex; align-items: center; justify-content: center; gap: 12px;
    margin-top: 12px; font-size: 12px; color: var(--text-secondary);
}
.mgt-pager .mg-more { margin: 0; padding: 6px 14px; }

@media (max-width: 720px) {
    .mg-range { flex-direction: column; align-items: stretch; }
    .mg-range-dates { justify-content: space-between; }
    .mg-date { flex: 1 1 0; min-width: 0; }
    .mgf-head, .mgf-row, .mgf-cur-row {
        grid-template-columns: minmax(0, 1.2fr) repeat(3, minmax(0, 1fr));
        gap: 6px; padding-left: 10px; padding-right: 10px;
    }
    .mgf-num, .mgf-head span { font-size: 11.5px; }
}

/* Role dot on a finance row — the tree's colour vocabulary, minus the glyph. */
.mgf-dot {
    flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%;
    background: var(--mg-role, var(--text-muted));
}
.mgf-nametext { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mgf-chev.is-leaf { visibility: hidden; }
.mgf-num i { font-style: normal; font-size: 10px; color: var(--text-muted); }
.mgf-cur-row.is-flat { background: var(--bg-secondary); padding-left: 12px; }

/* --- management: inline editing + toasts --------------------------------- */
.mgp-edit { display: inline-flex; align-items: center; gap: 6px; width: 100%; min-width: 0; }
.mgp-input {
    flex: 1 1 auto; min-width: 0; width: 100%;
    padding: 5px 8px; border-radius: 0;
    border: 1px solid var(--border-color); background: var(--bg-input);
    color: var(--text-primary); font: inherit; font-size: 13px; font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.mgp-input:focus { outline: 2px solid var(--accent-green); outline-offset: -1px; }
.mgp-input:disabled { opacity: .55; }
.mgp-suffix { font-size: 11px; color: var(--text-muted); }

/* Per-field save state — spinner → tick or cross, the legacy's feedback. */
.mgp-state { font-size: 11px; font-weight: 700; min-width: 14px; }
.mgp-state.is-saving { color: var(--text-muted); }
.mgp-state.is-ok     { color: var(--accent-green); }
.mgp-state.is-err    { color: var(--accent-red); }

.mgp-switch { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; }
.mgp-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.mgp-switch-track {
    position: relative; width: 38px; height: 21px; border-radius: 999px;
    background: var(--bg-tertiary); border: 1px solid var(--border-color);
    transition: background .15s, border-color .15s;
}
.mgp-switch-knob {
    position: absolute; top: 2px; left: 2px; width: 15px; height: 15px;
    border-radius: 50%; background: var(--text-muted); transition: transform .15s, background .15s;
}
.mgp-switch input:checked + .mgp-switch-track {
    background: color-mix(in srgb, var(--accent-green) 30%, transparent);
    border-color: var(--accent-green);
}
.mgp-switch input:checked + .mgp-switch-track .mgp-switch-knob {
    transform: translateX(17px); background: var(--accent-green);
}
.mgp-switch input:focus-visible + .mgp-switch-track { outline: 2px solid var(--accent-green); outline-offset: 2px; }
.mgp-switch input:disabled + .mgp-switch-track { opacity: .55; }

/* A field that saved this session, so the eye can find what it changed. */
.mgp-field.is-saved { box-shadow: inset 2px 0 0 var(--accent-green); }

/* The cascade warning is the one thing in the panel that must not be missed. */
.mgp-foot.is-warn { color: var(--accent-orange); background: var(--bg-secondary); }

/* Top-anchored: the detail drawer is a bottom sheet on mobile, so a
   bottom-anchored toast would sit on top of the fields it is reporting on. */
.mg-toasts {
    position: fixed; left: 50%; transform: translateX(-50%);
    top: max(12px, env(safe-area-inset-top));
    z-index: 1400; display: flex; flex-direction: column; gap: 8px;
    width: min(420px, calc(100vw - 24px)); pointer-events: none;
}
.mg-toast {
    display: flex; align-items: flex-start; gap: 10px;
    padding: 11px 14px; border-radius: 0;
    background: var(--bg-secondary); border: 1px solid var(--border-color);
    box-shadow: 0 8px 24px rgba(0, 0, 0, .35);
    color: var(--text-primary); font-size: 13px; font-weight: 600;
    pointer-events: auto; cursor: pointer;
    animation: mg-toast-in .18s ease-out;
}
.mg-toast.is-out { opacity: 0; transform: translateY(-6px); transition: opacity .2s, transform .2s; }
.mg-toast-ico { flex: 0 0 auto; font-weight: 700; }
.mg-toast.is-ok  { border-left: 3px solid var(--accent-green); }
.mg-toast.is-ok  .mg-toast-ico { color: var(--accent-green); }
.mg-toast.is-err { border-left: 3px solid var(--accent-red); }
.mg-toast.is-err .mg-toast-ico { color: var(--accent-red); }
.mg-toast-msg { min-width: 0; overflow-wrap: anywhere; }
@keyframes mg-toast-in { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: none; } }

/* --- management: group select + credit transfer -------------------------- */
.mgp-select { appearance: none; cursor: pointer; padding-right: 22px;
    background-image: linear-gradient(45deg, transparent 50%, var(--text-muted) 50%),
                      linear-gradient(135deg, var(--text-muted) 50%, transparent 50%);
    background-position: calc(100% - 12px) 50%, calc(100% - 7px) 50%;
    background-size: 5px 5px, 5px 5px; background-repeat: no-repeat;
}

/* Money movement gets its own visual weight — it is not another setting. */
.mgp-credit { padding: 12px; border-radius: 0; background: var(--bg-secondary);
    border: 1px solid var(--border-color); }
.mgp-credit .mgp-sec-title { margin-bottom: 10px; }
.mgp-credit-row { display: flex; gap: 8px; margin-bottom: 8px; }
.mgp-credit-row .mgp-input { padding: 8px 10px; }
.mgp-credit-row #mgp-credit-amt { flex: 1 1 auto; min-width: 0; }
.mgp-credit-row #mgp-credit-cur { flex: 0 0 96px; }
.mgp-credit-note { width: 100%; padding: 8px 10px; margin-bottom: 10px; font-weight: 500; }
.mgp-credit-actions { display: flex; align-items: center; gap: 8px; }
.mgp-btn { flex: 1 1 0; padding: 9px 12px; border-radius: 0; cursor: pointer;
    border: 1px solid transparent; font: inherit; font-size: 13px; font-weight: 700; }
.mgp-btn:disabled { opacity: .55; cursor: default; }
.mgp-btn.is-add { background: color-mix(in srgb, var(--accent-green) 18%, transparent);
    border-color: var(--accent-green); color: var(--accent-green); }
.mgp-btn.is-add:hover:not(:disabled) { background: color-mix(in srgb, var(--accent-green) 28%, transparent); }
.mgp-btn.is-take { background: color-mix(in srgb, var(--accent-red) 18%, transparent);
    border-color: var(--accent-red); color: var(--accent-red); }
.mgp-btn.is-take:hover:not(:disabled) { background: color-mix(in srgb, var(--accent-red) 28%, transparent); }
.mgp-credit-hint { margin-top: 8px; font-size: 11px; color: var(--text-muted); }

/* --- management: in-app confirm ------------------------------------------ */
/* Replaces window.confirm, which mobile Safari makes easy to miss. */
.mg-confirm-scrim {
    position: fixed; inset: 0; z-index: 1500;
    display: flex; align-items: center; justify-content: center; padding: 20px;
    background: rgba(0, 0, 0, .6);
}
.mg-confirm {
    width: min(380px, 100%); padding: 20px;
    background: var(--bg-secondary); border: 1px solid var(--border-color);
    border-radius: 0; box-shadow: 0 18px 48px rgba(0, 0, 0, .45);
    animation: mg-toast-in .16s ease-out;
}
.mg-confirm-msg { font-size: 14px; font-weight: 600; color: var(--text-primary); line-height: 1.45; }
.mg-confirm-actions { display: flex; gap: 8px; margin-top: 18px; }
.mg-confirm-btn {
    flex: 1 1 0; padding: 10px 14px; border-radius: 0; cursor: pointer;
    font: inherit; font-size: 13px; font-weight: 700; border: 1px solid var(--border-color);
    background: var(--bg-tertiary); color: var(--text-secondary);
}
.mg-confirm-btn.is-cancel:hover { background: var(--bg-hover); color: var(--text-primary); }
.mg-confirm-btn.is-ok {
    background: var(--accent-green); border-color: var(--accent-green); color: var(--bg-primary);
}
.mg-confirm-btn.is-ok.is-danger {
    background: var(--accent-red); border-color: var(--accent-red); color: var(--text-primary);
}
.mg-confirm-btn:focus-visible { outline: 2px solid var(--text-primary); outline-offset: 2px; }

/* --- management: finance table + drill-down ------------------------------ */
/* Same scrollable-table treatment as Transactions: the sport board carries nine
   columns and a grid squeezed the NAME to a few characters on a phone. */
.mgf-tbl { min-width: 780px; }
/* `.mgt-table td:last-child { min-width: 180px; white-space: normal }` exists
   for the Transactions description column, which SHOULD wrap. On this board the
   last column is "Live" — a ticket count — so that rule reserved 180px for a
   4-digit number, flung it to the far right of the table, and manufactured most
   of the horizontal scroll on its own. */
.mgf-tbl td:last-child { min-width: 0; white-space: nowrap; }
/* The casino boards have no commission column and no ticket counts — four
   columns, not eight — so the sport board's floor would leave half the table
   empty and scrolling for nothing. Still wide enough that a long account name
   and six-figure sums do not fight over a phone's width. */
.mgf-tbl.is-narrow { min-width: 460px; }
.mgf-tbl th, .mgf-tbl td { white-space: nowrap; }

/* The name stays put while the figures scroll under it — without this you lose
   track of which account a row belongs to two columns in. */
.mgf-sticky {
    position: sticky; left: 0; z-index: 1;
    background: var(--bg-primary);
    min-width: 150px; max-width: 220px;
}
.mgf-tbl tbody tr:hover .mgf-sticky { background: var(--bg-hover); }
.mgf-tbl thead .mgf-sticky { background: var(--bg-primary); }

.mgf-drill {
    display: inline-flex; align-items: center; gap: 7px; max-width: 100%;
    padding: 0; border: 0; background: none; cursor: pointer;
    font: inherit; font-size: 12.5px; font-weight: 600; color: var(--text-primary);
    text-align: left;
}
.mgf-drill:hover .mgf-nametext { color: var(--accent-green); text-decoration: underline; }
.mgf-drill .mgf-nametext { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.mgf-crumbs {
    display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
    margin-bottom: 10px; font-size: 12px;
}
.mgf-crumb {
    padding: 4px 9px; border-radius: 0; cursor: pointer; font: inherit; font-size: 12px;
    border: 1px solid var(--border-color); background: var(--bg-secondary); color: var(--text-secondary);
}
.mgf-crumb:hover { background: var(--bg-hover); color: var(--text-primary); }
.mgf-crumb.is-current {
    border-color: transparent; background: transparent;
    color: var(--text-primary); font-weight: 700; cursor: default; padding-left: 0;
}
.mgf-crumb-sep { color: var(--text-muted); }

@media (max-width: 720px) {
    /* Six currencies stacked one per row pushed the actual table two screens
       down. Swipe them sideways instead, so the figures start near the top. */
    .mgf-totals {
        display: flex; gap: 8px; overflow-x: auto; scroll-snap-type: x proximity;
        -webkit-overflow-scrolling: touch; padding-bottom: 4px;
    }
    .mgf-totals::-webkit-scrollbar { display: none; }
    .mgf-total { flex: 0 0 auto; min-width: 190px; scroll-snap-align: start; padding: 10px 12px; }
    .mgf-total-line { font-size: 11.5px; }

    /* The date range wrapped onto three rows; the chips fit one line scrolled. */
    .mg-range-chips {
        display: flex; flex-wrap: nowrap; overflow-x: auto; gap: 6px;
        -webkit-overflow-scrolling: touch;
    }
    /* Blink gives input[type=date] a hard intrinsic minimum — min-width: 0 does
       NOT override it. Below ~334px the two inputs therefore forced this row to
       319px and dragged the whole page into a horizontal scroll. Wrapping costs
       a second line only on those narrowest screens; everywhere else they still
       share one row. Shared with the finance boards, which had the same bug. */
    .mg-range { min-width: 0; }
    .mg-range-dates { flex-wrap: wrap; min-width: 0; }
    .mg-range-chips::-webkit-scrollbar { display: none; }
    .mg-range-chips .mg-chip { flex: 0 0 auto; }
}

/* --- management: finance tree -------------------------------------------- */
/* Depth indent lives on the sticky name cell so nesting survives the sideways
   scroll — the figures move, the hierarchy stays put. */
/* `.mgt-table td { padding: 9px 10px }` is more specific than `.mgf-sticky`, and
   its shorthand resets padding-left — so the indent needs to match that weight
   or the tree renders flat. */
.mgf-tbl td.mgf-sticky, .mgf-tbl th.mgf-sticky {
    padding-left: calc(10px + var(--mgf-depth, 0) * 16px);
}
.mgf-chev { display: inline-block; width: 10px; color: var(--text-muted); flex: 0 0 auto; }
/* A player row is the end of the tree: the chevron's slot is KEPT so names stay
   aligned down the column, but it holds nothing to click. */
.mgf-drill.is-leaf .mgf-chev { visibility: hidden; }
/* Where a player's rounds can be opened, the name reads as the link it is. */
.mgf-drill.is-leaf:not(:disabled):hover .mgf-nametext { color: var(--accent-green); }
/* Sport has no rounds view until the Tickets board lands. Show it as inert
   rather than dangling a link into a placeholder. */
.mgf-drill.is-leaf:disabled { cursor: default; }
.mgf-drill.is-leaf:disabled:hover .mgf-nametext { color: inherit; text-decoration: none; }
.mgf-node.is-open .mgf-chev { color: var(--text-primary); }
/* Every currency of an account, one after another: the name cell spans its lines
   (rowspan, mgfinance.js _nodeHtml), centred on them; lines 2..n carry the figures
   alone, divided from each other more lightly than from the next account. */
.mgf-tbl td.mgf-sticky[rowspan] { vertical-align: middle; }
.mgf-node.is-multi td:not(.mgf-sticky), .mgf-extra:has(+ .mgf-extra) td { border-bottom-color: var(--border-subtle); }
.mgf-extra td { padding-top: 7px; padding-bottom: 7px; }
/* The currency after an amount ("4,254.00 L"): quieter than the figure. */
.mgf-sym { color: var(--text-muted); font-weight: 600; }
/* An expanded branch's accounts (mgfinance.js / mgtickets.js, _branch): its colour
   (--mg-br) tints them and runs down beside their names; the parent that opened it
   carries the same colour (--mg-op) on its own name, so the group reads from its head
   to its last account, and the next branch in another colour. */
.mg-br-1 { --mg-br: var(--mg-branch-1-rgb); } .mg-op-1 { --mg-op: var(--mg-branch-1-rgb); }
.mg-br-2 { --mg-br: var(--mg-branch-2-rgb); } .mg-op-2 { --mg-op: var(--mg-branch-2-rgb); }
.mg-br-3 { --mg-br: var(--mg-branch-3-rgb); } .mg-op-3 { --mg-op: var(--mg-branch-3-rgb); }
.mg-br-4 { --mg-br: var(--mg-branch-4-rgb); } .mg-op-4 { --mg-op: var(--mg-branch-4-rgb); }
.mg-br-5 { --mg-br: var(--mg-branch-5-rgb); } .mg-op-5 { --mg-op: var(--mg-branch-5-rgb); }
.mg-br-6 { --mg-br: var(--mg-branch-6-rgb); } .mg-op-6 { --mg-op: var(--mg-branch-6-rgb); }
.mgf-tbl tr.mg-br td { background-color: rgba(var(--mg-br), .08); }
.mgf-tbl tr.mg-br td.mgf-sticky {
    background: linear-gradient(rgba(var(--mg-br), .08), rgba(var(--mg-br), .08)), var(--bg-primary);
    box-shadow: inset 3px 0 0 rgba(var(--mg-br), .85);
}
.mgf-tbl tr.mg-op td.mgf-sticky { box-shadow: inset 3px 0 0 rgba(var(--mg-op), .95); }
.mgf-tbl tr.mg-br:hover td.mgf-sticky { background: var(--bg-hover); }
.mgf-childnote td { padding: 6px 10px; font-size: 11.5px; }

/* --- management: finance currency chips ---------------------------------- */
.mgf-curchips { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.mgf-curchip {
    min-width: 40px; padding: 5px 12px; border-radius: 999px; cursor: pointer;
    font: inherit; font-size: 12px; font-weight: 700;
    border: 1px solid var(--border-color); background: var(--bg-secondary); color: var(--text-secondary);
}
.mgf-curchip:hover { background: var(--bg-hover); color: var(--text-primary); }
.mgf-curchip.active {
    background: var(--accent-green); border-color: var(--accent-green); color: var(--bg-primary);
}

/* --- management: one player's rounds (Finance leaf drill-in) ------------- */
/* A modal over the board, same shape as the account panel. The board stays
   mounted underneath, so dismissing costs no query and loses no expansion. */
.mga-scrim {
    position: fixed; inset: 0; z-index: 1200;
    background: rgba(0, 0, 0, .6);
    display: flex; align-items: center; justify-content: center; padding: 24px;
    opacity: 0; pointer-events: none; transition: opacity .18s;
}
.mga-scrim.is-open { opacity: 1; pointer-events: auto; }
.mga {
    display: flex; flex-direction: column;
    /* Wider than the account panel: this one holds a five-column table. */
    width: min(760px, 100%); max-height: min(86dvh, 900px);
    background: var(--bg-primary);
    border: 1px solid var(--border-color); border-radius: 0;
    box-shadow: 0 24px 64px rgba(0, 0, 0, .5);
    overflow: hidden;                       /* keeps the rounded corners */
    transform: translateY(8px) scale(.99); transition: transform .18s;
}
.mga-scrim.is-open .mga { transform: none; }
.mga-body { flex: 1 1 auto; overflow-y: auto; padding: 14px 18px 20px; }

.mga-head {
    display: flex; align-items: flex-start; justify-content: space-between;
    gap: 12px; padding: 18px 18px 14px;
    border-bottom: 1px solid var(--border-color);
}
.mga-title { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.mga-who  { font-size: 14px; font-weight: 700; color: var(--text-primary); }
.mga-what {
    font-size: 11px; font-weight: 600; letter-spacing: .05em;
    color: var(--text-muted); text-transform: uppercase;
}

.mga-summary {
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    margin-bottom: 12px; padding: 10px 12px;
    border-radius: 0; background: var(--bg-secondary);
    font-size: 12px; color: var(--text-secondary);
}
.mga-who { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mga-sum b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
/* Same weight as the rule above, or the round total's colour is overridden. */
.mga-sum b.dash-pos  { color: var(--accent-green); }
.mga-sum b.dash-neg  { color: var(--accent-red); }
.mga-sum b.dash-zero { color: var(--text-muted); }
.mga-count { margin-left: auto; color: var(--text-muted); }

/* Denser than the finance boards, deliberately. That board lists accounts —
   tens of rows you read. This lists one player's rounds, often hundreds, which
   you SCAN: every pixel of row height is a row you have to scroll past. */
.mga-tbl { min-width: 440px; font-size: 11.5px; }
.mga-tbl th { padding: 6px 8px; font-size: 9.5px; }
.mga-tbl td { padding: 5px 8px; }
/* `.mgt-table td:last-child { min-width: 180px }` reserved half a phone's width
   for Difference alone, which pushed Bet and Win off-screen entirely — the two
   columns most of the table exists for. */
.mga-tbl td:last-child { min-width: 0; white-space: nowrap; }
/* The game name is the only variable-width thing here. Truncate it rather than
   let "Immersive Roulette Deluxe" shove the amounts out of view. */
.mga-tbl .mgf-sticky { min-width: 104px; max-width: 148px; }
.mga-tbl td.mgf-sticky { overflow: hidden; }

/* Live / arcade / other. Only rendered when the player actually mixed them. */
.mga-chips { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.mga-chip { min-width: 0; }

/* A gameindex in neither catalog: shown as its raw id rather than dropped or
   given a name it has not earned. Monospaced so it reads as an id, not a title. */
.mga-game.is-raw {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 11.5px; color: var(--text-muted); font-weight: 500;
}
/* A cancelled stake is netted out of the total, so the badge is what makes that
   adjustment visible instead of silent. */
.mga-badge {
    margin-left: 6px; padding: 1px 6px; border-radius: 999px;
    font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
    background: var(--bg-tertiary); color: var(--text-muted);
}
.mga-cancelled td { opacity: .72; }
.mga-more { margin-top: 10px; width: 100%; }
.mga-tbl th, .mga-tbl td { white-space: nowrap; }
.mga-game {
    display: inline-block; max-width: 100%; vertical-align: bottom;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-weight: 600; color: var(--text-primary);
}

@media (max-width: 720px) {
    .mga-summary { gap: 8px; font-size: 11.5px; padding: 8px 10px; }
    .mga-count { margin-left: 0; }
    /* Tighter again on a phone, where the row count that fits on one screen is
       the whole difference between scanning and scrolling. */
    .mga-tbl { min-width: 400px; font-size: 11px; }
    .mga-tbl td { padding: 4px 7px; }
    .mga-tbl th { padding: 5px 7px; }
    .mga-tbl .mgf-sticky { min-width: 92px; max-width: 124px; }
}

@media (max-width: 900px) {
    /* Bottom sheet, like the account panel. 100dvh-relative height — the iOS
       URL bar does not shrink vh and the last rounds would clip. */
    .mga-scrim { padding: 0; align-items: flex-end; }
    .mga {
        width: 100%; max-height: 88dvh;
        border-radius: 0; border-bottom: 0;
        transform: translateY(16px);
    }
    .mga-head { padding: 14px 14px 12px; }
    .mga-body { padding: 12px 14px 18px; }
}

/* --- management: export button ------------------------------------------ */
.mg-export {
    display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto;
    padding: 6px 12px; border-radius: 0; cursor: pointer;
    font: inherit; font-size: 12px; font-weight: 600;
    border: 1px solid var(--border-color);
    background: var(--bg-secondary); color: var(--text-secondary);
}
.mg-export:hover { background: var(--bg-hover); color: var(--text-primary); border-color: var(--accent-green); }
.mg-export svg { width: 14px; height: 14px; flex: 0 0 auto; }
.mg-export:focus-visible { outline: 2px solid var(--accent-green); outline-offset: 2px; }

/* The product tabs scroll sideways on a phone; the export button must NOT be
   dragged off with them, so it sits outside the scroller and holds its place. */
.mgf-bar { display: flex; align-items: center; gap: 10px; min-width: 0; }
.mgf-bar .mg-subtabs { flex: 1 1 auto; min-width: 0; }

/* In the modal header it sits beside the close button. */
.mga-head .mg-export { margin-left: auto; }
@media (max-width: 480px) {
    /* Label out, icon only — the header already carries the player's name and
       that is what must not be truncated. */
    .mga-head .mg-export span { display: none; }
    .mga-head .mg-export { padding: 6px 9px; }
}

/* --- management: sticky table headers ------------------------------------ */
/*
   WHY THE CONTAINER HAS TO SCROLL, NOT THE PAGE
   `.mg-scroll` sets `overflow-x: auto`, and per spec that forces `overflow-y`
   to `auto` as well — so it is ALREADY a scroll container. A `position: sticky`
   header inside it sticks to THAT scrollport, never to the viewport, and with
   an auto height there is nothing to stick against. Bounding the height is what
   turns it into a real vertical scroller and makes the header work.

   `max-height` and not `height`: a short table renders at its natural height
   with no scrollbar at all, so a three-row board is untouched. Only tables long
   enough for the problem to exist get the treatment.
*/
/* The finance boards get NO max-height: a nested vertical scroller inside a
   page that also scrolls is miserable on a phone. They keep page scrolling and
   use the floating header below instead. The MODAL keeps the bounded scroller,
   because a dialog is already a bounded box — there is no second scroll to
   fight with. */

/* In the modal the height is already bounded by the dialog, so the table area
   takes what is left and the summary, chips and Load-more stay put around it. */
.mga-body { display: flex; flex-direction: column; overflow: hidden; }
.mga-body > .mg-scroll-v { flex: 0 1 auto; min-height: 0; max-height: none; }
.mga-body > .mga-more { flex: 0 0 auto; }

.mga-body .mg-scroll-v thead th {
    position: sticky; top: 0; z-index: 2;
    background: var(--bg-primary);
}
/* The name column is sticky horizontally; in the header it must be sticky in
   BOTH axes and sit above the rest, or the corner cell is overlapped by
   whichever of the two neighbours paints last. */
.mga-body .mg-scroll-v thead th.mgf-sticky { left: 0; z-index: 3; }

/* `border-collapse: collapse` gives the border to the TABLE, not the cell, so a
   sticky header leaves its underline behind as it moves. An inset shadow is
   painted by the cell and travels with it. */
.mga-body .mg-scroll-v thead th { border-bottom: 0; box-shadow: inset 0 -1px 0 var(--border-color); }

/* --- management: floating column header on the finance boards ------------ */
/*
   Same idea as `.live-league-header`: sticky against the PAGE, pinned just
   under the app header. It cannot be the table's own <thead> — that lives
   inside `.mg-scroll`, whose `overflow-x: auto` makes it a scroll container,
   and a sticky child can only ever stick to its nearest scroll container.

   So the header is rendered a second time into a bar that sits OUTSIDE the
   scroller, in page flow. `height: 0` so it reserves no space and cannot push
   the table down; the copy is absolutely positioned within it.
*/
.mgf-stickhead {
    position: sticky;
    top: var(--header-height, 60px);
    height: 0;                     /* occupies no flow space */
    z-index: 40;                   /* under the app header (100), over the rows */
    pointer-events: none;          /* it is a label, not a control */
}
.mgf-stickhead-clip {
    position: absolute; top: 0; left: 0; right: 0;
    overflow: hidden;              /* hides the part scrolled off sideways */
    opacity: 0; transition: opacity .12s;
}
.mgf-stickhead.is-on .mgf-stickhead-clip { opacity: 1; }
.mgf-stickhead table {
    background: var(--bg-primary);
    /* Its own bottom edge, since it is detached from the table's borders. */
    box-shadow: 0 1px 0 var(--border-color), 0 6px 14px rgba(0, 0, 0, .28);
}
/* The name column must hold still while the rest slides sideways, exactly as it
   does in the real table — but sticky cannot help here (the clip has no scroll
   of its own), so JS counter-translates it by the same offset. */
.mgf-stickhead th.mgf-sticky { background: var(--bg-primary); position: relative; z-index: 1; }

/* --- management: thin horizontal scrollbars ------------------------------ */
/*
   The global `::-webkit-scrollbar { width: 6px }` only governs VERTICAL bars —
   a horizontal one is sized by `height`, which that rule never sets, so every
   sideways scroller in the app falls back to the browser default (~15px). On
   the management tables that is a thick grey slab directly under the last row.

   Scoped to `.mg-scroll` rather than fixed globally: the global rule is shared
   with every promo rail and tab strip in the app, and this is not the change to
   quietly alter all of them with.
*/
/*
   Deliberately NOT `scrollbar-width: thin`. Chrome ignores every
   `::-webkit-scrollbar` rule the moment that standard property is present, hands
   the rendering to the browser, and on macOS that means an OVERLAY bar — zero
   height, and invisible until you already know to swipe. The horizontal bar IS
   the only cue that these tables extend past the screen edge, so it stays
   visible at the same 6px the app uses vertically.
*/
.mg-scroll::-webkit-scrollbar { width: 6px; height: 6px; }
.mg-scroll::-webkit-scrollbar-track { background: transparent; }
.mg-scroll::-webkit-scrollbar-thumb { background: var(--bg-hover); border-radius: 0; }
.mg-scroll::-webkit-scrollbar-thumb:hover { background: var(--border-color); }
/* Kills the little square where the two bars would meet. */
.mg-scroll::-webkit-scrollbar-corner { background: transparent; }

/* --- management: tickets board ------------------------------------------- */
/*
   A GRID, not a wrapping flex row. Flex sized each control by its own content,
   so "Të përjashtuara" came out half again as wide as "Të gjithë" and the row
   read as six unrelated things at six different widths. Equal tracks make the
   group read as one control surface, and they reflow without a media query.

   `align-items: end` on the bar so the Export button lines up with the CONTROLS,
   not with the label text above them.
*/
/* Finance's bar gets its gap-below from `.mg-subtabs { margin-bottom: 12px }`
   INSIDE it. This bar holds plain buttons with no such margin, so without its
   own it sat flush against the date chips. Same 12px rhythm as everything else. */
.mgtk-bar { align-items: flex-end; gap: 10px; margin-bottom: 12px; }
.mgt-filters {
    display: grid;
    /* auto-fit, NOT six fixed tracks. Six tracks had a min width of 730px, so
       between the breakpoint and about 830px the grid overflowed its flex item
       and the Export button was painted straight over the last select. Wrapping
       is the fix: the row becomes two rows instead of a collision. */
    grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
    gap: 8px 10px;
    flex: 1 1 auto; min-width: 0;
}
.mgtk-f { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.mgtk-f > span {
    font-size: 10px; font-weight: 700; letter-spacing: .05em;
    text-transform: uppercase; color: var(--text-muted);
}
/*
   `.mg-input` carries `flex: 1 1 220px`, written for the Users toolbar — a ROW
   container, where 220px is a width. `.mgtk-f` is a COLUMN, so the same
   flex-basis becomes a HEIGHT and the search box rendered 220px tall. Reset the
   shorthand rather than fight it; the field wrapper already owns the sizing.
*/
.mgtk-f > .mg-input, .mgtk-f > .mg-select { flex: 0 0 auto; min-width: 0; width: 100%; }
/* The match box earns two tracks; it holds a phrase, not a state. */
.mgtk-f-wide { grid-column: span 2; }

/* The "User" filter (mguserpick.js), on Tickets and Finance: a search box with
   a suggestion list under it, or — once an account is picked — a chip with its
   name, role and a clear button, the same height as the controls beside it. */
.mgup-box { position: relative; }
.mgup-box > .mg-input { width: 100%; box-sizing: border-box; }
.mgup-list {
    position: absolute; z-index: 30; left: 0; right: 0; top: calc(100% + 2px);
    margin: 0; padding: 4px 0; list-style: none; max-height: 300px; overflow-y: auto;
    background: var(--bg-secondary); border: 1px solid var(--border-color);
    box-shadow: 0 10px 24px rgba(0, 0, 0, .45);
}
.mgup-list li {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    padding: 9px 12px; font-size: 13px; color: var(--text-primary); cursor: pointer;
}
.mgup-list li.is-active, .mgup-list li:hover { background: var(--bg-hover); }
.mgup-list li.mgup-none { color: var(--text-muted); font-style: italic; cursor: default; background: none; }
.mgup-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.mgup-role, .mgup-chip-role { flex: none; font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; }
.mgup-chip {
    display: flex; align-items: center; gap: 8px; min-height: 38px; box-sizing: border-box;
    padding: 0 4px 0 12px; background: var(--bg-input);
    border: 1px solid var(--accent-green); color: var(--text-primary); font-size: 13px;
}
.mgup-chip-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 700; }
.mgup-clear {
    flex: none; display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; padding: 0; background: none; border: 0; cursor: pointer;
    color: var(--text-muted);
}
.mgup-clear:hover { color: var(--text-primary); }
.mgup-clear svg { width: 14px; height: 14px; }
.mgf-user { max-width: 360px; margin-bottom: 12px; }

/* 540px is the table's MEASURED minimum (its seven columns' own content), not
   a round guess. It was 720px — 181px more than the table needs — which forced
   a sideways scroll on every viewport between ~560 and 740px even though the
   table fitted comfortably there. */
.mgtk-tbl { min-width: 540px; }
.mgtk-tbl th, .mgtk-tbl td { white-space: nowrap; }
/* The description-column floor again — see 14b. Status is the last column here. */
.mgtk-tbl td:last-child { min-width: 0; white-space: nowrap; }
/* `.mgt-table th { text-align: left }` outweighs a bare `.mgt-c`, so the header
   drifted left of the cells it names. Same trap as `.mgt-r` in 14b. */
.mgtk-tbl th.mgt-c, .mgtk-tbl td.mgt-c { text-align: center; }
.mgtk-tbl .mgt-c { width: 1%; white-space: nowrap; }
.mgtk-sortable { cursor: pointer; user-select: none; }
.mgtk-sortable:hover { color: var(--text-primary); }
.mgtk-sortable.is-sorted { color: var(--accent-green); }

/* Operator over manager, the legacy's two-line cell. */
.mgtk-op { line-height: 1.25; }
.mgtk-opname { display: block; font-weight: 600; color: var(--text-primary); }
.mgtk-opsub { display: block; font-size: 10.5px; color: var(--text-muted); }
.mgtk-no { font-variant-numeric: tabular-nums; color: var(--text-secondary); }
/* Played and Won were styled identically. Won is the figure an operator scans
   for, so it carries the weight; Played is the context for it. */
.mgtk-tbl td:nth-child(5) { font-weight: 700; color: var(--text-primary); }

/* Status is a badge, not a row tint: a full-row colour behind numbers hurts
   readability, and four states over a dark table become mud.

   ONE token per outcome instead of four hardcoded pairs. `#6cb0ff` and the
   three raw rgba() tints were a live breach of the design-token rule
   (--accent-blue-ligth: #64b2fa already existed a hair away). The token is
   read TWICE — by the pill and by the card's left rail — so the state has a
   second, non-textual cue and colour is never load-bearing on its own.
   Contrast re-measured with the tint composited over the card and resolved
   through a canvas (--accent-green is display-p3): won 7.52 · lost 5.11 ·
   open 5.29 · cancelled 5.86. All AA. Mixing into `transparent` measured 4.08
   and FAILED — the mix must land on the opaque --bg-input. */
.mgtk-badge.is-won       { --mgtk-ink: var(--accent-green); }
.mgtk-badge.is-lost      { --mgtk-ink: var(--accent-red-soft); }
.mgtk-badge.is-open      { --mgtk-ink: var(--accent-blue-ligth); }
.mgtk-badge.is-cancelled { --mgtk-ink: var(--text-muted); }
.mgtk-badge {
    display: inline-block; padding: 2px 8px; border-radius: 999px;
    font-size: 10px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
    /* Flat tint first: an engine without color-mix() drops the line below and
       keeps a legible pill instead of a transparent one. */
    background: var(--bg-tertiary);
    background: color-mix(in srgb, var(--mgtk-ink, var(--text-muted)) 18%, var(--bg-input));
    color: var(--mgtk-ink, var(--text-muted));
}
/* The word on desktop, its initial on a card. The word stays in the DOM either
   way — clipped, not removed — so a screen reader still hears "Fituese". */
.mgtk-badge-short { display: none; }
.mgtk-badge-full { display: inline; }
/*
   Was `opacity: .6`, which dropped the row's text to ~3.6:1 — below AA, and it
   made the one state an operator most needs to notice the hardest to read.
   Voided is now said with a strike through the AMOUNTS (the thing that no
   longer counts) and muted-but-legible text, not by fading the row out.
*/
.mgtk-row.is-cancelled td { color: var(--text-muted); }
.mgtk-row.is-cancelled .mgtk-opname { color: var(--text-muted); font-weight: 600; }
.mgtk-row.is-cancelled td.mgt-amt { text-decoration: line-through; text-decoration-thickness: 1px; }

.mgtk-pager {
    display: flex; align-items: center; gap: 4px; flex-wrap: wrap;
    margin-top: 12px;
}
.mgtk-page {
    min-width: 30px; padding: 5px 9px; border-radius: 0; cursor: pointer;
    font: inherit; font-size: 12px; font-weight: 600;
    border: 1px solid var(--border-color); background: var(--bg-secondary); color: var(--text-secondary);
}
.mgtk-page:hover:not(:disabled) { background: var(--bg-hover); color: var(--text-primary); }
.mgtk-page.active {
    background: var(--accent-green); border-color: var(--accent-green); color: var(--bg-primary);
}
.mgtk-page:disabled { opacity: .4; cursor: default; }
.mgtk-gap { color: var(--text-muted); padding: 0 2px; }
.mgtk-count { margin-left: auto; font-size: 11.5px; color: var(--text-muted); }

/* Windows dark mode renders native option lists with the SYSTEM colours unless
   the option itself is painted — white-on-white in a dark theme. */
.mg-select option { background: var(--bg-input); color: var(--text-primary); }

/* Collapsed filters. Desktop never needs the toggle: the row fits. */
.mgtk-filtoggle { display: none; }
.mgtk-filtoggle, .mgtk-dir, .mgtk-page, .mg-export { touch-action: manipulation; }
.mgtk-filtoggle:focus-visible, .mgtk-dir:focus-visible, .mgtk-page:focus-visible {
    outline: 2px solid var(--accent-green); outline-offset: 2px;
}

/* The phone sort control. Redundant on desktop, where the header row is
   clickable, so it only exists below the card breakpoint. */
/* Top margin collapses with .mg-range's 12px bottom margin (block flow), so the
   gap above stays 12. The bottom 12px was simply missing — the Data select sat
   flush against the totals cards. */
.mgtk-sortbar { display: none; align-items: flex-end; gap: 8px; margin: 10px 0 12px; }
.mgtk-sortbar .mgtk-f { flex: 1 1 auto; }
.mgtk-dir {
    flex: 0 0 auto; width: 35px; height: 35px; border-radius: 0; cursor: pointer;
    font: inherit; font-size: 15px; line-height: 1;
    border: 1px solid var(--border-color); background: var(--bg-secondary); color: var(--text-primary);
}
.mgtk-dir:hover { background: var(--bg-hover); border-color: var(--accent-green); }

@media (max-width: 720px) {
    .mgtk-count { margin-left: 0; width: 100%; }
    /* The sortbar lives with the CARD layout (≤600px), not here: it exists
       only because the cards hide the sortable header row. */

    /*
       COLLAPSED BY DEFAULT. Six stacked fields pushed the first ticket a screen
       and a half down — on the page every staff login lands on. The board is
       the content; the filters are a tool you reach for.

       The count badge is what makes collapsing safe: a filter you cannot see is
       otherwise a silent explanation for an empty board.
    */
    .mgtk-bar { flex-wrap: wrap; align-items: center; }
    .mgtk-filtoggle {
        display: inline-flex; align-items: center; gap: 7px; flex: 1 1 auto;
        justify-content: center;
        min-height: 38px; padding: 8px 14px; border-radius: 0; cursor: pointer;
        font: inherit; font-size: 12.5px; font-weight: 600;
        border: 1px solid var(--border-color);
        background: var(--bg-secondary); color: var(--text-secondary);
    }
    .mgtk-filtoggle svg { width: 15px; height: 15px; }
    .mgtk-filtoggle:hover { background: var(--bg-hover); color: var(--text-primary); }
    .mg-panel.mgtk-filters-open .mgtk-filtoggle {
        border-color: var(--accent-green); color: var(--text-primary);
    }
    .mgtk-filcount {
        min-width: 18px; padding: 1px 6px; border-radius: 999px;
        font-size: 10.5px; font-weight: 700;
        background: var(--accent-green); color: var(--bg-primary);
    }
    /* DOM order is toggle → filters → export, so opening the panel pushed
       Export onto a third line of its own. Visual order only; the tab order
       stays as written. */
    /* Equal halves. Filtra stretched to fill the row while Eksporto stayed at
       its content width, which read as a broken layout rather than two peers.
       DOM order is toggle → filters → export, so `order` keeps Export beside
       the toggle when the panel opens; visual only, tab order is unchanged. */
    .mgtk-filtoggle,
    .mgtk-bar .mg-export {
        flex: 1 1 0; min-width: 0; justify-content: center;
        min-height: 38px; padding: 8px 12px;   /* identical box, so they measure equal */
    }
    .mgtk-filtoggle { order: 0; }
    .mgtk-bar .mg-export { order: 1; }
    .mgt-filters { order: 2; }

    .mgt-filters { display: none; }
    .mg-panel.mgtk-filters-open .mgt-filters {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        width: 100%; margin-top: 10px; padding: 12px;
        border: 1px solid var(--border-color); border-radius: 0;
        background: var(--bg-secondary);
    }
    /* The match box is the one field worth a full row. */
    .mg-panel.mgtk-filters-open .mgtk-f-wide { grid-column: 1 / -1; }
    /* 38px minimum so a control is not a coin-toss to hit with a thumb. */
    .mgt-filters .mg-select, .mgt-filters .mg-input { min-height: 38px; }
}

/* --- management: busy state --------------------------------------------- */
/*
   The panel keeps its content and goes inert. These procedures scan the ticket
   archive and can take seconds; replacing the table with a spinner collapses
   the page, loses the reader's position, and makes every refresh read as a
   navigation.
*/
.mg-busy { position: relative; }
.mg-busy > *:not(.mg-skeleton) { opacity: .45; transition: opacity .12s; pointer-events: none; }
.mg-busy::after {
    content: ""; position: absolute; left: 50%; top: 40px; z-index: 3;
    width: 26px; height: 26px; margin-left: -13px;
    border: 2px solid var(--border-color); border-top-color: var(--accent-green);
    border-radius: 50%;
    animation: mg-spin .7s linear infinite;
}
/* Pinned near the top of the panel, not its centre: a long table would put the
   spinner somewhere off-screen. */
@keyframes mg-spin { to { transform: rotate(360deg); } }

/* First load only — there is no previous state worth keeping, so the shape of
   the table arrives before its contents rather than an empty box that jumps. */
.mg-skeleton { display: flex; flex-direction: column; gap: 8px; padding: 8px 0; }
.mg-skeleton-row {
    height: 34px; border-radius: 0;
    background: linear-gradient(90deg, var(--bg-secondary) 25%, var(--bg-hover) 37%, var(--bg-secondary) 63%);
    background-size: 400% 100%;
    animation: mg-shimmer 1.4s ease infinite;
}
@keyframes mg-shimmer { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }
@media (prefers-reduced-motion: reduce) {
    .mg-busy::after, .mg-skeleton-row { animation: none; }
}

/* --- management: ticket detail modal ------------------------------------- */
.mgtk-tbl tbody tr[data-id] { cursor: pointer; }
.mgtk-tbl tbody tr[data-id]:focus-visible { outline: 2px solid var(--accent-green); outline-offset: -2px; }

.mgtd { width: min(820px, 100%); }
.mgtd-meta {
    display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
    gap: 8px; margin-bottom: 12px; padding: 10px 12px;
    border-radius: 0; background: var(--bg-secondary);
}
.mgtd-foot { margin: 12px 0 0; }
.mgtd-item { min-width: 0; }
.mgtd-label {
    display: block; font-size: 9.5px; font-weight: 700; letter-spacing: .05em;
    text-transform: uppercase; color: var(--text-muted); margin-bottom: 2px;
}
.mgtd-value {
    font-size: 12.5px; font-weight: 600; color: var(--text-primary);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block;
    font-variant-numeric: tabular-nums;
}
.mgtd-item.is-poss .mgtd-value { color: var(--accent-green); }

/* Legs. The state lives in a left border + the match name's colour — the row
   stays legible (no opacity games; see 16i) and the strip reads at a glance
   which leg killed the ticket. min-width so a narrow phone gets the sideways
   scroll fallback rather than crushed match names. */
/* 520, not 620: the kick-off sits under the match name, which gives the market (now a
   name, not a code) the column it needs and lets the table fit a phone. */
.mgtd-tbl { min-width: 520px; }
.mgtd-tbl th, .mgtd-tbl td { white-space: nowrap; }
.mgtd-tbl td:last-child { min-width: 0; white-space: nowrap; }  /* 14b again */
.mgtd-leg td:first-child { border-left: 3px solid var(--border-color); }
.mgtd-leg.is-won  td:first-child { border-left-color: var(--accent-green); }
.mgtd-leg.is-lost td:first-child { border-left-color: var(--accent-red); }
.mgtd-leg.is-won  .mgtd-match { color: var(--accent-green); }
.mgtd-leg.is-lost .mgtd-match { color: var(--accent-red-soft); }
.mgtd-match { font-weight: 600; }
/* The market reads as words, with the abbreviation kept under it. Two class names so
   this beats `.mgtd-tbl th, .mgtd-tbl td { white-space: nowrap }` on specificity — a
   market name is prose and may wrap; the box is bounded so the table stays in the modal. */
.mgtd-tbl.mgtd-tbl td.mgtd-mkt {
    white-space: normal; max-width: 190px;
    font-weight: 600; color: var(--text-primary); line-height: 1.2;
}
.mgtd-mkt-code,
.mgtd-sub {
    display: block; margin-top: 1px;
    font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
    color: var(--text-muted);
}
/* The kick-off under the match name: a value, not a label. */
.mgtd-sub { font-size: 11.5px; font-weight: 500; letter-spacing: 0; color: var(--text-secondary); }
/* Opens the match popup (timeline, or stored results) — the same one My Bets uses. */
.mgtd-match-btn {
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    text-decoration: underline;
    text-decoration-color: color-mix(in srgb, currentColor 35%, transparent);
    text-underline-offset: 3px;
}
.mgtd-match-btn:hover { text-decoration-color: currentColor; }
.mgtd-match-btn:focus-visible { outline: 2px solid var(--accent-green); outline-offset: 2px; border-radius: 0; }
.mgtd-pick { font-weight: 700; color: var(--text-primary); }
/* A leg placed in play, under its LIVE tag: the minute and score then, and for football the
   corners and cards (MgTicketDetail._placedHtml). It may wrap (the cell is nowrap). */
.mgtd-placed {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 2px 8px;
    margin-top: 3px;
    white-space: normal;
    font-size: 11px;
    font-weight: 500;
    color: var(--text-secondary);
}
.mgtd-pst {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    font-weight: 700;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}
.mgtd-pst .stat-ico { width: 12px; height: 12px; flex-shrink: 0; }
/* None of that kind yet: lighter weight and a faded icon, the number still readable. */
.mgtd-pst.is-zero { font-weight: 500; color: var(--text-secondary); }
.mgtd-pst.is-zero .stat-ico { opacity: .55; }
/* The operator's re-offer on a line: what it stood at, and what was offered.
   Quiet on purpose — small and non-bold beside the line's own coefficient,
   which stays exactly as it was. It is deliberately NOT compared to that
   coefficient and carries no accepted/refused verdict: on a pending live
   ticket the line's coefficient is the LIVE odd and keeps moving, so any
   comparison would be inventing a story the data does not tell. */
.mgtd-offer {
    margin-left: 6px;
    font-size: 10.5px; font-weight: 400; letter-spacing: 0;
    color: var(--accent-offer);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mgtd-offer-old { opacity: .85; }
.mgtd-offer-arrow { margin: 0 2px; }

/* The ticket on a phone (≤640px, MgTicketDetail._phoneHtml): its facts in three columns, each
   leg two lines - the match and its odds; the pick, the market and the result or kick-off -
   with its state on the left edge, the status beside the title and the money pinned at the
   sheet's foot. The table and its two grids are the wider screens'; this block is theirs. */
.mgtd-m, .mgtd-money, .mgtd-hbadge { display: none; }
.mgtd-who-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
@media (max-width: 640px) {
    .mgtd .mga-body > .mgtd-meta,
    .mgtd .mga-body > .mg-scroll { display: none; }
    .mgtd-m { display: flex; flex-direction: column; gap: 10px; }
    .mgtd-hbadge { display: inline-flex; flex: none; }
    .mgtd-money {
        display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px;
        flex: none;
        padding: 12px 16px calc(14px + env(safe-area-inset-bottom, 0px));
        background: var(--bg-deep);
        border-top: 1px solid var(--border-color);
    }
}
.mgtd-mmeta {
    display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px 12px;
    padding: 12px 14px; background: var(--bg-secondary);
}
.mgtd-mcell { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mgtd-mcell.is-wide { grid-column: span 2; }
.mgtd-mcell .mgtd-label { margin-bottom: 0; }
.mgtd-mval {
    font-size: 13px; font-weight: 600; color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mgtd-msub { font-size: 11px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.mgtd-money .mgtd-mval { font-size: 14px; font-weight: 700; }
.mgtd-money .mgtd-mcell.is-poss { text-align: right; }
.mgtd-money .is-poss .mgtd-mval { color: var(--accent-green); }
.mgtd-mlegs { display: flex; flex-direction: column; background: var(--bg-secondary); }
.mgtd-mhead {
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 10px 14px 8px; border-bottom: 1px solid var(--border-color);
    font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
    color: var(--text-muted);
}
.mgtd-mleg {
    display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 3px 12px;
    padding: 10px 14px 10px 11px;
    border-left: 3px solid var(--border-color);
    border-bottom: 1px solid var(--border-color);
}
.mgtd-mleg:last-child { border-bottom: 0; }
.mgtd-mleg.is-won  { border-left-color: var(--accent-green); }
.mgtd-mleg.is-lost { border-left-color: var(--accent-red); }
.mgtd-mname { min-width: 0; font-size: 13.5px; font-weight: 600; line-height: 18px; color: var(--text-primary); }
.mgtd-mleg.is-won  .mgtd-mname { color: var(--accent-green); }
.mgtd-mleg.is-lost .mgtd-mname { color: var(--accent-red-soft); }
.mgtd-mname .mgtd-match-btn {
    display: block; max-width: 100%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mgtd-modds {
    font-size: 14px; font-weight: 700; line-height: 18px; text-align: right;
    color: var(--text-primary); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mgtd-modds .mgtd-offer { display: block; margin-left: 0; }
.mgtd-mpick { min-width: 0; font-size: 12px; line-height: 16px; color: var(--text-secondary); }
.mgtd-mpick b { color: var(--text-primary); }
.mgtd-mcode { font-weight: 700; letter-spacing: .04em; color: var(--text-muted); }
.mgtd-mright {
    display: inline-flex; align-items: center; justify-content: flex-end; gap: 4px;
    font-size: 12px; font-weight: 700; color: var(--text-muted);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mgtd-mright svg { width: 12px; height: 12px; flex: none; }
.mgtd-mleg.is-won  .mgtd-mright { color: var(--accent-green); }
.mgtd-mleg.is-lost .mgtd-mright { color: var(--accent-red-soft); }
.mgtd-mht { font-weight: 500; color: var(--text-muted); }
.mgtd-mlive { grid-column: 1 / -1; display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; }
.mgtd-mlive .mgtd-placed { margin-top: 0; }
.mgtd-livechip {
    padding: 0 5px;
    background: var(--bg-tertiary);
    background: color-mix(in srgb, var(--accent-red) 22%, var(--bg-input));
    color: var(--accent-red-soft);
    font-size: 9.5px; font-weight: 700; letter-spacing: .05em; line-height: 15px;
}

/* --- management: grouped tickets tree ------------------------------------ */
/* Legacy's expandable boxes, in the app's own tokens.

   Indent comes from the NESTING (each .mgtg-kids adds one step), not from a
   per-node depth multiplier. The nodes already sit inside their parent's kids
   container, so a depth-scaled margin COMPOUNDED — step x d(d+1)/2 — and a
   third level drifted 48px right instead of 32. The `--mgtg-depth` custom
   property the JS still emits is now inert. */
.mgtg { display: flex; flex-direction: column; gap: 8px; }
.mgtg-node { min-width: 0; }
.mgtg-head {
    display: flex; align-items: center; gap: 8px; width: 100%;
    padding: 9px 12px; border-radius: 0; cursor: pointer;
    font: inherit; text-align: left;
    border: 1px solid var(--border-color); border-bottom: 0;
    background: var(--bg-secondary); color: var(--text-primary);
}
.mgtg-head:hover { background: var(--bg-hover); }
.mgtg-head:focus-visible { outline: 2px solid var(--accent-green); outline-offset: -2px; }
.mgtg-head.is-leaf .mgtg-chev { visibility: hidden; }
.mgtg-head.is-leaf:hover .mgtg-name { color: var(--accent-green); text-decoration: underline; }
.mgtg-chev {
    flex: 0 0 auto; width: 18px; height: 18px; border-radius: 0;
    display: grid; place-items: center;
    font-size: 13px; font-weight: 700; line-height: 1;
    background: var(--bg-tertiary); color: var(--accent-green);
}
.mgtg-dot { flex: 0 0 auto; width: 10px; height: 10px; border-radius: 50%; padding: 0; }
.mgtg-name {
    font-weight: 700; font-size: 12.5px; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mgtg-badges { margin-left: auto; display: flex; gap: 6px; flex: 0 0 auto; }
.mgtg-b {
    font-size: 9.5px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
    padding: 2px 7px; border-radius: 999px;
    background: var(--bg-tertiary); color: var(--text-muted); white-space: nowrap;
}
.mgtg-b b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.mgtg-lines {
    padding: 6px 12px 8px; border: 1px solid var(--border-color); border-top: 0;
    border-radius: 0; background: var(--bg-primary);
    display: flex; flex-direction: column; gap: 3px;
}
.mgtg-line {
    display: flex; align-items: baseline; gap: 6px;
    font-size: 11.5px; color: var(--text-secondary);
    font-variant-numeric: tabular-nums; white-space: nowrap;
}
.mgtg-cur { font-weight: 700; color: var(--text-muted); min-width: 30px; }
.mgtg-amt { font-weight: 700; color: var(--text-primary); }
.mgtg-sep { color: var(--text-muted); }
/*
   AN EXPANDED BRANCH READS AS ONE GROUP.

   Children used to differ from top-level accounts by 16px of indent alone, so
   opening a node just produced more rows that looked like roots. Two cues now
   carry the nesting, because either one alone can be missed: a SPINE the
   children hang off (visible even when the parent has scrolled away), and a
   RECESSED SURFACE — nested cards are mixed toward --bg-input, one step per
   level, so depth reads as "further in" without inventing new colours.
*/
.mgtg-kids {
    margin-top: 8px; display: flex; flex-direction: column; gap: 8px;
    padding-left: 10px;
    border-left: 2px solid var(--border-color);
}
/* Level 1. Flat token first: an engine without color-mix() keeps a legible
   card rather than a transparent one, and still gets the spine. */
.mgtg-kids > .mgtg-node > .mgtg-head {
    background: var(--bg-primary);
    background: color-mix(in srgb, var(--bg-secondary) 68%, var(--bg-input));
}
.mgtg-kids > .mgtg-node > .mgtg-lines {
    background: var(--bg-input);
    background: color-mix(in srgb, var(--bg-primary) 68%, var(--bg-input));
}
/* Level 2 — a player under an agent under a manager. */
.mgtg-kids .mgtg-kids > .mgtg-node > .mgtg-head {
    background: color-mix(in srgb, var(--bg-secondary) 40%, var(--bg-input));
}
.mgtg-kids .mgtg-kids > .mgtg-node > .mgtg-lines {
    background: color-mix(in srgb, var(--bg-primary) 40%, var(--bg-input));
}
/* Hover has to stay louder than the recess, or a nested row stops answering
   the pointer. */
.mgtg-kids > .mgtg-node > .mgtg-head:hover,
.mgtg-kids .mgtg-kids > .mgtg-node > .mgtg-head:hover { background: var(--bg-hover); }
/* The branch's colour (--mg-br, mgtickets.js _treeNodeHtml) on its spine and over its
   accounts' cards, the head that opened it marked in the same colour (--mg-op). Over the
   recessed surfaces above: a tint layered on them, not a new background. */
.mgtg-kids.mg-br { border-left-color: rgba(var(--mg-br), .85); }
.mgtg-kids.mg-br > .mgtg-node > .mgtg-head,
.mgtg-kids.mg-br > .mgtg-node > .mgtg-lines {
    background-image: linear-gradient(rgba(var(--mg-br), .10), rgba(var(--mg-br), .10));
}
.mgtg-head.mg-op { box-shadow: inset 3px 0 0 rgba(var(--mg-op), .95); }
.mgtg-note { padding: 6px 12px; font-size: 11.5px; }

/* STATISTIKAT counts row inside a totals card. Colour matches the status
   badges, but the LABEL is the cue — the counts read without the colour. */
/* STATISTIKAT counts as label/value rows — the same axis as the money lines,
   so nothing wraps differently from card to card. The dashed rule below the
   counts marks where pieces (tickets) end and money begins. */
.mgtg-cline.is-won b       { color: var(--accent-green); }
.mgtg-cline.is-lost b      { color: var(--accent-red-soft); }
.mgtg-cline.is-open b      { color: var(--accent-blue-ligth); }
.mgtg-cline.is-cancelled b { color: var(--text-muted); }
/* After the colour rules on purpose: a zero is quiet whatever its state. */
.mgtg-cline b.is-zero      { color: var(--text-muted); font-weight: 400; }
.mgtg-mstart {
    margin-top: 6px; padding-top: 7px;
    border-top: 1px dashed var(--border-color);
}

/* One player's tickets in a modal (opened from a tree leaf, §16n). Wider than
   the detail modal: it holds the board's own seven-column table. */
.mgtku { width: min(980px, 100%); }

/* The ticket modals scroll their BODY as one block. The flex-column +
   overflow:hidden treatment on .mga-body belongs to the Activity modal's
   bounded inner table; here it let the totals strip be flex-crushed (the card
   clipped mid-row on a phone) and turned the table wrapper into a second
   scroller inside the dialog. */
.mgtd .mga-body, .mgtku .mga-body { display: block; overflow: hidden auto; }

/* Every row's operator IS the player named in the modal title — the column is
   dropped rather than repeated a hundred times, and the freed width is what
   lets the phone cards fit without the sideways scroll. display:none keeps the
   nth-child numbering intact, so the card layout's area mapping still holds. */
.mgtku-tbl th:nth-child(2), .mgtku-tbl td:nth-child(2) { display: none; }
/* With that column gone the modal's table needs ~450px, not the board's 540px
   floor — and the dialog is narrower than the viewport, so inheriting that
   floor made the table scroll sideways inside its own modal. */
.mgtku-tbl { min-width: 0; }

/*
   16o — THE TICKET ROW ANSWERS TO ITS CONTAINER, AND ITS TRACKS FILL IT.

   TWO faults, one edit.

   FAULT 1 — the breakpoint read the VIEWPORT while one of the two hosts is a
   dialog. MEASURED: at a 1280px viewport the board's table box is 1250px and
   the MgUserTickets dialog's is 936px. 314px apart, one number, describing
   neither. `.mg-scroll` is the table's immediate wrapper in BOTH renderers,
   so one declaration reaches both and the question is asked of the exact box
   the row occupies. `:has(> .mgtk-tbl)` keeps transactions / activity /
   finance out, and excludes the ticket DETAIL modal by name — its table is
   `.mgtd-tbl`.

   FAULT 2 — `auto auto auto auto` + `justify-content: start` is content-sized
   and packs left, so the row's INK was a constant 213px (board) / 185px
   (modal) however wide the box got, and every spare pixel pooled at the right
   edge. MEASURED on the previous CSS, worst of eight rows: 125.7px dead at a
   339px board container, 148.3px at a 333px modal container (33–67% of the
   row unused), and EIGHT different column layouts across eight rows — the
   zig-zag §16j had fixed, reintroduced by the all-`auto` revert. Now every
   track is minmax(<measured px>, <n>fr): an fr track cannot leave slack, and
   neither term reads content, so track resolution is a pure function of
   container width and every row resolves to IDENTICAL pixels. MEASURED after:
   1 column layout at every width, both variants, all six languages, and the
   only "dead space" left is the card's own padding-right.

   The floors are real (never minmax(0,…), never a bare 1fr), so the fit-based
   sideways fallback still fires below 278px.

   MEASURED FLOORS (Oxanium, this stylesheet): AM/PM date 82.57 → 84 ·
   "GEWONNEN 1,326,431.91" 148.7 / "FITUAR 1,326,431.91" 126.5 → 124 with the
   label allowed to give way · widest status pill ΚΕΡΔΙΣΜΈΝΟ 89.3 → 92 · short
   pill 27.0 → 30. Board table min-content with typical production data:
   sq 558 · en 561 · de 565 · it 561 · es 555 · el 600, and 596 with a
   16-char operator + a 9-figure amount + a 3-letter code. The card therefore
   hands over at 605cqi, not 575: measured at 579 the table panned 17px, which
   is the sideways scroll this whole exercise exists to remove.
*/
.mgtk-tbl tbody tr.is-won       { --mgtk-ink: var(--accent-green); }
.mgtk-tbl tbody tr.is-lost      { --mgtk-ink: var(--accent-red-soft); }
.mgtk-tbl tbody tr.is-open      { --mgtk-ink: var(--accent-blue-ligth); }
.mgtk-tbl tbody tr.is-cancelled { --mgtk-ink: var(--text-muted); }

.mg-scroll:has(> .mgtk-tbl) { container: mgtk / inline-size; }
/* The sort bar stands in for the sortable <thead> once the header is hidden,
   so it MUST switch on the same signal — but it is a SIBLING of #mgtk-out,
   not a descendant of .mg-scroll. Its own box is the panel. Panel, #mgtk-out
   and .mg-scroll are plain block divs with nothing between them: MEASURED,
   both containers report the same width to the pixel and both thresholds flip
   together at 574/575. A viewport media query here drifts by whatever the page
   padding is, leaving a band with no header AND no sort bar. */
.mg-panel:has(> #mgtk-out)  { container: mgtkpanel / inline-size; }
@container mgtkpanel (max-width: 604px) { .mgtk-sortbar { display: flex; } }

@container mgtk (max-width: 604px) {
    /* 278px is this grid's own arithmetic minimum, not a round number, and it
       is the first width at which no track freezes: below it the fr algorithm
       leaves 3–7px unallocated, so the floor is set where that window ends.
       Below 278 the list pans sideways — the last-resort fallback. The
       previous floor was 320 and it panned 36px on a 320px phone; this pans 0. */
    .mgtk-tbl { display: block; width: 100%; min-width: 278px; }
    .mgtk-tbl thead { display: none; }
    .mgtk-tbl tbody { display: flex; flex-direction: column; gap: 6px; }

    .mgtk-tbl tbody tr {
        /* Floors and weights are named so the two variant templates and the
           status-word override cannot drift out of step with each other. */
        --f-ident:  84px; --w-ident: 1.05fr;
        --f-op:     34px; --w-op:    1.1fr;
        --f-money: 124px; --w-money: 1.65fr;
        --f-cs:     30px; --w-cs:     .5fr;
        display: grid;
        grid-template-columns:
            minmax(var(--f-ident), var(--w-ident))
            minmax(var(--f-op),    var(--w-op))
            minmax(var(--f-money), var(--w-money))
            minmax(var(--f-cs),    var(--w-cs));
        grid-template-rows: auto auto;
        /* cqi, not vw: the gutters answer to the row's own box, so the modal
           does not inherit gutters sized for the page. */
        column-gap: clamp(6px, 2cqi, 16px);
        row-gap: 2px;
        align-items: center;
        line-height: 1.25;
        padding-block: 7px;
        padding-inline: clamp(8px, 2.4cqi, 12px);
        /* .mg-row's chrome, not a flat divider list: this is a management
           board and the Users tree next door is the row staff already know.
           The rail says the outcome without a word, so it survives an
           ellipsis, a one-letter badge and colour-blindness. */
        border: 0;
        border-left: 3px solid var(--mgtk-ink, var(--border-color));
        border-radius: var(--radius-md);
        background: var(--bg-secondary);
    }
    /* `.mgt-table td` is (0,1,1) and `.mgtk-tbl .mgt-c { width: 1% }` is
       (0,2,0) — the fourth outing of that specificity trap. Every cell rule
       below names `.mgtk-tbl tbody` so it outranks both; `width: auto` is
       load-bearing or the currency and status cells collapse. */
    .mgtk-tbl tbody td {
        display: block; padding: 0; border: 0; width: auto;
        min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .mgtk-tbl tbody td.mgt-r, .mgtk-tbl tbody td.mgt-c { width: auto; text-align: left; }
    .mgtk-tbl tbody .mgtk-v { display: block; overflow: hidden; text-overflow: ellipsis; }

    /* dt op pl cur / nr op wn st — the area map already approved, now on
       flexible floored tracks. Explicit grid-column/grid-row, never
       grid-template-areas: the modal drops cell 2 with display:none and a
       named area with no occupant leaves a hole in the middle of line 1 — a
       pooled void, the exact failure being fixed. */
    .mgtk-tbl tbody td:nth-child(3) { grid-column: 1; grid-row: 1; font-size: 11px; }
    .mgtk-tbl tbody td:nth-child(1) {
        grid-column: 1; grid-row: 2;
        font-size: 11px; font-weight: 600; color: var(--text-secondary);
    }
    .mgtk-tbl tbody td:nth-child(1)::before { content: "#"; color: var(--text-muted); }
    .mgtk-tbl tbody td:nth-child(1) .mgtk-v { display: inline; }
    .mgtk-tbl tbody td:nth-child(2) { grid-column: 2; grid-row: 1 / span 2; line-height: 1.3; }
    .mgtk-tbl tbody td:nth-child(4) { grid-column: 3; grid-row: 1; font-size: 12px; font-weight: 600; color: var(--text-secondary); }
    /* Won is the figure an operator scans for; Played is the context for it. */
    .mgtk-tbl tbody td:nth-child(5) { grid-column: 3; grid-row: 2; font-size: 14px; font-weight: 800; color: var(--text-primary); }
    .mgtk-tbl tbody td:nth-child(6) {
        grid-column: 4; grid-row: 1;
        font-size: 10.5px; font-weight: 700; color: var(--text-muted); text-align: center;
    }
    .mgtk-tbl tbody td:nth-child(7) { grid-column: 4; grid-row: 2; line-height: 1; }

    /* The modal is the same row minus the operator track. */
    .mgtku-tbl tbody tr {
        grid-template-columns:
            minmax(var(--f-ident), var(--w-ident))
            minmax(var(--f-money), var(--w-money))
            minmax(var(--f-cs),    var(--w-cs));
    }
    .mgtku-tbl tbody td:nth-child(4), .mgtku-tbl tbody td:nth-child(5) { grid-column: 2; }
    .mgtku-tbl tbody td:nth-child(6), .mgtku-tbl tbody td:nth-child(7) { grid-column: 3; }

    .mgtk-tbl tbody .mgtk-opname {
        display: block; font-size: 12px; font-weight: 600; color: var(--text-secondary);
        overflow: hidden; text-overflow: ellipsis;
    }
    .mgtk-tbl tbody .mgtk-opsub {
        display: block; font-size: 10px; color: var(--text-muted);
        overflow: hidden; text-overflow: ellipsis;
    }

    /* Label PACKED with its amount, never space-between — the owner A/B'd both
       in DevTools and rejected the spread twice. The labels share one edge in
       every row because the track is container-derived. */
    .mgtk-tbl tbody td[data-label] {
        display: flex; align-items: baseline; gap: 6px;
        font-variant-numeric: tabular-nums;
    }
    /* The label gives way, the NUMBER never does. German "GEWONNEN
       1,326,431.91" needs 148.7px against a 124px floor; `flex: 0 3 auto` on
       the caption and `flex: 0 0 auto` on the value means the label
       ellipsises ("GEWON…") and the amount stays whole. */
    .mgtk-tbl tbody td[data-label]::before {
        content: attr(data-label); flex: 0 3 auto;
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
        font-size: 9.5px; font-weight: 700; letter-spacing: .04em;
        text-transform: uppercase; color: var(--text-muted);
    }
    .mgtk-tbl tbody td[data-label] .mgtk-v { flex: 0 0 auto; }

    /* The pill fills its track, so line 2's ink terminates on the row's own
       padding edge at every width — that is what makes "the row uses its
       width" true unconditionally rather than true-at-375-only. */
    .mgtk-tbl tbody .mgtk-badge {
        display: block; text-align: center; line-height: 1.35;
        padding: 2px 7px; font-size: 11px; letter-spacing: 0;
        overflow: hidden; text-overflow: ellipsis;
    }
    /* Scoped to the LIST: the detail modal reuses .mgtk-badge and carries only
       the full word — unscoped, this clipped it into an empty pill. */
    .mgtk-tbl .mgtk-badge-full {
        position: absolute; width: 1px; height: 1px; overflow: hidden;
        clip-path: inset(50%); white-space: nowrap;
    }
    .mgtk-tbl .mgtk-badge-short { display: inline; }

    /* Voided: muted but legible (6.38:1, AA — never opacity), and the strike
       lands on the NUMBER only. With the label a real ::before flex item,
       `text-decoration` on the <td> propagates into it and struck "LUAJTUR"
       too — a descendant cannot cancel a propagated decoration, which is why
       the .mgtk-v value span exists. */
    .mgtk-tbl tbody tr.is-cancelled td { color: var(--text-muted); }
    .mgtk-tbl tbody tr.is-cancelled td.mgt-amt { text-decoration: none; }
    .mgtk-tbl tbody tr.is-cancelled td.mgt-amt .mgtk-v {
        text-decoration: line-through; text-decoration-thickness: 1px;
    }
}

/* The tightest boxes (a 320px phone). Four columns plus their gaps need 310px;
   below that the OPERATOR — the lowest-ranked field — takes a line of its own
   at full width, name and agent inline, and the other three columns get their
   full width back: money resolves to 133px here instead of being crushed.
   Costs one text line (73.4px pitch vs 55.8) on 320px hardware only. The modal
   has no operator cell at all, so it simply stays two lines. */
@container mgtk (max-width: 314.98px) {
    .mgtk-tbl tbody tr {
        grid-template-columns:
            minmax(var(--f-ident), var(--w-ident))
            minmax(var(--f-money), var(--w-money))
            minmax(var(--f-cs),    var(--w-cs));
    }
    .mgtk-tbl tbody td:nth-child(4), .mgtk-tbl tbody td:nth-child(5) { grid-column: 2; }
    .mgtk-tbl tbody td:nth-child(6), .mgtk-tbl tbody td:nth-child(7) { grid-column: 3; }
    .mgtk-tbl tbody td:nth-child(2) {
        grid-column: 1 / -1; grid-row: 3;
        display: flex; align-items: baseline; gap: 6px;
    }
    .mgtk-tbl tbody td:nth-child(2) .mgtk-opname { flex: 0 1 auto; }
    .mgtk-tbl tbody td:nth-child(2) .mgtk-opsub  { flex: 0 2 auto; }
}

/* THE FULL STATUS WORD THE MOMENT THE BOX AFFORDS IT — and the answer differs
   per variant because the board carries one column more. That is the concrete
   payoff of asking the container: at a 375px viewport the modal shows the full
   word and the board shows the letter, and both are right for their own box.
   Below these widths the short form runs, which is safe only because of the
   el/it two-letter i18n fix shipping with this change — Α meant BOTH Ανοιχτό
   and Ακυρώθηκε, and the rail is the second cue. */
@container mgtk (min-width: 336px) and (max-width: 604px) {
    .mgtku-tbl tbody tr { --f-cs: 92px; --w-cs: .95fr; }
    .mgtku-tbl .mgtk-badge-full  { position: static; width: auto; height: auto; clip-path: none; }
    .mgtku-tbl .mgtk-badge-short { display: none; }
    .mgtku-tbl tbody .mgtk-badge { padding: 2px 8px; font-size: 10px; letter-spacing: .03em; }
}
@container mgtk (min-width: 420px) and (max-width: 604px) {
    .mgtk-tbl:not(.mgtku-tbl) tbody tr { --f-cs: 92px; --w-cs: .95fr; }
    .mgtk-tbl:not(.mgtku-tbl) .mgtk-badge-full  { position: static; width: auto; height: auto; clip-path: none; }
    .mgtk-tbl:not(.mgtku-tbl) .mgtk-badge-short { display: none; }
    .mgtk-tbl:not(.mgtku-tbl) tbody .mgtk-badge { padding: 2px 8px; font-size: 10px; letter-spacing: .03em; }
}

/* iOS 15 and older, Firefox <121: the @container blocks are dropped whole, so
   the row stays the desktop TABLE and .mg-scroll pans — the finance-table
   fallback, stated in code rather than inherited by accident. Floors are each
   variant's measured max-content with typical data. */
@supports not (container-type: inline-size) {
    .mgtk-tbl  { min-width: 575px; }
    .mgtku-tbl { min-width: 490px; }
    @media (max-width: 604px) { .mgtk-sortbar { display: flex; } }
}

/* Tree mode has no column sort and no pager. */
.mgtk-mode-tree .mgtk-sortbar { display: none !important; }
/* The grouped router is a shared procedure with no @hasOffer, so the offer
   toggle would be a control that changes nothing there. Hidden in tree mode —
   and cleared, so it can never be an invisible active filter. */
.mgtk-mode-tree .mgtk-f-switch { display: none; }
/* The switch sits in the same filter grid as the selects, label above control
   like its neighbours. */
.mgtk-f-switch { justify-content: flex-start; }
.mgtk-f-switch .mgp-switch { align-self: flex-start; margin-top: 2px; }

@media (max-width: 720px) {
    /* .mgtg-badges { display: none; }     */
          /* counts live in the lines below */
    /* A tighter step per level on a phone; the spine still marks the branch. */
    .mgtg-kids { padding-left: 7px; }
}

/* ===== Bet Builder test bench (#BB, admin-0) — betbuilder-admin.js =====
   Every rule is scoped to #page-betbuilder: the bench shares the bb- prefix with
   the Bet Boost cards, and unscoped its .bb-market / .bb-odd restyled every Bet
   Boost card on the home page (grey box round the market, a 76x46 price). */
#page-betbuilder .bb-bar { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 14px; }
#page-betbuilder .bb-bar input, #page-betbuilder .bb-bar select { background: var(--bg-input); color: var(--text-primary); border: 1px solid var(--border-color); border-radius: var(--radius-md); padding: 8px 10px; font-size: 13px; font-family: inherit; }
#page-betbuilder .bb-bar input { width: 130px; }
#page-betbuilder .bb-bar select { max-width: 420px; }
#page-betbuilder .bb-note { font-size: 13px; color: var(--text-muted); padding: 8px 0; }
#page-betbuilder .bb-layout { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 14px; align-items: start; }
@media (max-width: 1000px) { #page-betbuilder .bb-layout { grid-template-columns: 1fr; } }
#page-betbuilder .bb-card { background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: var(--radius-lg); padding: 14px 16px; margin-bottom: 12px; }
#page-betbuilder .bb-card h3 { margin: 0 0 10px; font-size: 14px; font-weight: 700; color: var(--text-primary); }
#page-betbuilder .bb-match { font-size: 16px; font-weight: 800; color: var(--text-primary); }
#page-betbuilder .bb-sub { font-size: 12px; color: var(--text-muted); margin-top: 2px; }
#page-betbuilder .bb-kv { display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; font-size: 13px; }
#page-betbuilder .bb-kv .k { color: var(--text-muted); }
#page-betbuilder .bb-kv .v { color: var(--text-primary); font-weight: 600; font-variant-numeric: tabular-nums; }
#page-betbuilder .bb-table { width: 100%; border-collapse: collapse; font-size: 12px; font-variant-numeric: tabular-nums; }
#page-betbuilder .bb-table th, #page-betbuilder .bb-table td { padding: 5px 8px; border-bottom: 1px solid var(--border-color); text-align: right; white-space: nowrap; }
#page-betbuilder .bb-table th:first-child, #page-betbuilder .bb-table td:first-child { text-align: left; }
#page-betbuilder .bb-table th { color: var(--text-muted); font-weight: 600; }
#page-betbuilder .bb-grid { border-collapse: collapse; font-size: 12px; font-variant-numeric: tabular-nums; }
#page-betbuilder .bb-grid th, #page-betbuilder .bb-grid td { padding: 4px 8px; text-align: center; border: 1px solid var(--border-color); min-width: 52px; }
#page-betbuilder .bb-grid th { color: var(--text-muted); background: var(--bg-input); font-weight: 600; }
#page-betbuilder .bb-grid td { color: var(--text-primary); }
#page-betbuilder .bb-grid td.hot { background: rgba(0,231,1,0.12); }
#page-betbuilder .bb-grid td.warm { background: rgba(0,231,1,0.05); }
#page-betbuilder .bb-grid td.hit { outline: 2px solid var(--accent-odds); outline-offset: -2px; }
#page-betbuilder .bb-grid td.dim { color: var(--text-muted); }
#page-betbuilder .bb-markets { display: grid; gap: 10px; }
#page-betbuilder .bb-market { background: var(--bg-tertiary); border: 1px solid var(--border-color); border-radius: var(--radius-md); padding: 8px 10px; }
#page-betbuilder .bb-market-h { display: flex; justify-content: space-between; gap: 8px; font-size: 12px; font-weight: 700; color: var(--text-secondary); margin-bottom: 6px; }
#page-betbuilder .bb-market-h .grp { color: var(--text-muted); font-weight: 500; }
#page-betbuilder .bb-odds { display: flex; flex-wrap: wrap; gap: 6px; }
#page-betbuilder .bb-odd { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; min-width: 76px; height: 46px; padding: 0 8px; background: var(--bg-odds); border: 1px solid transparent; border-radius: var(--radius-sm); cursor: pointer; font-family: inherit; }
#page-betbuilder .bb-odd:hover { background: var(--bg-hover); border-color: var(--accent-green); }
#page-betbuilder .bb-odd.selected { background: var(--odd-selected-bg); }
#page-betbuilder .bb-odd .l { font-size: 10px; color: var(--text-muted); font-weight: 500; max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#page-betbuilder .bb-odd .v { font-size: 13px; color: var(--accent-odds); font-weight: 700; }
#page-betbuilder .bb-odd.selected .l { color: rgba(255,255,255,0.8); }
#page-betbuilder .bb-odd.selected .v { color: #fff; }
#page-betbuilder .bb-odd:disabled { opacity: 0.45; cursor: not-allowed; }
#page-betbuilder .bb-result { position: sticky; top: calc(var(--header-height) + 10px); }
#page-betbuilder .bb-legs { display: grid; gap: 6px; margin-bottom: 10px; }
#page-betbuilder .bb-leg { display: flex; justify-content: space-between; align-items: center; gap: 8px; font-size: 12px; background: var(--bg-tertiary); border-radius: var(--radius-sm); padding: 6px 8px; }
#page-betbuilder .bb-leg .n { color: var(--text-primary); font-weight: 600; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#page-betbuilder .bb-leg .m { color: var(--text-muted); font-size: 11px; }
#page-betbuilder .bb-leg .o { color: var(--accent-odds); font-weight: 700; flex: none; }
#page-betbuilder .bb-leg .x { background: none; border: 0; color: var(--text-muted); cursor: pointer; font-size: 14px; padding: 0 2px; flex: none; }
#page-betbuilder .bb-leg .x:hover { color: var(--accent-red); }
#page-betbuilder .bb-leg.err { border: 1px solid var(--accent-red); }
#page-betbuilder .bb-leg .e { color: var(--accent-red); font-size: 11px; }
#page-betbuilder .bb-big { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin: 8px 0 4px; }
#page-betbuilder .bb-big .lbl { font-size: 12px; color: var(--text-muted); }
#page-betbuilder .bb-big .val { font-size: 28px; font-weight: 800; color: var(--accent-green); font-variant-numeric: tabular-nums; }
#page-betbuilder .bb-reject { border: 1px solid var(--accent-red); background: rgba(237,65,99,0.08); border-radius: var(--radius-md); padding: 10px 12px; font-size: 13px; color: var(--text-primary); margin: 8px 0; }
#page-betbuilder .bb-reject b { color: var(--accent-red); }
#page-betbuilder .bb-cmp { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 6px; margin-top: 8px; }
#page-betbuilder .bb-cmp > div { background: var(--bg-tertiary); border-radius: var(--radius-sm); padding: 8px; text-align: center; }
#page-betbuilder .bb-cmp .n { font-size: 16px; font-weight: 700; color: var(--text-primary); font-variant-numeric: tabular-nums; }
#page-betbuilder .bb-cmp .t { font-size: 10px; color: var(--text-muted); margin-top: 2px; }
#page-betbuilder .bb-corr-pos { color: var(--accent-orange); }
#page-betbuilder .bb-corr-neg { color: var(--accent-odds); }
#page-betbuilder .bb-hint { font-size: 12px; color: var(--text-muted); line-height: 1.5; margin-top: 8px; }

/* ==========================================
   MARKET SWITCHES — Market:SlotsEnabled / Market:LiveCasinoEnabled
   The server stamps html.no-slots / .no-live-casino / .no-casino onto every page it
   serves (Services/MarketFeatures.cs), so anything tagged data-casino is gone before
   first paint — no flash of a casino menu in a market without one.
   Uses data-casino, NOT data-market: that attribute already drives the odds-market
   selector (1x2 / ou / cou).
   !important because some of these get an inline display from JS when they render
   (e.g. #home-slots-promo). js/market.js guards the routes and loads markup can't.
   ========================================== */
html.no-slots [data-casino="slots"],
html.no-live-casino [data-casino="live-casino"],
html.no-live-casino [data-casino="arcade"],
html.no-casino [data-casino="any"],
/* ...and THIS ACCOUNT's (index.html's inline script, from kaSlote / ka_evolution / ka_arcade):
   a signed-in player without a product does not see it either. */
html.user-no-slots [data-casino="slots"],
html.user-no-live-casino [data-casino="live-casino"],
html.user-no-arcade [data-casino="arcade"],
html.user-no-casino [data-casino="any"] {
    display: none !important;
}

/* No casino at all: the product toggle keeps two positions, Sports | Live, rather
   than losing its Casino half and leaving the logo alone in the header pill. The
   Casino half is data-casino="any" (hidden above); the Live half exists only here.
   The LIVE badge is a wide, short glyph, so it gets a bigger box than the 21px
   ball to carry the same weight beside it. */
#product-toggle-live { display: none; }
html.no-casino #product-toggle-live,
html.user-no-casino #product-toggle-live { display: flex; }
#product-toggle-live .product-toggle-icon { width: 26px; height: 26px; }

/* =====================================================================
   RESTYLE SHELL (2026-10-07, branch `sherbimi`) — bet365-style frame
   Teal top bar (A-Z · Live · Kazino | centred logo | My Bets · search ·
   account), single full-width column, A-Z drawer instead of a permanent
   rail, bottom-sheet betslip on every width. Colours come from :root
   tokens only (--header-bg / --header-ink / --header-active / --scrim).
   ===================================================================== */

/* --- Top bar --------------------------------------------------------- */
.top-header {
    background: var(--header-bg);
    gap: 8px;
    padding: env(safe-area-inset-top, 0px) 8px 0 4px;
}

.top-header .header-left {
    background: none;
    border-radius: 0;
    padding: 0;
    margin-top: 0;
    gap: 0;
    height: 100%;
    align-self: stretch;
}

/* Retired from the bar: Live / Kazino tabs carry the "where am I" state now.
   Kept in the DOM so App.updateProductToggle keeps working unchanged. */
.top-header .product-toggle { display: none !important; }

.hdr-az,
.hdr-tab,
.hdr-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 100%;
    padding: 0 12px;
    background: none;
    border: 0;
    color: var(--header-ink);
    font: 500 14px var(--font-body);
    white-space: nowrap;
    cursor: pointer;
    position: relative;
    -webkit-tap-highlight-color: transparent;
}

.hdr-az { font-weight: 600; font-size: 13px; }
.hdr-tabs { display: flex; height: 100%; }

.hdr-tab.active::after,
.hdr-link.active::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 3px;
    background: var(--header-active);
}

@media (hover: hover) {
    .hdr-az:hover,
    .hdr-tab:hover,
    .hdr-link:hover,
    .hdr-icon-btn:hover { background: rgba(var(--bg-deep-rgb), 0.12); }
}

.hdr-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    background: none;
    border: 0;
    color: var(--header-ink);
    cursor: pointer;
    flex-shrink: 0;
}

/* Centred group: Live · Kazino | logo | My Bets. Absolutely centred so the
   left and right groups can be any width without pushing it off-centre; the
   1fr / auto / 1fr grid sizes both side columns to the wider side, which keeps
   the logo itself on the bar's exact centre line. */
.hdr-center {
    position: absolute;
    left: 50%;
    top: env(safe-area-inset-top, 0px);
    height: var(--header-bar);
    transform: translateX(-50%);
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: stretch;
}
/* Explicit columns: with the tabs hidden (≤900px) the logo must not slide
   into the first track. */
.hdr-center .hdr-tabs { grid-column: 1; justify-self: end; }
.hdr-center-end { grid-column: 3; justify-self: start; display: flex; height: 100%; }
.header-logo {
    grid-column: 2;
    display: flex;
    align-items: center;
    padding: 0 18px;
}
.header-logo .logo-img { height: 30px; width: auto; padding-left: 0; }

/* Account: user icon with the balance underneath. */
.hdr-account {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    padding: 0 6px;
}
.hdr-account .user-avatar {
    width: 30px;
    height: 24px;
    color: var(--header-ink);
}
.hdr-account .user-avatar:hover { color: var(--header-ink); opacity: 0.8; }
.hdr-account .wallet-display {
    height: auto;
    padding: 0;
    gap: 3px;
    background: none;
    border: 0;
    color: var(--header-ink);
    font-size: 11px;
    font-weight: 600;
    line-height: 1.2;
    white-space: nowrap;
}
.hdr-account .wallet-display svg { display: none; }
.hdr-account .currency-badge {
    display: inline;
    padding: 0;
    background: none;
    border: 0;
    color: inherit;
    font-size: 10px;
}
/* The menu drops from the bar's bottom edge, not from the icon (the balance
   sits under the icon now). */
.top-header .user-dropdown {
    position: fixed;
    top: var(--header-height);
    right: 8px;
    left: auto;
}

.top-header .header-right {
    min-width: 0;
    gap: 4px;
    height: 100%;
}

/* The desktop betslip toggle is redundant now — the floating betslip button and
   the My Bets link cover it on every width. */
.top-header .header-betslip-toggle { display: none !important; }

/* Search: hidden in the bar; the search button drops it down below the bar. */
.top-header .header-center {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    max-width: none;
    margin: 0;
    padding: 8px 12px;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border-color);
}
.top-header.search-open .header-center { display: block; }

/* --- A-Z drawer (was the permanent left rail) ------------------------ */
/* Explicit height, not top+bottom with height:auto — that left the drawer as tall
   as its content, so it never scrolled and its last rows were unreachable. */
.sidebar {
    position: fixed;
    top: var(--header-height);
    left: 0;
    bottom: auto;
    height: calc(100dvh - var(--header-height));
    width: min(320px, 86vw);
    z-index: 90;
    /* As a rail it showed the page through; as a drawer over content it needs
       its own surface. */
    background: var(--bg-primary);
    border-right: 1px solid var(--border-subtle);
    overflow-y: auto;
    overscroll-behavior: contain;
    transform: translateX(-100%);
    transition: transform 0.25s ease;
}
.sidebar.open {
    transform: translateX(0);
    box-shadow: var(--shadow-drawer);
}
.sidebar-overlay {
    display: none;
    position: fixed;
    top: var(--header-height);
    left: 0;
    right: 0;
    bottom: 0;
    background: var(--scrim);
    z-index: 89;
}
.sidebar-overlay.active { display: block; }

/* --- Single full-width column --------------------------------------- */
.content { max-width: none; }

/* --- Betslip: bottom sheet on every width ---------------------------- */
.betslip-panel { display: none !important; }

@media (min-width: 901px) {
    /* No bottom nav above 900px, so the floating button sits in the corner. */
    .betslip-fab {
        display: flex;
        bottom: calc(24px + env(safe-area-inset-bottom, 0px));
        right: 24px;
    }
    /* Chat stacks directly above the betslip button, centred on it (48px over
       52px → 2px further in). The slip column is gone, so the old "step clear
       of the open panel" shift no longer applies either. */
    #chat-root,
    body:has(.betslip-panel.open) #chat-root {
        right: 26px;
        bottom: calc(24px + 52px + 12px + env(safe-area-inset-bottom, 0px));
    }
}

/* --- Bottom nav: a flat, full-width bar ------------------------------- */
/* No glass pill: the bar fills the whole bottom edge in the darkest grey,
   items sit straight on it. */
.bottom-nav {
    padding: 0;
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: var(--bg-deep);
    border-top: 1px solid var(--border-subtle);
}
.bottom-nav-inner {
    height: 100%;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    box-shadow: none;
}
.bottom-nav-item { border-radius: 0; }
/* The betslip sheet now rests on a full-width bar, so it spans it too. */
@media (max-width: 900px) {
    .betslip-overlay-panel { width: 100%; }
}

/* --- Tablets and phones ------------------------------------------------ */
@media (max-width: 900px) {
    /* The drawer ends on the bottom nav, not under it. */
    .sidebar { height: calc(100dvh - var(--header-height) - var(--bottom-nav-height)); }
    /* The centre group stays (Live · logo · My Bets, as on b3tsport's phone
       bar) but joins the flow, spread across the room between A-Z and the
       account: an absolutely centred group has no width budget here and would
       run into both sides. */
    .hdr-center {
        position: static;
        transform: none;
        flex: 1 1 auto;
        min-width: 0;
        height: 100%;
        display: flex;
        justify-content: space-evenly;
        align-items: stretch;
    }
    .hdr-center .hdr-tabs,
    .hdr-center-end,
    .header-logo { grid-column: auto; }

    /* Guests: Sign In / Register take the room. Live is in the bottom nav and
       My Bets needs a login anyway. */
    html.is-guest .hdr-tabs,
    html.is-guest #hdr-mybets,
    html.is-guest .hdr-account { display: none; }

    /* The betslip button comes back while the slip holds selections, above
       the bottom nav — the nav's My Bets opens the My Bets page, so this is
       the way to the slip. Chat steps up above it. */
    .betslip-fab.has-items {
        display: flex !important;
        bottom: calc(var(--bottom-nav-height) + 12px);
        right: 16px;
    }
    body:has(.betslip-fab.has-items) #chat-root {
        right: 18px;
        bottom: calc(var(--bottom-nav-height) + 12px + 52px + 12px);
    }
}
@media (max-width: 600px) {
    /* Phone bar: A-Z | Live · logo · My Bets | account. Kazino and search
       live in the bottom nav (Slote / Sporte). */
    .hdr-tab[data-hdr-tab="casino"],
    #hdr-search-btn { display: none; }
    .hdr-az { padding: 0 8px; }
    .hdr-tab,
    .hdr-link { padding: 0 6px; font-size: 13px; }
    .header-logo { padding: 0 4px; }
    .header-logo .logo-img { height: 25px; }
}

/* --- Sport-icon strip (home, under the header) ----------------------- */
.ss-strip {
    display: flex;
    overflow-x: auto;
    scrollbar-width: none;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border-subtle);
    /* Edge to edge: step out of .content's own padding (8px, 10px on phones). */
    margin: -8px -8px 8px;
    height: 80px;
}
.ss-strip::-webkit-scrollbar { display: none; }
.ss-strip:empty { display: none; }

.ss-item {
    flex: 0 0 auto;
    min-width: 84px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 12px 10px 10px;
    color: var(--text-secondary);
    text-decoration: none;
    border-right: 1px solid var(--border-subtle);
    transition: background 0.15s ease, color 0.15s ease;
}
.ss-item:hover,
.ss-item:focus-visible {
    background: var(--bg-hover);
    color: var(--text-primary);
}
.ss-icon {
    width: 26px;
    height: 26px;
    object-fit: contain;
}
.ss-name {
    font-size: 11px;
    line-height: 1.2;
    white-space: nowrap;
}

@media (max-width: 600px) {
    .ss-strip { margin: -10px -10px 2px; }
    .ss-item { min-width: 72px; padding: 10px 8px 8px; }
    .ss-icon { width: 22px; height: 22px; }
}

/* --- Footer ----------------------------------------------------------
   Darkest surface, edge to edge, opened by a full-width "back to top" bar;
   the settings become full-width select boxes and the brand block centres. */
.site-footer {
    margin: 32px -8px 0;
    padding: 0 24px 28px;
    background: var(--bg-deep);
    border-top: 0;
}
.site-footer-totop {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: calc(100% + 48px);
    margin: 0 -24px 28px;
    padding: 12px 16px;
    background: var(--bg-tertiary);
    color: var(--text-secondary);
    border: 0;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}
.site-footer-totop:hover,
.site-footer-totop:focus-visible {
    background: var(--bg-hover);
    color: var(--text-primary);
}

.site-footer-col h4 {
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.4px;
    color: var(--text-secondary);
}

/* Language / odds format as select boxes. */
.site-footer-dropdown-wrap .site-footer-link {
    width: 100%;
    padding: 10px 12px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    color: var(--text-muted);
}
.site-footer-dropdown-wrap .site-footer-link:hover {
    border-color: var(--text-muted);
}
.site-footer-dropdown-wrap .site-footer-link-value { margin-left: auto; }
.site-footer-dropdown { width: 100%; }

.site-footer-divider { background: var(--border-subtle); }
.site-footer-badges { justify-content: center; }
.site-footer-bottom {
    align-items: center;
    text-align: center;
}

@media (max-width: 600px) {
    .site-footer {
        margin: 32px -10px 0;
        padding: 0 16px 20px;
    }
    .site-footer-totop {
        width: calc(100% + 32px);
        margin: 0 -16px 24px;
    }
}

/* =====================================================================
   HOME (2026-10-07 restyle) — #page-sports
   ===================================================================== */

/* Blocks the restyled home no longer shows. Markup and code are kept; their
   loaders are simply not called (hero, promo rail, Bet Boost). */
#page-sports .home-hero-grid,
#page-sports #bet-boost-section,
#page-sports .content-tabs,
#home-popular-leagues,
#league-matches-grouped { display: none !important; }

/* Home blocks sit flush, edge to edge, like the strip above them. */
#page-sports > .section-block,
#page-sports > .ff-module,
#page-sports > #home-ff,
#page-sports > .hb-banner,
#page-sports > .ul-list,
#page-sports > .tc-block {
    margin-left: -8px;
    margin-right: -8px;
}

/* --- Teal section banner ---------------------------------------------- */
.hb-banner {
    display: flex;
    flex-direction: column;
    padding: 5px 10px 10px;
    margin-bottom: 2px;
    background: var(--accent-teal);
    color: var(--header-ink);
    text-decoration: none;
}
.hb-sport { font-size: 10px; line-height: 1.2; opacity: 0.85; }
.hb-title { font-size: 14px; font-weight: 600; line-height: 1.3; }
.hb-banner:hover .hb-title,
.hb-banner:focus-visible .hb-title { text-decoration: underline; }

/* --- Featured-fixture modules ----------------------------------------- */
.ff-module {
    margin-bottom: 8px;
    background: var(--bg-secondary);
    border-top: 1px solid var(--accent-teal);
}
.ff-module:has(.ff-row:empty) { display: none; }
.ff-head {
    margin: 0;
    padding: 8px 10px;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    background: var(--bg-tertiary);
}
.ff-head a {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: inherit;
    text-decoration: none;
}
.ff-head a:hover { text-decoration: underline; }
.ff-head .league-comp-logo { width: 18px; height: 18px; object-fit: contain; }

.ff-row {
    display: flex;
    overflow-x: auto;
    scrollbar-width: none;
}
.ff-row::-webkit-scrollbar { display: none; }

.ff-card {
    flex: 0 0 236px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 8px;
    padding: 10px;
    border-right: 1px solid var(--border-subtle);
}
.ff-teams {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
    color: var(--text-primary);
    text-decoration: none;
}
.ff-teams:hover .ff-name { text-decoration: underline; }
.ff-team {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    font-size: 12px;
}
.ff-name {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ff-kit { width: 14px; height: 14px; flex: 0 0 14px; }
.ff-when { font-size: 11px; color: var(--text-muted); margin-top: 2px; }

.ff-odds { display: flex; gap: 2px; }
.ff-odd {
    flex: 1 1 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 4px;
    min-height: 32px;
    padding: 0 8px;
    background: var(--bg-odds);
    border: 0;
    color: var(--text-primary);
    font: inherit;
    font-size: 12px;
    cursor: pointer;
    transition: background 0.15s ease;
}
.ff-odd-lbl { color: var(--text-muted); }
.ff-odd-val { color: var(--accent-odds); font-weight: 600; font-variant-numeric: tabular-nums; }

/* Shared states for both price-button families. */
.ff-odd:hover:not(:disabled):not(.disabled),
.ul-odd:hover:not(:disabled):not(.disabled) { background: var(--bg-hover); }
.ff-odd.selected,
.ul-odd.selected { background: var(--blue-alt); }
.ff-odd.selected .ff-odd-lbl,
.ff-odd.selected .ff-odd-val,
.ul-odd.selected .ff-odd-lbl,
.ul-odd.selected .ff-odd-val { color: var(--header-ink); }
.ff-odd:disabled,
.ff-odd.disabled,
.ul-odd:disabled,
.ul-odd.disabled { cursor: default; opacity: 0.6; }

/* --- "In play" board header ------------------------------------------ */
#page-sports > .home-live {
    background: var(--bg-secondary);
    border-top: 1px solid var(--accent-teal);
    padding-top: 0;
}
#page-sports > .home-live .live-now-header h3 {
    text-transform: uppercase;
    font-size: 15px;
    letter-spacing: 0.3px;
}

/* --- Upcoming list (wide rows) --------------------------------------- */
.ul-list { margin-bottom: 8px; background: var(--bg-secondary); }
.ul-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    align-items: stretch;
    gap: 8px;
    padding: 6px 10px;
    border-bottom: 1px solid var(--border-subtle);
}
.ul-info {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
    min-width: 0;
    color: var(--text-primary);
    text-decoration: none;
}
.ul-info:hover .ff-name { text-decoration: underline; }
.ul-meta {
    display: flex;
    gap: 10px;
    font-size: 11px;
    color: var(--text-muted);
}
.ul-mkts { color: var(--text-secondary); }
.ul-odds { display: flex; gap: 2px; }
.ul-odd {
    flex: 1 1 0;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    background: var(--bg-odds);
    border: 0;
    font: inherit;
    font-size: 13px;
    cursor: pointer;
    transition: background 0.15s ease;
}
/* The wide cells carry the price alone; the column is self-evident. */
.ul-odd .ff-odd-lbl { display: none; }

/* --- Top competitions ------------------------------------------------ */
.tc-block { margin-bottom: 8px; background: var(--bg-secondary); }
.tc-head {
    margin: 0;
    padding: 10px;
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    border-top: 1px solid var(--accent-teal);
}
.tc-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px;
    border-top: 1px solid var(--border-subtle);
    color: var(--text-secondary);
    font-size: 13px;
    text-decoration: none;
}
.tc-row:hover,
.tc-row:focus-visible { background: var(--bg-hover); color: var(--text-primary); }
.tc-flag { display: inline-flex; width: 18px; justify-content: center; }
.tc-flag img { width: 16px; height: 16px; object-fit: contain; }
.tc-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tc-chev { flex: 0 0 auto; color: var(--text-muted); }

@media (max-width: 600px) {
    #page-sports > .section-block,
    #page-sports > .ff-module,
    #page-sports > #home-ff,
    #page-sports > .hb-banner,
    #page-sports > .ul-list,
    #page-sports > .tc-block {
        margin-left: -10px;
        margin-right: -10px;
    }
    .ff-card { flex-basis: 200px; }
    .ul-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr); }
}


/* =====================================================================
   RESTYLE — live match page (#LM), b3tsport layout (2026-10-07, `sherbimi`)
   Scoped to #page-live-match: the prematch match page shares the market
   classes and keeps its own look until it gets the same pass.
   1. One-line score bar instead of the hero card.
   2. Stats · Timeline tabs over the pitch (Live._applyMdView); the
      latest-goals ticker stays on the Live overview only.
   3. Market tabs as underlined text.
   4. Flat markets: "Name  1.20" with the price right after its name.
   ===================================================================== */

/* --- 1. Score bar ----------------------------------------------------- */
#page-live-match #live-md-detail-top {
    display: flex;
    align-items: center;
    gap: 4px;
    min-height: 54px;
    padding: 4px 8px;
    background: var(--bg-secondary);
    border-radius: 0;
    border-bottom: 1px solid var(--bg-tertiary);
}

#page-live-match #live-md-detail-top .sport-back-link {
    flex: none;
    margin: 0;
    padding: 10px 6px;
    color: var(--text-secondary);
}

#page-live-match #live-match-back-text { display: none; }

#page-live-match .live-md-hero {
    position: relative;
    flex: 1;
    min-width: 0;
    padding: 0 30px 0 0;
}

/* LIVE badge and league name go; the follow bell stays, pinned right. */
#page-live-match .live-md-meta {
    position: absolute;
    top: 50%;
    right: 0;
    transform: translateY(-50%);
    margin: 0;
}

#page-live-match .live-md-badge,
#page-live-match .live-md-league { display: none; }

/* notifications.css lifts the bell 45px for the old tall hero; in the bar it sits level. */
#page-live-match .live-match-top .push-bell { top: 0; }

#page-live-match #live-md-head-duel .live-md-teams {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center;
    gap: 12px;
    margin: 0;
    padding: 0;
}

#page-live-match #live-md-head-duel .live-md-team {
    display: flex;
    flex-direction: row;
    align-items: center;
    min-width: 0;
    gap: 0;
}

#page-live-match #live-md-head-duel .live-md-team:first-child { justify-content: flex-end; text-align: right; }
#page-live-match #live-md-head-duel .live-md-team:last-child  { justify-content: flex-start; text-align: left; }

/* Kits, form and the per-team card/corner counts move out of the bar —
   the counts are on the Stats tab. */
#page-live-match #live-md-head-duel .md-kit-wrap,
#page-live-match #live-md-head-duel .live-md-form,
#page-live-match #live-md-head-duel .live-md-team-stats,
#page-live-match #live-md-head-duel .live-md-stats { display: none !important; }

#page-live-match #live-md-head-duel .live-md-name-row { display: flex; min-width: 0; width: 100%; }
#page-live-match #live-md-head-duel .live-md-team:first-child .live-md-name-row { justify-content: flex-end; }
#page-live-match #live-md-head-duel .live-md-team:last-child .live-md-name-row { justify-content: flex-start; }
#page-live-match #live-md-head-duel .live-md-team:first-child .live-md-team-name { text-align: right; }
#page-live-match #live-md-head-duel .live-md-team:last-child .live-md-team-name { text-align: left; }

#page-live-match #live-md-head-duel .live-md-team-name {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 15px;
    font-weight: 700;
    line-height: 1.2;
    color: var(--text-primary);
    white-space: normal;
}

#page-live-match #live-md-head-duel .live-md-centre {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0;
    padding: 0;
}

#page-live-match #live-md-head-duel .live-md-scoreline {
    display: flex;
    align-items: center;
    gap: 14px;
    order: 1;
}

#page-live-match #live-md-head-duel .live-md-score {
    min-width: 0;
    padding: 0;
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    font-size: 28px;
    font-weight: 800;
    line-height: 1.1;
    color: var(--accent-odds);
}

#page-live-match #live-md-head-duel .live-md-score-sep { display: none; }

/* The clock rides under the score: the pitch shows it for football, but every
   other sport has no pitch to show it on. */
#page-live-match #live-md-head-duel .live-md-status {
    order: 2;
    margin: 0;
    font-size: 11px;
    line-height: 1.2;
}

#page-live-match #live-md-head-duel .live-md-agg,
#page-live-match #live-md-head-duel .live-md-gamepts-row { order: 3; }

/* --- 2. Stats · Timeline over the pitch -------------------------------- */
#page-live-match .live-md-goals-wrap,
#page-live-match #live-md-row-toggle { display: none !important; }

.live-md-view-tabs {
    display: flex;
    justify-content: center;
    gap: 28px;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--bg-tertiary);
}

.live-md-view-tabs[hidden] { display: none; }

.live-md-view-tab {
    padding: 12px 2px 9px;
    background: none;
    border: 0;
    border-bottom: 3px solid transparent;
    border-radius: 0;
    color: var(--text-secondary);
    font: inherit;
    font-size: 15px;
    cursor: pointer;
}

.live-md-view-tab:hover { color: var(--text-primary); }

.live-md-view-tab.active {
    color: var(--text-primary);
    font-weight: 700;
    border-bottom-color: var(--text-primary);
}

/* Pitch view: the stats block is out of the way. */
#page-live-match .live-md-side[data-md-view="pitch"] #live-md-summary { display: none !important; }

/* Stats / Timeline / Players view: the panel takes the pitch's place, opened,
   with its own header and tab row hidden (the tabs above drive it). */
#page-live-match .live-md-side:not([data-md-view="pitch"]) #live-md-scout,
#page-live-match .live-md-side:not([data-md-view="pitch"]) #live-md-scout-stripe,
#page-live-match .live-md-side:not([data-md-view="pitch"]) #live-md-row,
#page-live-match .live-md-side:not([data-md-view="pitch"]) #live-md-media-switch { display: none !important; }

#page-live-match #live-md-summary-toggle,
#page-live-match #live-md-summary .lmst-tabs { display: none; }

#page-live-match #live-md-summary-body[hidden] { display: block; }

#page-live-match #live-md-summary {
    border-radius: 0;
    border: 0;
    margin: 0;
}

@media (max-width: 980px) {
    /* Same ordering contract as the stack above: tabs lead the pitch. */
    #page-live-match #live-md-view-tabs { order: 2; }
}

/* --- 3. Market tabs ----------------------------------------------------- */
#page-live-match .md-categories-wrapper {
    gap: 0;
    margin: 0;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--accent-teal);
}

#page-live-match .md-categories {
    height: auto;
    padding: 0;
    gap: 0;
    border-radius: 0;
}

#page-live-match #live-md-categories .md-cat-btn {
    padding: 14px 12px 11px;
    background: none;
    border: 0;
    border-bottom: 3px solid transparent;
    border-radius: 0;
    color: var(--text-secondary);
    font-size: 15px;
    font-weight: 400;
}

#page-live-match #live-md-categories .md-cat-ico { display: none; }

#page-live-match #live-md-categories .md-cat-btn:hover {
    background: none;
    color: var(--text-primary);
}

#page-live-match #live-md-categories .md-cat-btn.active {
    background: none;
    color: var(--text-primary);
    border-bottom-color: var(--text-secondary);
}

#page-live-match .md-search-toggle {
    height: auto;
    align-self: stretch;
    width: 40px;
    background: none;
    border: 0;
    border-radius: 0;
}

#page-live-match .md-search-bar {
    margin: 0;
    border-radius: 0;
    border: 0;
    border-bottom: 1px solid var(--bg-tertiary);
}

/* --- 4. Flat markets ------------------------------------------------------ */
/* The live match AND the prematch match page: the same flat, ruled markets (the
   prematch page kept the old raised boxes, a lighter fill on the grey card). */
:is(#page-live-match, #page-match-detail) .md-markets {
    gap: 10px;
    padding: 10px 0;
}

:is(#page-live-match, #page-match-detail) .md-market {
    background: var(--bg-hover);
    border: 0;
    border-radius: 0;
}

:is(#page-live-match, #page-match-detail) .md-market-header {
    padding: 14px;
    font-size: 17px;
    border-bottom: 1px solid var(--bg-tertiary);
}

:is(#page-live-match, #page-match-detail) .md-market-odds {
    padding: 0;
    gap: 0;
}

:is(#page-live-match, #page-match-detail) .md-odd-btn {
    margin: 0;
    padding: 14px;
    gap: 8px;
    justify-content: flex-start;
    background: none;
    border: 0;
    border-radius: 0;
}

:is(#page-live-match, #page-match-detail) .md-odd-label {
    flex: 0 1 auto;
    min-width: 0;
    max-width: none;
    font-size: 15px;
    font-weight: 400;
    color: var(--text-secondary);
    white-space: normal;
    line-height: 1.2;
    text-align: left;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
/* Player props (Player Assists, goalscorers…): the player's name, and under it the line
   ("OVER 0.5") in its own small caps — the 2-line clamp above ran the two together
   ("Amir RrahmaniOVER 0.5"). */
:is(#page-live-match, #page-match-detail) .md-odd-label.md-player-name {
    display: flex;
    flex-direction: column;
    -webkit-line-clamp: unset;
    white-space: nowrap;
    text-overflow: ellipsis;
}
:is(#page-live-match, #page-match-detail) .md-player-name .md-player-qual {
    margin-top: 2px;
    line-height: 1.1;
}

:is(#page-live-match, #page-match-detail) .md-odd-value {
    flex: none;
    margin-left: 0;
    font-size: 16px;
    font-weight: 400;
}

@media (hover: hover) {
    :is(#page-live-match, #page-match-detail) .md-odd-btn:hover {
        background: rgba(var(--bg-deep-rgb), 0.18);
        border-color: transparent;
    }
}

:is(#page-live-match, #page-match-detail) .md-odd-btn.selected {
    background: var(--blue-alt);
}

:is(#page-live-match, #page-match-detail) .md-odd-btn.selected .md-odd-label,
:is(#page-live-match, #page-match-detail) .md-odd-btn.selected .md-odd-value { color: var(--text-primary); }

/* Name-and-price markets: side by side, as many columns as selections
   (1X2 in three, Qualifies in two), on every width. */
:is(#page-live-match, #page-match-detail) .md-market-odds.md-team-rows {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, 1fr);
    flex-direction: row;
}

:is(#page-live-match, #page-match-detail) .md-market-odds.md-team-rows .md-odd-btn {
    width: auto;
    min-width: 0;
    padding: 14px;
}

/* Three names in a phone's width: the name takes what the price leaves it and
   wraps to two lines, as on b3t ("Kucukcekmece / Sinop Spor AS 1.20"). */
@media (max-width: 600px) {
    :is(#page-live-match, #page-match-detail) .md-market-odds.md-team-rows .md-odd-label { flex: 1 1 0; }
    :is(#page-live-match, #page-match-detail) .md-odd-btn,
    :is(#page-live-match, #page-match-detail) .md-market-odds.md-team-rows .md-odd-btn { padding: 12px 10px; gap: 6px; }
    :is(#page-live-match, #page-match-detail) .md-odd-label { font-size: 13px; }
    :is(#page-live-match, #page-match-detail) .md-odd-value { font-size: 14px; }
}

/* Two-way markets (Odd/Even…) get a divider between the halves. */
:is(#page-live-match, #page-match-detail) .md-market-odds:not(.md-team-rows):not(.md-many-opts) .md-odd-btn + .md-odd-btn {
    border-left: 1px solid var(--bg-tertiary);
}

/* Long lists: one selection per line, ruled. */
:is(#page-live-match, #page-match-detail) .md-market-odds.md-many-opts {
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}

:is(#page-live-match, #page-match-detail) .md-market-odds.md-many-opts .md-odd-btn {
    justify-content: flex-start;
    border-bottom: 1px solid var(--bg-tertiary);
}

/* Over / Under: Line · Over · Under table */
:is(#page-live-match, #page-match-detail) .md-market-table th {
    padding: 10px 12px;
    font-size: 15px;
    font-weight: 400;
    color: var(--text-secondary);
    background: var(--bg-tertiary);
}

:is(#page-live-match, #page-match-detail) .md-market-table td {
    padding: 0;
    border-top: 1px solid var(--bg-tertiary);
}

:is(#page-live-match, #page-match-detail) .md-market-table td + td { border-left: 1px solid var(--bg-tertiary); }

:is(#page-live-match, #page-match-detail) .md-market-table .md-table-line {
    text-align: center;
    color: var(--text-muted);
    font-size: 15px;
}

:is(#page-live-match, #page-match-detail) .md-market-table td .md-odd-btn { justify-content: center; }

/* Correct score: three ruled columns */
:is(#page-live-match, #page-match-detail) .md-cs-grid {
    gap: 0;
    padding: 0;
}

:is(#page-live-match, #page-match-detail) .md-cs-col + .md-cs-col { border-left: 1px solid var(--bg-tertiary); }

:is(#page-live-match, #page-match-detail) .md-cs-head {
    margin: 0;
    border-radius: 0;
    font-size: 14px;
    font-weight: 400;
    color: var(--text-secondary);
}

:is(#page-live-match, #page-match-detail) .md-cs-col .md-odd-btn {
    width: 100%;
    justify-content: center;
    border-bottom: 1px solid var(--bg-tertiary);
}

/* =====================================================================
   BETSLIP (b3t style, 2026-10-07) — light slip over the dark page
   Collapsed: #bs-dock, a bar docked at the bottom on every width (above the
   bottom nav on phones) while the slip holds selections. Open: the overlay
   sheet, full width, whose head repeats that bar's line. Rows: match name,
   then "Market (Pick)" with the price on the right. Footer: Stake | Place,
   keypad underneath on touch. Colours: the --slip-* / --odd-selected-* tokens.
   ===================================================================== */

/* --- Selected price on every odds family: light grey + dark-green ink ---- */
/* Same selectors as the rules that set white text on the old dark fill, so
   these (later in the file) win without !important. */
.live-now-odd.selected .lno-label,
.live-now-odd.selected .lno-value,
.bb-odd.selected .bb-odd-new,
.odd-btn-card.selected .odd-btn-card-label,
.odd-btn-card.selected .odd-btn-card-value,
.odd-btn-inline.selected,
.live-odd-btn.selected,
.live-odd-btn.selected.odd-chg .oc-new,
.odd-btn-inline.selected.odd-chg .oc-new,
.odd-btn-card.selected .odd-chg .oc-new,
.odd-btn-card.selected .odd-chg .oc-chev,
.md-odd-btn.selected .odd-chg .oc-new,
.md-odd-btn.selected .odd-chg .oc-chev,
.bb-odd.selected .bb-odd-new.odd-chg .oc-new,
.bb-odd.selected .bb-odd-new.odd-chg .oc-chev,
.md-odd-btn.selected .md-odd-label,
.md-odd-btn.selected .md-odd-value,
.md-odd-btn.selected .md-player-qual,
#page-betbuilder .bb-odd.selected .l,
#page-betbuilder .bb-odd.selected .v,
.ff-odd.selected .ff-odd-lbl,
.ff-odd.selected .ff-odd-val,
.ul-odd.selected .ff-odd-lbl,
.ul-odd.selected .ff-odd-val,
#page-live-match .md-odd-btn.selected .md-odd-label,
#page-live-match .md-odd-btn.selected .md-odd-value,
#page-match-detail .md-odd-btn.selected .md-odd-label,
#page-match-detail .md-odd-btn.selected .md-odd-value {
    color: var(--odd-selected-ink);
}
.bb-odd.selected .bb-odd-new { -webkit-text-fill-color: var(--odd-selected-ink); }
.odd-btn-card.selected .odd-chg .oc-rise,
.md-odd-btn.selected .odd-chg .oc-rise,
.bb-odd.selected .bb-odd-new.odd-chg .oc-rise {
    --rise-rgb: var(--odd-selected-ink-rgb);
}

/* --- Collapsed bar ------------------------------------------------------ */
.bs-dock {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 150;
    display: flex;
    align-items: center;
    gap: 10px;
    height: 55px;
    padding: 0 0 0 9px;
    padding-bottom: env(safe-area-inset-bottom, 0px);
    box-sizing: content-box;
    background: var(--slip-bar-bg);
    border: 0;
    border-top: 1px solid var(--slip-line);
    color: var(--slip-ink);
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.bs-dock[hidden],
body.betslip-open .bs-dock,
/* …and while the sheet is still sliding down over it (App._hideBetslipOverlay). */
body.bs-closing .bs-dock { display: none; }
.bs-dock-chev {
    flex: 0 0 55px;
    height: 100%;
    padding: 0 18px;
    box-sizing: border-box;
    color: var(--slip-ink-3);
    border-left: 1px solid var(--slip-line);
}

/* The bar's line, shared with the open sheet's head. */
.bs-head-count {
    flex: 0 0 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--slip-accent);
    color: var(--header-ink);
    font-size: 14px;
}
.bs-head-title { font-size: 16px; color: var(--slip-ink); }
.bs-head-odds {
    flex: 1 1 auto;
    min-width: 0;
    text-align: center;
    font-size: 16px;
    color: var(--slip-ink);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.bs-head-bal {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    font-size: 12px;
    line-height: 1.35;
    color: var(--slip-ink-3);
    white-space: nowrap;
}
.bs-head-bal[hidden] { display: none; }
.bs-head-bal-val { color: var(--slip-ink); }

/* The floating button is replaced by the bar on every width. */
.betslip-fab,
.betslip-fab.has-items { display: none !important; }

/* Page end and chat clear the bar while it shows. */
body:has(#bs-dock:not([hidden])) .site-footer { padding-bottom: calc(28px + 56px); }
#chat-root,
body:has(.betslip-panel.open) #chat-root { bottom: calc(24px + env(safe-area-inset-bottom, 0px)); right: 16px; }
body:has(#bs-dock:not([hidden])) #chat-root { bottom: calc(56px + 16px + env(safe-area-inset-bottom, 0px)); }

@media (max-width: 900px) {
    .bs-dock { bottom: var(--bottom-nav-height); padding-bottom: 0; }
    #chat-root,
    body:has(.betslip-fab.has-items) #chat-root { bottom: calc(var(--bottom-nav-height) + 16px); right: 16px; }
    body:has(#bs-dock:not([hidden])) #chat-root { bottom: calc(var(--bottom-nav-height) + 56px + 16px); }
}

/* --- Open sheet ---------------------------------------------------------- */
.betslip-overlay { background: var(--scrim); }
.betslip-overlay-panel,
body.bs-keyboard-open .betslip-overlay-panel {
    width: 100%;
    max-width: none;
    background: var(--slip-bg);
    border-radius: 0;
}
@media (max-width: 900px) {
    .betslip-overlay-panel { width: 100%; }
}

.betslip-overlay-header {
    height: 55px;
    padding-left: 9px;
    gap: 10px;
    background: var(--slip-bar-bg);
    border-bottom: 1px solid var(--slip-line);
}
/* My Bets is its own page now — the sheet is the slip only. */
.betslip-overlay-header .betslip-tabs { display: none; }
.bs-head {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 10px;
    height: 100%;
}
.betslip-overlay-header .bs-clear-all-header {
    flex: 0 0 auto;
    background: none;
    border: 0;
    color: var(--slip-ink-3);
    font-size: 12px;
}
.betslip-overlay-header .bs-clear-all-header:hover { color: var(--slip-delete); }
.betslip-overlay-header .betslip-close {
    flex: 0 0 55px;
    height: 100%;
    color: var(--slip-ink-3);
    border-left: 1px solid var(--slip-line);
}
.betslip-overlay-header .betslip-close:hover { color: var(--slip-ink); }

.betslip-overlay .bs-content { padding: 0; }
/* The body's own clear-all duplicates the head's. */
.betslip-overlay .bs-header-row { display: none; }

/* Empty state on the light sheet. */
.betslip-overlay .betslip-empty p { color: var(--slip-ink); }
.betslip-overlay .betslip-empty span { color: var(--slip-ink-3); }

/* --- Rows ---------------------------------------------------------------- */
.betslip-overlay .bs-selections-wrap { margin-bottom: 0; }
.betslip-overlay .bs-selections { gap: 0; }
/* Scroll fades in the light sheet's colour (the dark chevron art is dropped:
   a data-URI can't read a token). */
.betslip-overlay .bs-selections-wrap::before {
    background: linear-gradient(to bottom, var(--slip-bg) 35%, transparent);
}
.betslip-overlay .bs-selections-wrap::after {
    background: linear-gradient(to top, var(--slip-bg) 35%, transparent);
}
.betslip-overlay .bs-sel-row {
    border-radius: 0;
    background: var(--slip-bg);
    border-bottom: 1px solid var(--slip-line);
}
.betslip-overlay .bs-selection {
    padding: 8px;
    background: var(--slip-bg);
    border-radius: 0;
}
.betslip-overlay .bs-sel-header { margin-bottom: 1px; align-items: center; }
.betslip-overlay .bs-sel-match {
    font-size: 15px;
    line-height: 19px;
    color: var(--slip-ink);
}
.betslip-overlay .bs-sel-match-link:hover .bs-sel-match-name,
.betslip-overlay .bs-sel-match-link:focus-visible .bs-sel-match-name { color: var(--slip-ink); }
.betslip-overlay .bs-sel-remove { color: var(--slip-ink-3); }
.betslip-overlay .bs-sel-remove:hover { color: var(--slip-delete); }
/* The × stays on touch screens too: swipe (the red "Fshij" panel) is b3t's way, but it is
   undiscoverable, and an invalid/locked leg must always be removable. */
.betslip-overlay .bs-sel-bottom {
    align-items: baseline;
    gap: 8px;
}
.betslip-overlay .bs-sel-line {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 12px;
    color: var(--slip-ink-2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* The market in the line's grey, the pick in black and bold beside it: the two read apart. */
.betslip-overlay .bs-sel-market,
.betslip-overlay .bs-sel-value {
    font-size: 12px;
    font-weight: 400;
    color: var(--slip-ink-2);
}
.betslip-overlay .bs-sel-value {
    font-weight: 700;
    color: var(--slip-ink-pick);
}
.betslip-overlay .bs-sel-value::before { content: ' ('; }
.betslip-overlay .bs-sel-value::after { content: ')'; }
.betslip-overlay .bs-sel-odds {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    padding: 0 3px;
}
.betslip-overlay .bs-sel-koefi {
    font-size: 15px;
    font-weight: 400;
    color: var(--slip-ink-2);
    font-variant-numeric: tabular-nums;
}
.betslip-overlay .bs-sel-koefi-old {
    font-size: 12px;
    color: var(--slip-ink-3);
    text-decoration: line-through;
}
.betslip-overlay .bs-sel-delete {
    background: var(--slip-delete);
    color: var(--header-ink);
    padding-right: 24px;
    font-size: 15px;
}
.betslip-overlay .bs-sel-delete svg { display: none; }
.bs-sel-delete-text { display: none; }
.betslip-overlay .bs-sel-delete-text { display: inline; }

/* --- Totals, systems, stake details -------------------------------------- */
.betslip-overlay .bs-totals,
.betslip-overlay .bs-stake,
.betslip-overlay .bs-result-area:not(:empty) {
    padding: 6px 8px;
    color: var(--slip-ink-2);
}
.betslip-overlay .bs-total-row,
.betslip-overlay .bs-payout-row {
    font-size: 13px;
    color: var(--slip-ink-2);
}
.betslip-overlay .bs-total-odds,
.betslip-overlay .bs-payout-value,
.betslip-overlay .bs-sys-total-val,
.betslip-overlay .bs-sys-min-val {
    color: var(--slip-ink);
    font-weight: 600;
}
.betslip-overlay .bs-stake { padding-top: 0; }
.betslip-overlay .bs-stake-row { margin: 0; gap: 8px; }
.betslip-overlay .bs-stake-row:empty { display: none; }
.betslip-overlay .bs-remember-toggle { margin-left: auto; }
.betslip-overlay .bs-remember-label { color: var(--slip-ink-3); }

/* --- Footer: Stake | Place ----------------------------------------------- */
.bs-foot {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    margin-bottom: 5px;
}
.bs-foot .bs-stake-input-wrap,
body.bs-keyboard-open .betslip-overlay-body .bs-foot .bs-stake-input-wrap {
    flex: 1 1 50%;
    width: auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    text-align: left;
    gap: 0;
    height: 50px;
    margin: 0;
    padding: 0 11px;
    background: var(--bg-secondary);
    border: 0;
    border-radius: 0;
    cursor: text;
}
.bs-foot .bs-stake-label {
    font-size: 11px;
    line-height: 13px;
    color: var(--text-muted);
}
.bs-foot .bs-stake-field {
    display: flex;
    align-items: baseline;
    gap: 5px;
    min-width: 0;
}
.bs-foot .bs-stake-currency {
    order: 3;
    font-size: 12px;
    font-weight: 400;
    color: var(--text-muted);
}
.bs-foot .bs-stake-multiplier { font-size: 12px; color: var(--text-muted); }
.bs-foot .bs-stake-input {
    flex: 0 1 auto;
    width: 9ch;
    padding: 0 2px;
    /* background: var(--slip-accent-tint); */
    color: var(--slip-accent-gkali);
    font-size: 20.8px;
    font-weight: 400;
    line-height: 22px;
}
.bs-foot .bs-stake-input::placeholder { color: var(--slip-accent); opacity: 0.7; }
.bs-foot .bs-place-btn,
body.bs-keyboard-open .betslip-overlay-body .bs-foot .bs-place-btn {
    flex: 1 1 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-width: 0;
    height: 48px;
    margin: 0;
    padding: 0 11px;
    border: 0;
    border-radius: 0;
    background: var(--accent-green-grad);
    color: var(--bg-green-deep);
    font-size: 16px;
    font-weight: 600;
}
.bs-foot .bs-place-btn.bs-place-disabled,
.bs-foot .bs-place-btn:disabled,
body.bs-keyboard-open .betslip-overlay-body .bs-foot .bs-place-btn.bs-place-disabled,
body.bs-keyboard-open .betslip-overlay-body .bs-foot .bs-place-btn:disabled {
    background: var(--slip-place-bg);
    color: var(--text-muted);
    opacity: 1;
    height: 50px;
}
/* Re-offer: the message spans the bar, the two answers take the Place half. */
.bs-foot .bs-reoffer-msg { flex: 1 1 100%; order: -1; padding: 6px 8px; color: var(--slip-ink); }
.bs-foot .bs-reoffer-btns,
body.bs-keyboard-open .betslip-overlay-body .bs-foot .bs-reoffer-btns {
    flex: 1 1 50%;
    display: flex;
    margin: 0;
}
.bs-foot .bs-reoffer-btns > button { flex: 1; border-radius: 0; height: 48px; margin: 0; }

/* --- Keypad (touch) ------------------------------------------------------ */
/* The slip's own Place stays visible beside the stake box (b3t), so the keypad
   drops its Place row and the duplicate remember toggle. */
.bs-kb-header,
.bs-kb-remember { display: none; }
.bs-keyboard {
    background: var(--slip-bg);
    color: var(--slip-key-ink);
    box-shadow: none;
}
.bs-kb-quick,
.bs-kb-numpad,
.bs-kb-footer { background: var(--slip-bg); border-top: 0; }
.bs-kb-quick button,
.bs-kb-numpad button,
.bs-kb-clear,
.bs-kb-done {
    height: 44px;
    padding: 0;
    background: var(--slip-bg);
    color: var(--slip-key-ink);
    border: 0;
    border-right: 1px solid var(--slip-line);
    border-bottom: 1px solid var(--slip-line);
}
.bs-kb-numpad button { font-size: 30px; font-weight: 400; }
.bs-kb-quick button,
.bs-kb-clear,
.bs-kb-done { font-size: 14px; font-weight: 600; }
.bs-kb-numpad button:nth-child(3n),
.bs-kb-quick button:last-child,
.bs-kb-done { border-right: 0; }
.bs-kb-quick button:active,
.bs-kb-numpad button:active,
.bs-kb-clear:active,
.bs-kb-done:active { background: var(--slip-line); }
.bs-kb-back,
.bs-kb-clear { color: var(--slip-key-ink); }
/* The sheet docks straight onto the keypad: the overlay ends where the keypad starts
   (the old formula also took the header off, which left a gap the page showed through). */
body.bs-keyboard-open .betslip-overlay { height: calc(100dvh - var(--bs-keyboard-height)); bottom: auto; }
body.bs-keyboard-open .betslip-overlay-body .bs-content { max-height: calc(100dvh - var(--bs-keyboard-height) - 56px); }
/* quick 44 + numpad 4 × 44 + footer 44 = 264 */
:root { --bs-keyboard-height: calc(264px + env(safe-area-inset-bottom, 0px)); }
@media (max-height: 700px) {
    :root { --bs-keyboard-height: calc(264px + env(safe-area-inset-bottom, 0px)); }
}

/* =====================================================================
   HEADER — phone/tablet bar in equal columns (b3t: A-Z | Live | logo |
   My Bets | account, each centred in its own fifth). Signed-in only; guests
   keep the flex bar their wider Sign In / Register pair needs.
   ===================================================================== */
@media (max-width: 900px) {
    html:not(.is-guest) .top-header {
        display: grid;
        grid-auto-flow: column;
        grid-auto-columns: minmax(0, 1fr);
        align-items: stretch;
        gap: 0;
        padding-left: 0;
        padding-right: 0;
    }
    html:not(.is-guest) .top-header .header-left,
    html:not(.is-guest) .top-header .hdr-center,
    html:not(.is-guest) .top-header .hdr-tabs,
    html:not(.is-guest) .top-header .hdr-center-end,
    html:not(.is-guest) .top-header .header-right { display: contents; }
    html:not(.is-guest) .top-header .hdr-az,
    html:not(.is-guest) .top-header .hdr-tab,
    html:not(.is-guest) .top-header .hdr-link,
    html:not(.is-guest) .top-header .header-logo,
    html:not(.is-guest) .top-header .hdr-icon-btn,
    html:not(.is-guest) .top-header .hdr-account {
        justify-content: center;
        justify-self: stretch;
        height: 100%;
        width: auto;
        min-width: 0;
        padding: 0 4px;
    }
    html:not(.is-guest) .top-header .hdr-tab.active::after { left: 18%; right: 18%; }
    /* A fifth of a phone bar is ~78px: the balance must fit under the icon. */
    html:not(.is-guest) .top-header .hdr-account { padding: 0 2px; overflow: hidden; }
    html:not(.is-guest) .hdr-account .wallet-display { font-size: 10px; gap: 2px; }
    html:not(.is-guest) .hdr-account .currency-badge { font-size: 9px; }
}
/* The VIVA365 wordmark is ~3.9× as wide as it is tall: in an equal fifth it would run
   over Live and My Bets. On a phone the logo column takes the width it needs and
   the four others share the rest. */
@media (max-width: 600px) {
    html:not(.is-guest) .top-header {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) auto minmax(0, 1fr) minmax(0, 1fr);
        grid-auto-columns: minmax(0, 1fr);
    }
    html:not(.is-guest) .top-header .header-logo .logo-img { height: 22px; }
}

/* =====================================================================
   HOME — "In play" heading as a plain b3t title bar
   ===================================================================== */
#page-sports > .home-live .live-now-header {
    flex-wrap: nowrap;
    gap: 12px;
    min-height: 44px;
    margin: 0;
    padding: 0 10px;
    border-bottom: 1px solid var(--border-subtle);
}
#page-sports > .home-live .live-now-header h3 {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 auto 0 0;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 0.2px;
}
#page-sports > .home-live .live-now-header .section-icon { display: none; }
#page-sports > .home-live .live-now-count {
    padding: 0;
    background: none;
    color: var(--text-muted);
    font-size: 13px;
    font-weight: 600;
}
#page-sports > .home-live #live-now-markets {
    align-self: stretch;
    gap: 0;
    padding: 0;
    background: none;
}
#page-sports > .home-live .live-now-header .live-now-mkt-btn {
    position: relative;
    height: 100%;
    padding: 0 10px;
    background: none;
    color: var(--text-muted);
    font-size: 13px;
    font-weight: 600;
}
#page-sports > .home-live .live-now-header .live-now-mkt-btn.active {
    background: none;
    color: var(--text-primary);
}
#page-sports > .home-live .live-now-header .live-now-mkt-btn.active::after {
    content: '';
    position: absolute;
    left: 10px;
    right: 10px;
    bottom: 0;
    height: 2px;
    background: var(--accent-odds);
}
#page-sports > .home-live .live-now-viewall {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-secondary);
}

/* =====================================================================
   HOME — casino row ("Slote Top") as a b3t-style module
   Compact title bar like the fixture modules, then a tight row of smaller
   tiles with the game name laid over the foot of the art.
   ===================================================================== */
#page-sports > #home-slots-promo {
    margin-bottom: 8px;
    padding: 0 0 8px;
    background: var(--bg-secondary);
    border-top: 1px solid var(--accent-teal);
}
#home-slots-promo .section-header {
    margin: 0;
    padding: 8px 10px;
    min-height: 0;
    background: var(--bg-tertiary);
}
#home-slots-promo .section-header h3 {
    font-size: 13px;
    font-weight: 600;
    gap: 0;
}
#home-slots-promo .section-header .section-icon,
#home-slots-promo .scroll-arrows { display: none; }
#home-slots-promo .view-all {
    font-size: 12px;
    font-weight: 600;
    color: var(--text-secondary);
}
#home-slots-promo .slots-promo-scroll {
    gap: 6px;
    padding: 8px 8px 0;
    scroll-padding-left: 8px;   /* snap the first tile to the padding, not the edge */
}

#home-slots-promo .slot-card-promo {
    position: relative;
    flex: 0 0 116px;
    background: none;
    border: 0;
    border-radius: 0;
    overflow: hidden;
}
#home-slots-promo .slot-card-promo:hover { transform: none; }
#home-slots-promo .slot-card-promo:hover .slot-card-thumb { filter: brightness(1.08); }
#home-slots-promo .slot-card-promo .slot-card-meta {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 2;
    padding: 18px 7px 6px;
    background: linear-gradient(to top, rgba(var(--bg-deep-rgb), 0.92), rgba(var(--bg-deep-rgb), 0));
    pointer-events: none;
}
#home-slots-promo .slot-card-promo .slot-card-name {
    font-size: 12px;
    font-weight: 700;
    color: var(--text-primary);
}
#home-slots-promo .slot-card-promo .slot-card-heart {
    width: 22px;
    height: 22px;
    top: 4px;
    right: 4px;
}
#home-slots-promo .slot-card-promo .slot-card-heart svg { width: 12px; height: 12px; }

@media (max-width: 600px) {
    #page-sports > #home-slots-promo { margin-left: -10px; margin-right: -10px; }
    #home-slots-promo .slot-card-promo { flex-basis: 104px; }
}

/* =====================================================================
   AUDIT FIXES (2026-10-07) — selected-price states on the light grey,
   the light betslip's flashes, the frozen stake, and the docked bar
   ===================================================================== */

/* Hovering a selected home price must keep the selected fill (the plain
   hover rule is more specific than .ff-odd.selected). */
.ff-odd.selected:hover:not(:disabled):not(.disabled),
.ul-odd.selected:hover:not(:disabled):not(.disabled) { background: var(--odd-selected-bg); }

/* Odds-change arrows + flash on a selected price: dark green for a rise,
   dark red for a fall (neon / yellow / amber vanish on #e4e4e4). */
[data-koefi].selected .oc-rise,
.live-odd-btn.selected.odd-chg .oc-chev.oc-rise,
.odd-btn-inline.selected.odd-chg .oc-chev.oc-rise,
.odd-btn-card.selected .odd-chg .oc-rise,
.md-odd-btn.selected .odd-chg .oc-rise,
.bb-odd.selected .bb-odd-new.odd-chg .oc-rise {
    --rise-rgb: var(--odd-selected-ink-rgb);
    --flash-rgb: var(--odd-selected-ink-rgb);
}
[data-koefi].selected .odd-chg-down .oc-chev.oc-rise,
[data-koefi].selected.odd-chg-down .oc-chev.oc-rise {
    --rise-rgb: var(--accent-red-ink-rgb);
    --flash-rgb: var(--accent-red-ink-rgb);
}
.ff-odd.selected .odd-chg .oc-new,
.ul-odd.selected .odd-chg .oc-new { color: var(--odd-selected-ink); }
.live-odd-btn.selected.odd-chg-up,
.odd-btn-inline.selected.odd-chg-up { box-shadow: inset 0 0 0 2px var(--odd-selected-ink); }
.live-odd-btn.selected .live-odd-cap { color: var(--odd-selected-ink); }
[data-koefi].selected .odd-lock-icon { color: var(--slip-ink-3); }

/* Light betslip rows: a price move tints the row instead of flashing it
   charcoal, and the flashed number + arrows use dark ink. */
.betslip-overlay .bs-selection.odds-up { animation-name: slipFlashUp; }
.betslip-overlay .bs-selection.odds-down { animation-name: slipFlashDown; }
@keyframes slipFlashUp {
    0%, 100% { background: var(--slip-bg); }
    15%      { background: color-mix(in srgb, var(--slip-accent) 22%, var(--slip-bg)); }
    50%      { background: color-mix(in srgb, var(--slip-accent) 10%, var(--slip-bg)); }
}
@keyframes slipFlashDown {
    0%, 100% { background: var(--slip-bg); }
    15%      { background: color-mix(in srgb, var(--accent-red) 22%, var(--slip-bg)); }
    50%      { background: color-mix(in srgb, var(--accent-red) 10%, var(--slip-bg)); }
}
.betslip-overlay .bs-sel-koefi.odd-chg-up .oc-new { color: var(--slip-accent); }
.betslip-overlay .bs-sel-koefi.odd-chg-down .oc-new { color: var(--accent-red-ink); }
.betslip-overlay .bs-sel-koefi .oc-rise {
    --rise-rgb: var(--odd-selected-ink-rgb);
    --flash-rgb: var(--odd-selected-ink-rgb);
}
.betslip-overlay .bs-sel-koefi.odd-chg-down .oc-chev.oc-rise {
    --rise-rgb: var(--accent-red-ink-rgb);
    --flash-rgb: var(--accent-red-ink-rgb);
}

/* Frozen slip (placing / accepted / operator-pending): the whole stake box is
   inert — clicking its label used to focus the input past the old lock. */
.bs-content.bs-locked .bs-foot .bs-stake-input-wrap {
    pointer-events: none;
    opacity: 0.6;
}
/* The amount stays as it reads when editable — only dimmed with its box above. The
   green tint behind it read as a state of its own while the bet was waiting. */
.betslip-overlay .bs-content.bs-locked .bs-foot .bs-stake-input {
    background: transparent;
    color: var(--slip-accent-gkali);
}

/* The docked bar steps aside for the A-Z drawer and the user menu, which
   would otherwise lose their last rows underneath it. */
body:has(.sidebar.open) .bs-dock,
body.user-menu-open .bs-dock { display: none; }

/* =====================================================================
   VISUAL AUDIT (2026-10-07) — closer to b3tsport's measured values
   ===================================================================== */

/* --- Home "In play": the phone copy of the market switcher (board head) */
.live-now-markets { background: none; }
.lnb-head-markets { gap: 0; padding: 0; background: none; align-self: stretch; }
.lnb-head-markets .live-now-mkt-btn {
    position: relative;
    height: 100%;
    padding: 0 9px;
    background: none;
    color: var(--text-muted);
    font-size: 13px;
    font-weight: 600;
}
.lnb-head-markets .live-now-mkt-btn.active { background: none; color: var(--text-primary); }
.lnb-head-markets .live-now-mkt-btn.active::after {
    content: '';
    position: absolute;
    left: 9px;
    right: 9px;
    bottom: 0;
    height: 2px;
    background: var(--accent-odds);
}

/* --- Live rows: denser, b3t-like type (prices 44px, names 12px/400) ---- */
.live-match-team-name { font-size: 12px; font-weight: 400; color: var(--text-secondary); }
.live-match-minute { font-size: 11px; font-weight: 600; color: var(--text-muted); }
.live-odd-btn,
.odd-btn-inline { font-size: 13px; font-weight: 600; }
.md-odd-value { font-size: 13px; font-weight: 600; }

/* Live league sub-header keeps its own (sport-tinted) background — by request. */

/* --- Counts and active states: no lime (b3t uses none) ----------------- */
.league-match-markets {
    padding: 0;
    background: none;
    border: 0;
    color: var(--text-muted);
    font-weight: 600;
}
.live-mkt-count-val { color: var(--text-muted); font-weight: 600; }
.country-pill.active {
    border-color: var(--accent-teal);
    background: rgba(var(--accent-teal-rgb), 0.12);
}
.md-cat-btn.active {
    background: none;
    color: var(--text-primary);
    box-shadow: inset 0 -2px 0 var(--accent-odds);
}

/* --- Sport / league / match page headings: b3t title-bar scale --------- */
.sport-detail-title h2 { font-size: 18px; font-weight: 700; }
.league-page-title h2 { font-size: 17px; font-weight: 700; }
#page-live-match .md-market-header,
.md-market-header {
    min-height: 44px;
    padding: 0 12px;
    background: var(--bg-odds);
    font-size: 15px;
    font-weight: 700;
}

/* --- Live match score header ------------------------------------------- */
#page-live-match #live-md-head-duel .live-md-score,
#page-live-match .live-md-score,
.live-md-score { font-size: 18px; font-weight: 400; color: var(--accent-odds); }
#page-live-match #live-md-head-duel .live-md-team-name,
#page-live-match .live-md-team-name,
.live-md-team-name { font-size: 13px; font-weight: 400; color: var(--text-secondary); }
.live-md-minute {
    display: inline-block;
    padding: 2px 6px;
    background: rgba(var(--bg-deep-rgb), 0.6);
    color: var(--accent-teal-light);
    font-size: 11px;
    font-weight: 600;
}

/* --- Search: the results drop below the opened search bar, same width -- */
.top-header.search-open .search-dropdown {
    top: calc(var(--header-height) + 57px);
    left: 0;
    right: 0;
    width: auto;
    max-width: none;
    margin-top: 0;
    transform: none;
    border-radius: 0;
    max-height: calc(100dvh - var(--header-height) - 57px);
}

/* --- Home module heads match each other --------------------------------- */
.tc-head { background: var(--bg-tertiary); border-top: 1px solid var(--accent-teal); }
.tc-block { border-top: 0; }

/* --- Price surfaces one step lighter, like b3t (cards #494949, prices #505050) */
.ff-card,
.ul-row { background: var(--bg-event); }
.live-match-row,
.league-match-row { background-color: var(--bg-event); }

/* --- Chat button: off the price column (it sat over every row's "2") --- */
#chat-root,
body:has(.betslip-panel.open) #chat-root,
body:has(#bs-dock:not([hidden])) #chat-root { right: auto; left: 12px; }

/* --- Guest header: centred logo, plain yellow "Hyr" (b3t "Login") ------ */
.top-header .guest-actions { padding: 0; gap: 6px; background: none; border-radius: 0; }
.top-header .guest-btn-login {
    padding: 0 6px;
    background: none;
    color: var(--accent-odds);
    font-weight: 600;
}
.top-header .guest-btn-login:hover { background: none; color: var(--accent-odds); text-decoration: underline; }
@media (max-width: 900px) {
    html.is-guest .top-header {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
        align-items: stretch;
    }
    html.is-guest .top-header .header-left { grid-column: 1; justify-self: start; }
    html.is-guest .top-header .hdr-center { grid-column: 2; flex: none; }
    html.is-guest .top-header .header-right { grid-column: 3; justify-self: end; }
}

/* --- Footer: b3t's lighter grey band --------------------------------------- */
.site-footer {
    background: var(--bg-footer);
    color: var(--text-footer);
    padding-top: 11px;
}
.site-footer-totop {
    width: auto;
    height: 33px;
    margin: 0 0 22px;
    padding: 0 16px;
    background: var(--bg-lightg);
    color: var(--text-footer);
}
.site-footer-legal,
.site-footer-copy,
.site-footer-cookies { color: var(--text-footer); font-size: 11px; line-height: 21px; }
.site-footer-col a,
.site-footer-link { color: var(--text-secondary); }
.site-footer-dropdown-wrap .site-footer-link { background: var(--bg-tertiary); }
@media (max-width: 600px) {
    .site-footer-totop { width: auto; margin: 0 0 18px; }
}

/* =====================================================================
   DESKTOP SPORTS RAIL (2026-10-07) — b3t keeps its sports menu open on the
   left from 960px (280px wide, 330px from 1255px). The A-Z drawer IS that
   menu: on desktop it stays docked, the A-Z button goes, and the page
   starts after it. Phones/tablets keep the drawer.
   ===================================================================== */
:root { --rail-w: 0px; }
@media (min-width: 960px) {
    :root { --rail-w: 280px; }
}
@media (min-width: 1255px) {
    :root { --rail-w: 330px; }
}

@media (min-width: 960px) {
    .sidebar,
    .sidebar.open {
        /* Explicit height: with height:auto the docked rail took its content's
           height (1446px on a 900px screen), so it never scrolled and its last rows
           were out of reach. */
        top: var(--header-height);
        bottom: auto;
        height: calc(100dvh - var(--header-height));
        width: var(--rail-w);
        transform: none;
        transition: none;
        box-shadow: none;
        background: var(--bg-secondary);
        z-index: 80;
    }
    .sidebar-overlay,
    .sidebar-overlay.active { display: none; }
    .top-header #az-toggle { display: none; }

    /* The page, and everything pinned to the bottom of it, start after the rail. */
    .content { margin-left: var(--rail-w); }
    .bs-dock { left: var(--rail-w); }
    .verify-banner { left: var(--rail-w); }
    #chat-root,
    body:has(.betslip-panel.open) #chat-root,
    body:has(#bs-dock:not([hidden])) #chat-root { left: calc(var(--rail-w) + 12px); }
    /* The docked rail is never "open", so the bar has no reason to step aside. */
    body:has(.sidebar.open) .bs-dock { display: flex; }
    body:has(.sidebar.open) .bs-dock[hidden] { display: none; }

    /* b3t's menu rows: 44px, 15px regular, muted; the current one raised. */
    .sidebar .sidebar-item {
        min-height: 44px;
        padding-left: 11px;
        padding-right: 11px;
        font-size: 14px;
        font-weight: 400;
        color: var(--text-muted);
    }
    .sidebar .sidebar-item:hover { background: var(--bg-hover); color: var(--text-primary); }
    .sidebar .sidebar-item.active {
        background: var(--bg-tertiary);
        color: var(--text-primary);
        box-shadow: inset 3px 0 0 var(--accent-teal);
    }
}

/* Live match: the "Fusha" (pitch) tab that leads the view tabs — icon + label. */
.live-md-view-tab-pitch {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}
.live-md-view-tab-pitch .live-md-view-ico { flex: 0 0 auto; }

/* Betslip result messages on the LIGHT sheet: the dark-theme colours (lime
   success, pink-red error, pale amber pending) vanished on #ddd. Dark inks on
   a light tint of the same hue instead. */
.betslip-overlay .bs-result { border-radius: 0; }
.betslip-overlay .bs-result-success {
    background: color-mix(in srgb, var(--slip-accent) 14%, var(--slip-bar-bg));
    border-color: var(--slip-accent);
    color: color-mix(in srgb, var(--slip-accent) 80%, black);
}
.betslip-overlay .bs-result-success svg { stroke: var(--slip-accent); }
.betslip-overlay .bs-result-error {
    background: color-mix(in srgb, var(--accent-red) 12%, var(--slip-bar-bg));
    border-color: var(--accent-red-ink);
    color: var(--accent-red-ink);
}
.betslip-overlay .bs-result-error svg { stroke: var(--accent-red-ink); }
.betslip-overlay .bs-result-pending {
    background: color-mix(in srgb, var(--accent-orange) 14%, var(--slip-bar-bg));
    border-color: color-mix(in srgb, var(--accent-orange) 70%, black);
    color: color-mix(in srgb, var(--accent-orange) 55%, black);
}
/* Betslip system picker — a compact dropdown row on the light sheet:
   "Sisteme  [Dyshe (2/5) · 10x ▾]  (i)". */
.betslip-overlay .bs-systems-pick {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    padding: 6px 8px;
    background: none;
    border: 0;
    border-top: 1px solid var(--slip-line);
}
.bs-sys-select-wrap {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 10px;
}
.betslip-overlay .bs-systems-pick .bs-systems-title {
    flex: 0 0 auto;
    font-size: 13px;
    font-weight: 600;
    color: var(--slip-ink-2);
    text-transform: none;
    letter-spacing: 0;
}
.bs-sys-select {
    flex: 1 1 auto;
    min-width: 0;
    height: 36px;
    padding: 0 10px;
    background: var(--slip-bar-bg);
    color: var(--slip-ink);
    border: 1px solid var(--slip-line);
    border-radius: 0;
    font: inherit;
    font-size: 13px;
    cursor: pointer;
}
.bs-sys-select:focus-visible { outline: 2px solid var(--slip-accent); outline-offset: 1px; }
.bs-sys-select:disabled { opacity: 0.6; cursor: default; }
.betslip-overlay .bs-sys-info {
    flex: 0 0 28px;
    width: 28px;
    height: 28px;
    padding: 0;
    border: 1px solid var(--slip-line);
    border-radius: 50%;
    background: var(--slip-bar-bg);
    color: var(--slip-accent);
    font-size: 13px;
    font-weight: 700;
    font-style: italic;
    cursor: pointer;
}
/* Slip: a smaller system dropdown, and info that reads on the light sheet. */
.betslip-overlay .bs-systems-pick { padding: 4px 8px; gap: 6px; }
.betslip-overlay .bs-sys-select-wrap { flex: 0 1 auto; gap: 8px; }
.betslip-overlay .bs-systems-pick .bs-systems-title { font-size: 12px; }
.bs-sys-select {
    flex: 0 1 auto;
    width: auto;
    max-width: 210px;
    height: 28px;
    padding: 0 6px;
    font-size: 12px;
}
/* The (i): a solid disc, not a faint outline. */
.betslip-overlay .bs-sys-info {
    flex: 0 0 22px;
    width: 22px;
    height: 22px;
    border: 0;
    background: var(--slip-accent);
    color: var(--header-ink);
    font-size: 12px;
    line-height: 22px;
}
.betslip-overlay .bs-sys-info:hover { background: color-mix(in srgb, var(--slip-accent) 80%, black); }
/* Stake limit hint ("Shuma minimale është L100.00"): dark ink, not the dark theme's muted grey. */
.betslip-overlay .bs-stake-limit {
    font-size: 12px;
    color: var(--slip-ink-2);
    padding: 2px 0 4px;
}
.betslip-overlay .bs-stake-limit-bad { color: var(--accent-red-ink); }
/* No self-registration in this version (Register.enabled = false in register.js):
   every Register button / link is hidden; Sign In stays. */
#guest-register-btn,
#auth-modal-register,
[data-mybets-auth="register"],
#open-register-link,
.login-footer .separator { display: none !important; }

/* No betting-exchange promotion in this version: its menu entries go. */
#sidebar-exchange-section,
.browse-nav-item[data-page="exchange"] { display: none !important; }
/* Home live board: no per-sport head strip (by request). On phones the market
   switcher lived in that head, so its section-header copy comes back instead. */
.live-now-board-head { display: none !important; }
@media (max-width: 600px) {
    #page-sports > .home-live #live-now-markets { display: flex; }
    #page-sports > .home-live .live-now-header .live-now-viewall { display: none; }
    #page-sports > .home-live .live-now-header { gap: 6px; padding: 0 8px; }
    #page-sports > .home-live .live-now-header h3 { font-size: 14px; white-space: nowrap; gap: 6px; }
    #page-sports > .home-live .live-now-header .live-now-mkt-btn { padding: 0 7px; font-size: 12px; }
}
/* Live match, sport without a pitch, panel closed by the user: the slot is empty. */
#page-live-match .live-md-side[data-md-view="closed"] #live-md-summary { display: none !important; }

/* Finance tabs on phones: each tab is as wide as its label and the strip starts at
   the first one; the chosen tab is only scrolled into view (Finance._revealActiveTab). */
@media (max-width: 600px) {
    .fin-tab { flex: 0 0 auto; min-width: 0; white-space: nowrap; }
}
/* Place button, b3t style: the action on top, what the ticket can win under it. */
.bs-foot .bs-place-btn,
body.bs-keyboard-open .betslip-overlay-body .bs-foot .bs-place-btn {
    flex-direction: column;
    gap: 1px;
    line-height: 1.15;
}
.bs-foot .bs-pb-label { font-size: 17px; font-weight: 600; }
.bs-foot .bs-pb-win {
    font-size: 12px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    opacity: 0.85;
}
/* The stake box sizes to its amount (Betslip._sizeStakeInput). */
.bs-foot .bs-stake-input { flex: 0 0 auto; max-width: 100%; }
/* My Bets: b3t's "Totali" bar under the ticket list. */
/* Staked · Won · Net (MyBets._buildTotal): three equal cells, a small label over each
   figure. Won is green; the net is green above zero and red below. */
.mybets-total {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px;
    padding: 8px 12px;
    background: var(--mybets-total-bg);
    color: var(--slip-ink);
}
.mybets-total-cell { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.mybets-total-cell:nth-child(2) { align-items: center; text-align: center; }
.mybets-total-cell:last-child { align-items: flex-end; text-align: right; }
.mybets-total-lbl { font-size: 12px; color: var(--slip-ink-2); }
.mybets-total-val {
    max-width: 100%;
    font-size: 17px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.mybets-total-val small { font-size: 11px; font-weight: 400; }
.mybets-total-won .mybets-total-val,
.mybets-total-pos .mybets-total-val { color: var(--odd-selected-ink); }
.mybets-total-neg .mybets-total-val { color: var(--accent-red-ink); }
@media (max-width: 420px) {
    .mybets-total-val { font-size: 15px; }
}
/* =====================================================================
   LOGIN SCREEN (2026-10-07 redesign) — the site's own frame: teal bar,
   charcoal card with a #444343 head and teal rule, square fields, green
   Sign In, grey 18+ footer. No forgot-password link, no exchange teaser,
   no stadium photo.
   ===================================================================== */
#login-section .login-overlay {
    justify-content: flex-start;
    gap: 0;
    padding: 0;
    background: var(--bg-primary);
}
#login-section .login-overlay::before,
#login-section .login-container::before { display: none; }

/* --- Top bar --------------------------------------------------------------- */
.lg-bar {
    position: sticky;
    top: 0;
    z-index: 20;
    width: 100%;
    height: var(--header-height);
    padding-top: env(safe-area-inset-top, 0px);
    box-sizing: border-box;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: stretch;
    background: var(--header-bg);
    color: var(--header-ink);
}
.lg-bar-back {
    justify-self: start;
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 0 14px;
    color: var(--header-ink);
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
}
.lg-bar-back:hover { background: rgba(var(--bg-deep-rgb), 0.12); color: var(--header-ink); }
.lg-bar-logo { align-self: center; height: 34px; width: auto; }
/* The language selector sits in the bar (no longer a floating corner box). */
#login-section .login-lang-corner.lg-bar-lang {
    position: relative;
    top: auto;
    right: auto;
    justify-self: end;
    align-self: stretch;
    display: flex;
    margin: 0;
}
#login-section .lg-bar-lang .login-lang-select {
    min-height: 0;
    height: 100%;
    padding: 0 14px;
    background: none;
    border: 0;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    color: var(--header-ink);
    font-weight: 600;
}
#login-section .lg-bar-lang .login-lang-select:hover { background: rgba(var(--bg-deep-rgb), 0.12); }
#login-section .lg-bar-lang .login-lang-chev { color: var(--header-ink); }
#login-section .login-lang-menu { top: 100%; border-radius: 0; }
#login-section .login-lang-opt.active { color: var(--accent-odds); }

/* --- Card ---------------------------------------------------------------------- */
#login-section .login-container {
    margin: auto;
    padding: 0;
    max-width: 420px;
    background: var(--bg-secondary);
    border: 0;
    border-radius: 0;
    box-shadow: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}
.lg-card-head {
    display: flex;
    align-items: center;
    min-height: 48px;
    padding: 0 20px;
    background: var(--bg-tertiary);
    border-top: 1px solid var(--accent-teal);
}
.lg-card-head h2 { margin: 0; font-size: 16px; font-weight: 700; letter-spacing: 0.2px; color: var(--text-primary); }
#login-section .login-logo { display: none; }   /* the logo is in the bar */
#login-section #login-form,
#login-section #forgot-form,
#login-section #unlock-form { padding: 24px 24px 24px; }
#login-section .login-welcome { text-align: left; margin-bottom: 20px; }
#login-section .login-welcome h1 { font-size: 15px; font-weight: 700; margin: 0 0 4px; letter-spacing: 0; }
#login-section .login-welcome p { font-size: 13px; color: var(--text-secondary); }

#login-section .form-group { margin-bottom: 18px; }
#login-section .form-group label { font-size: 12px; font-weight: 600; color: var(--text-muted); }
#login-section .form-group input {
    height: 44px;
    box-sizing: border-box;
    padding: 0 12px;
    background: var(--bg-input);
    border: 1px solid var(--border-color);
    border-radius: 0;
    color: var(--text-primary);
    font-size: 15px;
}
#login-section .form-group input:focus { border-color: var(--accent-teal); outline: none; }
/* "Shfaq" sits INSIDE the field's right end (it is absolutely placed over the
   input): a full-height cell divided off by one line. */
#login-section .reg-password-row input { padding-right: 84px; }
#login-section .reg-pwd-toggle {
    top: 1px;
    right: 1px;
    bottom: 1px;
    transform: none;
    height: auto;
    min-width: 72px;
    padding: 0 14px;
    justify-content: center;
    background: none;
    border: 0;
    border-left: 1px solid var(--border-color);
    border-radius: 0;
    color: var(--accent-odds);
    font-size: 13px;
    font-weight: 600;
}
#login-section #login-btn,
#login-section #forgot-btn,
#login-section #unlock-send-btn,
#login-section #unlock-btn {
    width: 100%;
    height: 48px;
    margin-top: 6px;
    background: var(--accent-green-grad);
    border: 0;
    border-radius: 0;
    color: var(--bg-green-deep);
    font-size: 17px;
    font-weight: 700;
}

/* No forgot-password link (by request) — and Register is off anyway. */
#login-section #login-form .login-footer { display: none; }
/* No betting-exchange teaser. */
#login-section .login-promo { display: none !important; }

/* "Continue browsing without an account": a quiet link under a rule. */
#login-section .login-browse-footer {
    margin: 8px 24px 0;
    padding: 0;
    border-top: 1px solid var(--border-color);
}
#login-section .login-browse-footer a {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 48px;
    color: var(--text-secondary);
    font-size: 13px;
    font-weight: 600;
    text-decoration: none;
}
#login-section .login-browse-footer a:hover { color: var(--text-primary); }

/* --- Footer strip ------------------------------------------------------------- */
.lg-foot {
    width: 100%;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-height: 56px;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom, 0px));
    background: var(--bg-footer);
    color: var(--text-footer);
    font-size: 12px;
}
.lg-foot-age {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border: 1px solid var(--text-footer);
    border-radius: 50%;
    font-size: 11px;
    font-weight: 700;
}

/* Phones: the card runs edge to edge under the bar, like the rest of the site. */
@media (max-width: 520px) {
    #login-section .login-container { max-width: none; margin: 0 0 auto; }
    #login-section #login-form,
    #login-section #forgot-form,
    #login-section #unlock-form { padding: 24px 16px 24px; }
    #login-section .login-browse-footer { margin: 8px 16px 0; }
    #login-section .lg-bar-lang .login-lang-name { display: none; }
}
/* The login heading takes focus for screen readers (App._focusAuthHeading); no ring for that. */
#login-section #login-title:focus { outline: none; }
/* Login required (Session:LoginRequired → html.login-required): no site behind the login
   screen, so no way back to it. The bar's back slot keeps its width (hidden, not removed),
   so the logo stays centred. */
html.login-required #login-section .lg-bar-back { visibility: hidden; }
html.login-required #login-section .login-browse-footer { display: none; }
/* No KYC on this deployment (Kyc:Enabled=false → html.no-kyc): no verify-email banner and
   no verification card on My Account. !important: the banner's display is set inline. */
html.no-kyc #verify-banner,
html.no-kyc #kyc-section { display: none !important; }
/* =================================================================
   Volleyball / table tennis / ice hockey live panels (js/livesports.js)
   Team colours follow the tennis panel: home = accent green, away = violet.
   ================================================================= */
:root {
    --team-home: var(--accent-green-neon);
    --team-away: #a855f7;
    --team-away-soft: rgba(168, 85, 247, 0.28);
    --team-home-soft: rgba(154, 232, 73, 0.24);
    --rink-ice: #e9f1f6;
    --rink-board: #9fb4c2;
    --rink-crease: rgba(20, 117, 225, 0.25);
    --rink-trail: rgba(26, 46, 57, 0.45);
    --rink-puck: #111820;
    --rink-halo: rgba(17, 24, 32, 0.18);
}

/* Periods header: the set in play and the winner's boxed total. */
.lmhp-h-cur { color: var(--accent-green-neon); }
.lmhp-total.is-winner { box-shadow: inset 0 0 0 1.5px var(--accent-green-neon); }

.lvs-block {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 14px;
}
.lvs-h {
    margin: 0;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.lvs-h-sc {
    margin-left: 4px;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0;
}
.lvs-note {
    margin: 0;
    font-size: 11px;
    color: var(--text-muted);
    display: flex;
    align-items: center;
    gap: 6px;
}

/* The statistics panel as football's (the soccer module's AllStatsAdvanced, js/livesports.js
   _footballHtml): up to three wheels across - the sides' figures either side of a ring split
   in their colours - then the dual bars, a total over its part; centred, at most 440px wide.
   The sizes and greys are the module's. */
.lvs-st {
    max-width: 440px;
    margin: 0 auto;
}
.lvs-fb { display: flex; flex-direction: column; gap: 18px; padding: 8px 0 4px; }
.lvs-more > .lvs-fb { padding-top: 18px; }
.lvs-fb-wheels { display: flex; justify-content: center; }
.lvs-wh {
    flex: 1 1 0;
    min-width: 0;
    max-width: 123px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 7px;
}
.lvs-wh-l {
    width: 100%;
    font-size: 11px;
    line-height: 13px;
    color: var(--color-grey6);
    text-align: center;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.lvs-wh-row { display: flex; align-items: center; justify-content: center; width: 100%; }
.lvs-wh-v {
    flex: 1 1 0;
    min-width: 0;
    font-size: 14px;
    font-weight: 700;
    line-height: 16px;
    color: var(--color-grey6);
    text-align: center;
    font-variant-numeric: tabular-nums;
}
.lvs-wh-c { position: relative; flex: none; width: 34px; height: 34px; }
.lvs-wh-ring { display: block; width: 34px; height: 34px; }
.lvs-wh-ring circle { fill: none; stroke-width: 4; }
.lvs-wh-h { stroke: var(--team-home); }
.lvs-wh-a { stroke: var(--team-away); }
.lvs-wh-empty { stroke: var(--stat-track); }
.lvs-wh-ico {
    position: absolute;
    left: 9px;
    top: 9px;
    width: 16px;
    height: 16px;
    color: var(--color-grey6);
}
.lvs-fb-duals { display: flex; flex-direction: column; align-items: center; gap: 14px; }
.lvs-dual {
    width: 100%;
    max-width: 260px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
}
.lvs-dual-l { font-size: 11px; line-height: 13px; color: var(--color-grey6); text-align: center; }
.lvs-dual-row { display: flex; align-items: center; width: 100%; gap: 6px; }
.lvs-dual-side {
    flex: none;
    min-width: 37px;
    text-align: center;
    font-size: 13px;
    line-height: 15px;
    color: var(--color-grey6);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.lvs-dual-side b { font-weight: 700; }
.lvs-dual-sep { margin: 0 1px; color: var(--text-muted); }
.lvs-dual-bars { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 4px; padding: 3px 0; }
.lvs-dual-bar { display: flex; gap: 2px; height: 3px; }
.lvs-dual-bar.is-empty { background: var(--stat-track); }
.lvs-dual-bar i { display: block; min-width: 0; height: 3px; }
.lvs-dual-h { background: var(--team-home); }
.lvs-dual-a { background: var(--team-away); }

/* The run in progress and the last six points, one line over the pills. */
.lvs-now {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 6px 16px;
    margin: 0 0 12px;
    font-size: 11px;
    line-height: 13px;
    color: var(--text-muted);
}
.lvs-run {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-weight: 700;
    color: var(--text-secondary);
}
.lvs-last6 { display: inline-flex; align-items: center; gap: 4px; }
.lvs-last6-lbl { margin-right: 2px; }
.lvs-dot { width: 7px; height: 7px; border-radius: 50%; display: inline-block; flex: 0 0 auto; }
.lvs-dot-h { background: var(--team-home); }
.lvs-dot-a { background: var(--team-away); }

/* Match | Game 1 | Game 2 … — small pills, centred; more than fit scroll sideways (the
   auto margins centre them and give way once they overflow). */
.lvs-scope {
    display: flex;
    gap: 4px;
    overflow-x: auto;
    scrollbar-width: none;
    margin: 0 0 16px;
}
.lvs-scope::-webkit-scrollbar { display: none; }
.lvs-scope > :first-child { margin-left: auto; }
.lvs-scope > :last-child { margin-right: auto; }
.lvs-scope-btn {
    flex: 0 0 auto;
    height: 25px;
    padding: 0 10px;
    border: 0;
    border-radius: var(--radius-lg25);
    background: transparent;
    color: var(--text-muted);
    font: inherit;
    font-size: 11px;
    line-height: 13px;
    cursor: pointer;
    transition: background-color 0.15s, color 0.15s;
}
.allow-hover .lvs-scope-btn:hover { color: var(--text-primary); }
.lvs-scope-btn:focus-visible { outline: 2px solid var(--accent-green-neon); outline-offset: 1px; }
.lvs-scope-btn.active {
    background: var(--stat-pill-bg);
    color: var(--text-primary);
    font-weight: 700;
}

/* "Show more", as the football module's (ml1-StatsContainerToggleButton): a 25px pill in a
   45px bar under the panel, the rest opening above it. */
.lvs-more[hidden] { display: none; }
.lvs-more > .lvs-block:first-child { margin-top: 18px; }
/* Inside the grid's column the point log, the momentum chart and the goals line up on its axis. */
.lvs-st .lvs-block { align-items: center; text-align: center; }
.lvs-st .lvs-ptlog,
.lvs-st .lvs-note { justify-content: center; }
.lvs-st .lvs-mom,
.lvs-st .lvs-gl { align-self: stretch; text-align: left; }
.lvs-more-bar {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 45px;
}
.lvs-more-btn {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 25px;
    padding: 0 10px;
    border: 0;
    border-radius: var(--radius-lg25);
    background: var(--stat-pill-bg);
    color: var(--text-secondary);
    font: inherit;
    font-size: 11px;
    line-height: 13px;
    cursor: pointer;
}
.allow-hover .lvs-more-btn:hover { color: var(--text-primary); }
.lvs-more-btn:focus-visible { outline: 2px solid var(--accent-green-neon); outline-offset: 1px; }
.lvs-more-btn svg { flex: 0 0 auto; transition: transform 0.2s; }
.lvs-more-btn.is-open svg { transform: rotate(180deg); }

/* Volleyball momentum chart. */
.lvs-mom { display: flex; flex-direction: column; gap: 2px; }
.lvs-mom-svg { width: 100%; height: 84px; display: block; }
.lvs-mom-y {
    font-size: 10px;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.lvs-mom-zero { stroke: var(--border-color); stroke-width: 1; }
.lvs-mom-area-h { fill: var(--team-home-soft); }
.lvs-mom-area-a { fill: var(--team-away-soft); }
.lvs-mom-line { fill: none; stroke: var(--text-primary); stroke-width: 1.5; stroke-linejoin: round; }

/* Table tennis point log. */
.lvs-ptlog {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}
.lvs-pt {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 2px 6px;
    border-radius: var(--radius-sm);
    background: var(--bg-tertiary);
    font-size: 11px;
    font-variant-numeric: tabular-nums;
    color: var(--text-primary);
    border-bottom: 2px solid transparent;
}
.lvs-pt-h { border-bottom-color: var(--team-home); }
.lvs-pt-a { border-bottom-color: var(--team-away); }
.lvs-pt-srv {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--text-secondary);
    display: inline-block;
}

/* Timeline (all three sports): newest first, under the game / set / period it belongs to;
   the latest few, the rest under "Show more". */
.lvs-tl {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
}
.lvs-tl-grp {
    padding: 10px 2px 4px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.lvs-tl > .lvs-tl-grp:first-child { padding-top: 2px; }
.lvs-tl-item {
    display: flex;
    align-items: baseline;
    gap: 8px;
    padding: 6px 2px;
    font-size: 12px;
    line-height: 16px;
    color: var(--text-secondary);
    border-bottom: 1px solid var(--border-subtle, var(--border-color));
}
.lvs-tl-item.is-goal { color: var(--text-primary); font-weight: 700; }
.lvs-tl-dot { flex: 0 0 auto; width: 7px; height: 7px; border-radius: 50%; background: var(--text-muted); transform: translateY(-1px); }
.lvs-tl-h .lvs-tl-dot { background: var(--team-home); }
.lvs-tl-a .lvs-tl-dot { background: var(--team-away); }
.lvs-tl-txt { min-width: 0; overflow-wrap: anywhere; }
.lvs-pb-cur th, .lvs-pb-cur td { color: var(--accent-green-neon); }
/* The sets / periods table of these sports: a thin bar in the two teams' colours. */
.lvs-pb .lmst-pb-bar {
    gap: 2px;
    height: 3px;
    border-radius: var(--radius-sm);
    background: transparent;
}
.lvs-pb .lmst-pb-bar-h { background: var(--team-home); }
.lvs-pb .lmst-pb-bar-a { background: var(--team-away); }
.lvs-tl-block .lvs-more-bar { min-height: 40px; }

/* Ice hockey. */
.lvs-winner, .lvs-situation {
    margin: 6px 0 0;
    text-align: center;
    font-size: 12px;
    font-weight: 700;
    color: var(--accent-green-neon);
}
.lvs-situation { color: var(--text-primary); }
.lvs-st > .lvs-winner,
.lvs-st > .lvs-situation { margin: 0 0 12px; }
.lvs-so-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto 24px;
    align-items: center;
    gap: 10px;
    font-size: 12px;
}
.lvs-so-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-primary); }
.lvs-so-now { font-style: normal; font-size: 10px; color: var(--accent-green-neon); margin-left: 4px; }
.lvs-so-shots { display: inline-flex; gap: 5px; }
.lvs-so-shot { width: 12px; height: 12px; border-radius: 50%; display: inline-block; border: 1.5px solid var(--text-muted); }
.lvs-so-shot.is-in { background: var(--accent-green-neon); border-color: var(--accent-green-neon); }
.lvs-so-shot.is-miss { background: var(--accent-red); border-color: var(--accent-red); }
.lvs-so-sum { text-align: right; font-variant-numeric: tabular-nums; }

.lvs-gl { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.lvs-gl-per {
    margin-top: 6px;
    font-size: 10px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.lvs-gl-goal {
    display: grid;
    grid-template-columns: 44px minmax(0, 1fr) auto;
    align-items: center;
    gap: 8px;
    padding: 4px 0;
    font-size: 12px;
    border-bottom: 1px solid var(--border-subtle, var(--border-color));
}
.lvs-gl-time { color: var(--text-muted); font-variant-numeric: tabular-nums; }
.lvs-gl-team { min-width: 0; display: flex; align-items: center; gap: 6px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-primary); }
.lvs-gl-kit { flex: 0 0 auto; width: 10px; height: 10px; border-radius: 2px; background: var(--text-muted); box-shadow: inset 0 0 0 1px var(--border-color); }
.lvs-gl-h .lvs-gl-kit:not([style]) { background: var(--team-home); }
.lvs-gl-a .lvs-gl-kit:not([style]) { background: var(--team-away); }
.lvs-gl-score { font-variant-numeric: tabular-nums; }

/* Live rink (#live-md-scout) — the hockey counterpart of the football pitch. */
.lvs-rink-wrap {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.lvs-rink-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    min-height: 22px;
}
.lvs-rink-clock {
    padding: 2px 9px;
    border-radius: 999px;
    background: var(--bg-tertiary);
    font-size: 12px;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--text-primary);
}
.lvs-rink-sit {
    padding: 2px 9px;
    border-radius: 999px;
    background: var(--accent-green-neon);
    color: var(--bg-primary);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.04em;
}
.lvs-rink-live { width: 100%; height: auto; display: block; }
.lvs-rink-ice { fill: var(--rink-ice); stroke: var(--rink-board); stroke-width: 2; }
.lvs-rink-red { stroke: var(--accent-red); stroke-width: 1.6; }
.lvs-rink-blue { stroke: var(--accent-blue); stroke-width: 2; }
.lvs-rink-goalline { stroke: var(--accent-red); stroke-width: 0.6; }
.lvs-rink-crease { fill: var(--rink-crease); stroke: var(--accent-red); stroke-width: 0.6; }
.lvs-rink-net { fill: none; stroke: var(--rink-board); stroke-width: 0.8; }
.lvs-rink-circle { fill: none; stroke: var(--accent-red); stroke-width: 0.6; opacity: 0.8; }
.lvs-rink-dot { fill: var(--accent-red); }
.lvs-rink-trail {
    fill: none;
    stroke: var(--rink-trail);
    stroke-width: 1.2;
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-dasharray: 2 2;
}
.lvs-rink-puck { transition: transform 0.8s cubic-bezier(0.3, 0.7, 0.3, 1); }
.lvs-rink-disc { fill: var(--rink-puck); }
.lvs-rink-halo { fill: var(--rink-halo); }
.lvs-rink-puck.is-h .lvs-rink-halo { fill: var(--team-home-soft); stroke: var(--team-home); stroke-width: 0.8; }
.lvs-rink-puck.is-a .lvs-rink-halo { fill: var(--team-away-soft); stroke: var(--team-away); stroke-width: 0.8; }
.lvs-rink-puck.is-idle { opacity: 0.35; }
@media (prefers-reduced-motion: reduce) {
    .lvs-rink-puck { transition: none; }
}

/* Stats popover: the set / game in play. */
.lsp-head.lsp-cur,
.lsp-cell.lsp-cur { color: var(--accent-green-neon); }

/* =====================================================================
   SHARE A TICKET (ported from gli-33 6df4ceb0) — js/ticketshare.js draws the ticket
   as an image / one-page PDF and hands it to the phone's share sheet. The button sits
   in the open ticket's action row (beside Repeat / Bet Details) and under the Bet
   Details summary; a won ticket's reads "Share the win", in green.
   ===================================================================== */
.mybets-share-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}
.mybets-share-btn svg { flex: 0 0 auto; color: var(--accent-odds); }
.mybets-share-win, .mybets-share-win svg { color: var(--odd-selected-ink); }
.mybets-legs-actions .mybets-share-win { color: var(--accent-green); }
.mybets-legs-actions .mybets-share-win svg { color: var(--accent-green); }

.mybets-detail-share { padding: 12px; }
.mybets-share-btn-wide {
    width: 100%;
    height: 44px;
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    color: var(--text-primary);
    font: inherit;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
}
.mybets-share-btn-wide:hover { background: var(--bg-hover); }
.mybets-share-btn-wide.mybets-share-win {
    border-color: var(--accent-green);
    background: color-mix(in srgb, var(--accent-green) 12%, transparent);
    color: var(--accent-green);
}
.mybets-share-btn-wide.mybets-share-win svg { color: var(--accent-green); }
/* The share sheet: a bottom sheet on phones, a centred card from 600px. */
.tsh-backdrop {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    background: color-mix(in srgb, var(--bg-deep) 80%, transparent);
}
.tsh-sheet {
    display: flex;
    flex-direction: column;
    gap: 12px;
    max-height: 92dvh;
    overflow-y: auto;
    padding: 10px 16px calc(20px + env(safe-area-inset-bottom, 0px));
    border-radius: var(--radius-md) var(--radius-md) 0 0;
    border-top: 1px solid var(--border-color);
    background: var(--bg-secondary);
    color: var(--text-primary);
}
@media (min-width: 600px) {
    .tsh-backdrop { justify-content: center; align-items: center; }
    .tsh-sheet { width: 420px; border-radius: var(--radius-md); border: 1px solid var(--border-color); padding-bottom: 20px; }
    .tsh-grip { display: none; }
}
.tsh-grip { align-self: center; width: 40px; height: 4px; border-radius: var(--radius-sm); background: var(--bg-lightg); }
.tsh-head { display: flex; align-items: flex-start; gap: 12px; }
.tsh-head-text { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
.tsh-title { margin: 0; font-size: 18px; font-weight: 800; }
.tsh-sub { font-size: 12px; color: var(--text-muted); }
.tsh-close {
    width: 44px;
    height: 44px;
    margin: -8px -10px 0 0;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    border-radius: var(--radius-md);
    background: transparent;
    color: var(--text-secondary);
    cursor: pointer;
}
.tsh-close:focus-visible,
.tsh-option:focus-visible { outline: 2px solid var(--text-primary); outline-offset: 2px; }
.tsh-preview {
    display: flex;
    justify-content: center;
    padding: 10px;
    border-radius: var(--radius-dec);
    border: 1px solid var(--border-color);
    background: var(--bg-deep);
}
.tsh-preview-img { display: block; max-width: 100%; max-height: 34dvh; border-radius: var(--radius-sm); }
.tsh-preview-wait { display: flex; align-items: center; gap: 10px; min-height: 120px; font-size: 13px; color: var(--text-muted); }
.tsh-option {
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 64px;
    padding: 0 14px;
    border-radius: var(--radius-dec);
    border: 1px solid var(--border-color);
    background: var(--bg-input);
    color: var(--text-primary);
    font-family: inherit;
    text-align: left;
    cursor: pointer;
}
.tsh-option:disabled { opacity: 0.55; cursor: default; }
.tsh-option-ico {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: var(--radius-dec);
}
.tsh-option-image .tsh-option-ico { background: color-mix(in srgb, var(--accent-odds) 14%, transparent); color: var(--accent-odds); }
.tsh-option-pdf .tsh-option-ico { background: color-mix(in srgb, var(--accent-green) 12%, transparent); color: var(--accent-green); }
.tsh-option-text { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
.tsh-option-title { font-size: 15px; font-weight: 700; }
.tsh-option-sub { font-size: 12px; color: var(--text-muted); }
.tsh-option-chev { flex: 0 0 auto; color: var(--text-muted); }
.tsh-error { margin: 0; font-size: 12px; color: var(--accent-red-soft); }
.tsh-error[hidden] { display: none; }
.tsh-privacy { display: flex; align-items: center; gap: 8px; margin: 0; font-size: 12px; color: var(--text-muted); }
.tsh-privacy svg { flex: 0 0 auto; }


/* =====================================================================
   CENTRED PAGE (2026-10-08) — the page is at most --page-max wide and sits in
   the middle; a wider screen gets even margins on both sides. The teal bar
   keeps the full width, its contents follow the page. The docked rail, the
   slip bar, the chat button and the slip sheet are position:fixed, so each
   takes the same gutter: for a fixed box `%` is the viewport WITHOUT the
   scrollbar, which is exactly the width the in-flow page is centred in, so
   the two line up to the pixel. Below the cap the gutter is 0 and nothing
   changes, hence the media query.
   ===================================================================== */
:root { --page-max: 1500px; }

@media (min-width: 1500px) {
    .main-layout {
        max-width: var(--page-max);
        margin-left: auto;
        margin-right: auto;
    }
    .top-header {
        padding-left:  calc(max(0px, (100% - var(--page-max)) / 2) + 4px);
        padding-right: calc(max(0px, (100% - var(--page-max)) / 2) + 8px);
    }
    .sidebar,
    .sidebar.open { left: max(0px, calc((100% - var(--page-max)) / 2)); }
    .bs-dock,
    .verify-banner {
        left:  calc(max(0px, (100% - var(--page-max)) / 2) + var(--rail-w));
        right: max(0px, calc((100% - var(--page-max)) / 2));
    }
    #chat-root,
    body:has(.betslip-panel.open) #chat-root,
    body:has(#bs-dock:not([hidden])) #chat-root {
        left: calc(max(0px, (100% - var(--page-max)) / 2) + var(--rail-w) + 12px);
    }
    /* The user menu docks to the page's right edge, not the screen's; the search
       row under the bar keeps its field inside the page too. */
    .top-header .user-dropdown { right: calc(max(0px, (100% - var(--page-max)) / 2) + 8px); }
    .top-header .header-center {
        padding-left:  calc(max(0px, (100% - var(--page-max)) / 2) + 12px);
        padding-right: calc(max(0px, (100% - var(--page-max)) / 2) + 12px);
    }
    /* The slip sheet opens over the page area (rail to right edge), like its bar. */
    .betslip-overlay {
        padding-left:  calc(max(0px, (100% - var(--page-max)) / 2) + var(--rail-w));
        padding-right: max(0px, calc((100% - var(--page-max)) / 2));
    }
}

/* The desktop's live match page: the slip's bar and its open sheet as wide as the markets column
   (App._alignSlip measures it), not the whole page area across the markets and the pitch rail. */
@media (min-width: 981px) {
    html.slip-column .bs-dock { left: var(--slip-left); right: var(--slip-right); }
    html.slip-column .betslip-overlay { padding-left: var(--slip-left); padding-right: var(--slip-right); }
}


/* =====================================================================
   MANAGEMENT — CREATE ACCOUNT (2026-10-08). The BetsoftWebClient create
   dialog, on the in-app confirm's card (.mg-confirm). Prefix mgc-.
   ===================================================================== */
.mg-create-btn {
    display: inline-flex; align-items: center; gap: 6px;
    padding: 9px 14px; border-radius: 0; cursor: pointer;
    border: 1px solid var(--accent-green); font: inherit; font-size: 13px; font-weight: 700;
    background: color-mix(in srgb, var(--accent-green) 18%, transparent); color: var(--accent-green);
}
.mg-create-btn svg { width: 14px; height: 14px; flex: 0 0 auto; }
.mg-create-btn:hover { background: color-mix(in srgb, var(--accent-green) 28%, transparent); }
.mg-create-btn:focus-visible { outline: 2px solid var(--text-primary); outline-offset: 2px; }
.mgp-create { width: 100%; }

.mgc { width: min(440px, 100%); max-height: calc(100dvh - 40px); overflow-y: auto;
    display: flex; flex-direction: column; gap: 14px; }
.mgc-head { display: flex; flex-direction: column; gap: 4px; }
.mgc-title { font-size: 16px; font-weight: 700; color: var(--text-primary); }
.mgc-under { font-size: 12px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mgc-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.mgc-field[hidden] { display: none; }
.mgc-input { width: 100%; flex: 1 1 auto; }
.mgc-input:disabled { opacity: 1; color: var(--text-secondary); }
.mgc-pwd { display: flex; gap: 6px; }
.mgc-show {
    flex: 0 0 auto; padding: 0 12px; border-radius: 0; cursor: pointer;
    border: 1px solid var(--border-color); background: var(--bg-tertiary);
    color: var(--text-secondary); font: inherit; font-size: 12px; font-weight: 600;
}
.mgc-show:hover { background: var(--bg-hover); color: var(--text-primary); }
.mgc-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.mgc-chip { position: relative; cursor: pointer; }
.mgc-chip input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.mgc-chip span {
    display: inline-block; padding: 6px 10px; border-radius: 0;
    border: 1px solid var(--border-color); background: var(--bg-input);
    color: var(--text-secondary); font-size: 12px; font-weight: 700; letter-spacing: .03em;
}
.mgc-chip input:checked + span {
    border-color: var(--accent-green); color: var(--accent-green);
    background: color-mix(in srgb, var(--accent-green) 14%, transparent);
}
.mgc-chip input:focus-visible + span { outline: 2px solid var(--text-primary); outline-offset: 1px; }
.mgc-pct { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; }
.mgc-pct-cell { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.mgc-note, .mgc-error { font-size: 12px; line-height: 1.45; padding: 8px 10px; border-radius: 0; }
.mgc-note { color: var(--text-secondary); background: var(--bg-tertiary); border-left: 3px solid var(--accent-green); }
.mgc-note[hidden], .mgc-error[hidden] { display: none; }
.mgc-error {
    color: var(--text-primary); border-left: 3px solid var(--accent-red);
    background: color-mix(in srgb, var(--accent-red) 16%, transparent);
}
.mgc .mg-confirm-actions { margin-top: 2px; }
/* ==========================================================================
   Management → Overview (#MG#OVR) — js/management/mgoverview.js
   Built on the #OD dashboard vocabulary (dash-kpi, dash-panel) with one change:
   cards and panels sit on --bg-card instead of --bg-tertiary, because the soft
   red of a negative difference and the orange of a cash-out need the darker
   ground to stay readable. Colours that have no token of their own (the card
   accents, the chart's played/won bars) come through the existing dash-kpi--*
   classes, which only set --dash-accent.
   ========================================================================== */
.mgov { display: flex; flex-direction: column; gap: 18px; margin-top: 14px; }
.mgov .dash-kpi, .mgov .dash-panel { background: var(--bg-card); }
.mgov .dash-panel { margin: 0; display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.mgov .dash-kpis { margin: 0; }
.mgov .dash-pos  { color: var(--accent-green); }
.mgov .dash-neg  { color: var(--accent-red-soft); }
.mgov .dash-zero { color: var(--text-muted); }
.mgov-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(440px, 100%), 1fr)); gap: 18px; }

.mgov-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 16px; }
.mgov-title { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; min-width: 0; }
.mgov-title h2 { margin: 0; font-size: 18px; font-weight: 700; color: var(--text-primary); }
.mgov-title-sm { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.mgov-note { font-size: 12px; color: var(--text-muted); }
.mgov-updated { display: flex; align-items: center; gap: 10px; font-size: 12px; color: var(--text-muted); }
.mgov-icon-btn {
    width: 44px; height: 44px; display: grid; place-items: center; padding: 0;
    border: 1px solid var(--border-color); border-radius: var(--radius-md);
    background: transparent; color: var(--text-secondary); cursor: pointer;
}
.mgov-icon-btn:hover { background: var(--bg-hover); color: var(--text-primary); }
.mgov-btn {
    min-height: 44px; padding: 0 16px; border: 1px solid var(--border-color); border-radius: var(--radius-md);
    background: transparent; color: var(--text-primary); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.mgov-btn:hover { background: var(--bg-hover); }
.mgov-icon-btn:focus-visible, .mgov-btn:focus-visible, .mgov-tab:focus-visible, .mgov-alert:focus-visible {
    outline: 2px solid var(--accent-green); outline-offset: 2px;
}

.mgov-sec { display: flex; flex-direction: column; gap: 10px; }
.mgov-sec-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px 12px; }
.mgov-sec-head.is-tabs { align-items: center; gap: 8px 12px; }
.mgov-h {
    margin: 0; font-size: 13px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
    color: var(--text-primary);
}

/* --- needs attention (a point in time, not the period) ------------------ */
.mgov-alerts { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); gap: 10px; }
.mgov-alert {
    --mgov-tone: var(--amber);
    display: flex; align-items: center; gap: 12px; min-height: 64px; padding: 12px 14px;
    border: 1px solid color-mix(in srgb, var(--mgov-tone) 42%, transparent); border-radius: var(--radius-lg);
    background: var(--bg-card); color: var(--text-primary); font: inherit; text-align: left; cursor: pointer;
}
.mgov-alert.is-bad { --mgov-tone: var(--accent-red-soft); }
.mgov-alert:hover { background: var(--bg-hover); }
.mgov-alert-ico {
    flex: 0 0 auto; width: 32px; height: 32px; display: grid; place-items: center; border-radius: var(--radius-md);
    color: var(--mgov-tone); background: color-mix(in srgb, var(--mgov-tone) 14%, transparent);
}
.mgov-alert-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.mgov-alert-text b { font-size: 14px; font-weight: 700; }
.mgov-alert-text span { font-size: 12px; color: var(--text-muted); }
.mgov-alert-go { flex: 0 0 auto; display: flex; color: var(--text-muted); }
.mgov-calm {
    margin: 0; display: flex; align-items: center; gap: 8px; padding: 12px 14px;
    border: 1px solid var(--border-color); border-radius: var(--radius-lg);
    background: var(--bg-card); font-size: 13px; color: var(--text-secondary);
}
.mgov-calm svg { color: var(--accent-green); }

/* --- headline cards ------------------------------------------------------ */
.mgov-kpi-value {
    display: flex; align-items: baseline; gap: 5px;
    font-size: 17px; font-weight: 800; line-height: 1.1; color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}
.mgov-kpi-unit { font-size: 12px; font-weight: 600; color: var(--text-muted); }
.mgov-kpi-lead { color: var(--text-primary); }
.mgov-kpi--open { --dash-accent: var(--accent-blue-ligth); }

/* --- played and won, by hour or day -------------------------------------- */
.mgov-legend { display: flex; flex-wrap: wrap; gap: 8px 20px; font-size: 12px; color: var(--text-secondary); }
.mgov-key { display: flex; align-items: center; gap: 8px; }
.mgov-key i { width: 10px; height: 10px; border-radius: var(--radius-sm); background: var(--dash-accent); }
.mgov-key b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.mgov-chart { display: grid; grid-template-columns: 48px minmax(0, 1fr); gap: 8px; }
.mgov-yaxis {
    height: 140px; display: flex; flex-direction: column; justify-content: space-between; align-items: flex-end;
    font-size: 10.5px; line-height: 1; color: var(--text-muted); font-variant-numeric: tabular-nums;
}
.mgov-plot { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.mgov-bars {
    position: relative; height: 140px; display: flex; align-items: flex-end; gap: 4px;
    border-top: 1px dashed var(--border-color); border-bottom: 1px solid var(--border-color);
}
.mgov-bars::before { content: ""; position: absolute; left: 0; right: 0; top: 50%; border-top: 1px dashed var(--border-color); }
.mgov-slot { position: relative; flex: 1 1 0; min-width: 0; height: 100%; display: flex; align-items: flex-end; justify-content: center; gap: 2px; }
.mgov-slot i { flex: 0 1 18px; min-width: 2px; background: var(--dash-accent); border-radius: var(--radius-sm) var(--radius-sm) 0 0; }
.mgov-xaxis { display: flex; gap: 4px; }
.mgov-xaxis span { flex: 1 1 0; min-width: 0; text-align: center; font-size: 10.5px; color: var(--text-muted); white-space: nowrap; }

/* --- stat tiles, stacked bars and rows ------------------------------------ */
.mgov-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(92px, 100%), 1fr)); gap: 8px; }
.mgov-stat {
    min-width: 0; display: flex; flex-direction: column; gap: 2px; padding: 10px 12px;
    background: var(--bg-primary); border-radius: var(--radius-dec);
}
.mgov-stat b { font-size: 20px; font-weight: 800; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.mgov-stat b.mgov-t-open  { color: var(--accent-blue-ligth); }
.mgov-stat b.mgov-t-live  { color: var(--accent-red-soft); }
.mgov-stat b.mgov-t-mixed { color: var(--dash-accent); }
.mgov-lbl { font-size: 10.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--text-muted); }
.mgov-stack {
    display: flex; gap: 2px; height: 12px; overflow: hidden;
    border-radius: var(--radius-lg25); background: var(--bg-tertiary);
}
.mgov-stack i { flex: 0 0 auto; min-width: 3px; height: 100%; }
.mgov-c-won   { background: var(--accent-green); }
.mgov-c-co    { background: var(--accent-orange); }
.mgov-c-lost  { background: var(--accent-red-soft); }
.mgov-c-canc  { background: var(--text-muted); }
.mgov-c-open  { background: var(--accent-blue-ligth); }
.mgov-c-pre   { background: var(--text-secondary); }
.mgov-c-live  { background: var(--accent-red); }
.mgov-c-mixed { background: var(--dash-accent); }
.mgov-dot { flex: 0 0 auto; display: inline-block; width: 10px; height: 10px; border-radius: var(--radius-sm); }
.mgov-rows { display: flex; flex-direction: column; }
.mgov-srow {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 12px;
    padding: 10px 0; border-top: 1px solid var(--border-color);
}
.mgov-srow-main {
    flex: 0 1 210px; min-width: 0; display: grid; grid-template-columns: 10px minmax(0, 1fr);
    column-gap: 10px; row-gap: 2px; align-items: center;
}
.mgov-srow-label { display: flex; justify-content: space-between; gap: 8px; font-size: 13px; color: var(--text-primary); }
.mgov-srow-label b { font-variant-numeric: tabular-nums; }
.mgov-srow-kinds { grid-column: 2; font-size: 11.5px; color: var(--text-muted); }
.mgov-srow-money { margin-left: auto; font-size: 12px; color: var(--text-secondary); text-align: right; font-variant-numeric: tabular-nums; }
.mgov-krow { display: flex; flex-direction: column; gap: 8px; padding: 12px 0; border-top: 1px solid var(--border-color); }
.mgov-krow-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 13px; font-weight: 600; color: var(--text-primary); }
.mgov-krow-head > span:first-child { display: flex; align-items: center; gap: 8px; }
.mgov-cells { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(110px, 100%), 1fr)); gap: 8px 12px; }
.mgov-cell { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mgov-cell b { font-size: 14px; font-weight: 700; color: var(--text-primary); font-variant-numeric: tabular-nums; }

/* --- list rows: matches, accounts, requests, transfers -------------------- */
.mgov-mrow { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; padding: 11px 0; border-top: 1px solid var(--border-color); }
.mgov-mrow.mgov-colhead {
    padding: 0 0 8px; border-top: 0; align-items: flex-end;
    font-size: 10.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--text-muted);
}
.mgov-mrow-main { flex: 1 1 220px; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.mgov-mrow-name { min-width: 0; display: flex; align-items: center; gap: 8px; }
.mgov-mrow-title { font-size: 14px; font-weight: 600; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mgov-mrow-title small { font-size: 12px; font-weight: 500; color: var(--text-muted); }
.mgov-mrow-sub { font-size: 12px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mgov-nums {
    flex: 0 0 auto; margin-left: auto; display: flex; gap: 12px;
    font-size: 14px; font-weight: 700; color: var(--text-primary); font-variant-numeric: tabular-nums;
}
.mgov-colhead .mgov-nums { font-size: inherit; font-weight: inherit; color: inherit; }
.mgov-n1 { width: 60px; text-align: right; }
.mgov-n2 { width: 96px; text-align: right; }
.mgov-n3 { width: 112px; text-align: right; }
.mgov-n3.is-none { color: var(--text-muted); }
.mgov-n4 { width: 92px; text-align: right; }
.mgov-link {
    min-width: 0; padding: 0; border: 0; background: none; color: var(--accent-green);
    font: inherit; font-size: 14px; font-weight: 600; text-align: left;
    text-decoration: underline; text-underline-offset: 3px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer;
}
.mgov-link:focus-visible { outline: 2px solid var(--accent-green); outline-offset: 2px; border-radius: var(--radius-sm); }
.mgov-badge {
    flex: 0 0 auto; display: inline-flex; align-items: center; gap: 5px; padding: 2px 7px;
    border-radius: var(--radius-lg25); background: color-mix(in srgb, var(--text-primary) 6%, transparent);
    color: var(--text-secondary); font-size: 10px; font-weight: 700; letter-spacing: .05em;
}
.mgov-badge.is-live { background: color-mix(in srgb, var(--accent-red) 16%, transparent); color: var(--accent-red-soft); }
.mgov-badge.is-live i { width: 6px; height: 6px; border-radius: var(--radius-lg25); background: var(--accent-red); }
.mgov-badge.is-sm { padding: 1px 6px; font-size: 9.5px; }
.mgov-foot { margin: 0; font-size: 12px; line-height: 1.4; color: var(--text-muted); }
.mgov-empty { margin: 0; padding: 14px 0; font-size: 13px; color: var(--text-muted); text-align: center; }

.mgov-bars-list { display: flex; flex-direction: column; gap: 14px; }
.mgov-bar { display: flex; flex-direction: column; gap: 6px; }
.mgov-bar-top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; font-size: 13px; color: var(--text-primary); }
.mgov-bar-name { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mgov-bar-name small { margin-left: 8px; font-size: 10.5px; font-weight: 700; letter-spacing: .05em; color: var(--text-muted); }
.mgov-bar-val { flex: 0 0 auto; white-space: nowrap; font-variant-numeric: tabular-nums; }
.mgov-bar-val b { font-weight: 700; }
.mgov-bar-val small { font-size: 11px; color: var(--text-muted); }
.mgov-track { height: 6px; overflow: hidden; border-radius: var(--radius-lg25); background: var(--bg-tertiary); }
.mgov-track i { display: block; height: 100%; border-radius: var(--radius-lg25); background: var(--accent-green); }

.mgov-tabs { display: flex; gap: 4px; padding: 3px; background: var(--bg-input); border-radius: var(--radius-dec); }
.mgov-tab {
    min-height: 36px; padding: 0 12px; border: 0; border-radius: var(--radius-md);
    background: transparent; color: var(--text-muted); font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
}
.mgov-tab.is-on { background: var(--bg-tertiary); color: var(--text-primary); }
.mgov-tab:not(.is-on):hover { color: var(--text-primary); }

.mgov-arow { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 0; border-top: 1px solid var(--border-color); }
.mgov-arow > div:first-child { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.mgov-arow-sub { font-size: 12px; color: var(--text-secondary); }
.mgov-arow-val { flex: 0 0 auto; display: flex; align-items: baseline; gap: 6px; }
.mgov-arow-val b { font-size: 22px; font-weight: 800; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.mgov-arow-val span { font-size: 12px; font-weight: 600; color: var(--text-muted); }

.mgov-req-right {
    flex: 0 0 auto; margin-left: auto; display: grid; grid-template-columns: auto auto;
    grid-template-areas: "amt pill" "amt when"; align-items: center; justify-items: end; gap: 3px 12px;
}
.mgov-req-amt { grid-area: amt; font-size: 14px; font-weight: 700; color: var(--text-primary); font-variant-numeric: tabular-nums; white-space: nowrap; }
.mgov-mrow > .mgov-req-amt { margin-left: auto; }
.mgov-req-right .mgov-pill { grid-area: pill; }
.mgov-req-when { grid-area: when; font-size: 11.5px; color: var(--text-muted); white-space: nowrap; }
.mgov-pill {
    --mgov-tone: var(--text-muted);
    display: inline-flex; padding: 2px 9px; border-radius: var(--radius-lg25); white-space: nowrap;
    font-size: 10.5px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
    color: var(--mgov-tone); background: color-mix(in srgb, var(--mgov-tone) 14%, transparent);
}
.mgov-pill.is-won       { --mgov-tone: var(--accent-green); }
.mgov-pill.is-lost      { --mgov-tone: var(--accent-red-soft); }
.mgov-pill.is-open      { --mgov-tone: var(--accent-blue-ligth); }
.mgov-pill.is-co        { --mgov-tone: var(--accent-orange); }
.mgov-pill.is-warn      { --mgov-tone: var(--amber); }
.mgov-pill.is-cancelled { --mgov-tone: var(--text-muted); }

/* --- the match's tickets (management modal shell) -------------------------- */
.mga.mgov-mt { width: min(920px, 100%); }
.mgov-mt-stats { margin-bottom: 10px; }
.mgov-mt-words { margin: 0 0 6px; }
.mgov-trows { display: flex; flex-direction: column; }
.mgov-trow { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 14px; padding: 12px 0; border-bottom: 1px solid var(--border-subtle); }
.mgov-trow-id { flex: 0 0 116px; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mgov-trow-id .mgov-link { align-self: flex-start; font-weight: 700; }
.mgov-trow-pick { flex: 1 1 220px; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.mgov-trow-pickline { min-width: 0; display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--text-primary); }
.mgov-trow-pickline b { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mgov-trow-nums {
    flex: 0 0 auto; margin-left: auto; display: flex; align-items: center; gap: 14px;
    font-size: 14px; font-weight: 700; color: var(--text-primary); font-variant-numeric: tabular-nums;
}
.mgov-trow-nums .mgov-n2 { width: 80px; }
.mgov-odds { width: 44px; text-align: right; color: var(--accent-odds); }
.mgov-trow-st { width: 116px; display: flex; flex-direction: column; align-items: flex-end; gap: 3px; }
.mgov-trow-st small { font-size: 12px; font-weight: 500; color: var(--text-secondary); }
.mgov-mt-foot { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px; padding-top: 14px; }

/* --- skeleton: the page's own shape while vibast_mg_overview works --------- */
.mgov-skeleton { display: flex; flex-direction: column; gap: 18px; }
.mgov-skel {
    border-radius: var(--radius-lg);
    background: linear-gradient(90deg, var(--bg-secondary) 25%, var(--bg-hover) 37%, var(--bg-secondary) 63%);
    background-size: 400% 100%;
    animation: mg-shimmer 1.4s ease infinite;
}
.mgov-skel-title { width: min(320px, 70%); height: 24px; border-radius: var(--radius-md); }
.mgov-skel-alert { height: 64px; }
.mgov-skel-kpi   { height: 120px; }
.mgov-skel-chart { height: 270px; }
.mgov-skel-panel {
    display: flex; flex-direction: column; gap: 12px; min-height: 220px; padding: 16px;
    border: 1px solid var(--border-color); border-radius: var(--radius-lg); background: var(--bg-card);
}
.mgov-skel-panel .mgov-skel { background-image: linear-gradient(90deg, var(--bg-primary) 25%, var(--bg-tertiary) 37%, var(--bg-primary) 63%); }
.mgov-skel-h   { width: 40%; height: 14px; border-radius: var(--radius-sm); }
.mgov-skel-row { height: 30px; border-radius: var(--radius-md); }
.mgov-sr { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
@media (prefers-reduced-motion: reduce) {
    .mgov-skel { animation: none; }
}

/* Live match side panel: a horizontal swipe moves between its tabs (live.js
   _wireMdSwipe), so the browser keeps only vertical panning (and pinch zoom) here,
   and the sliding pages are clipped without making the panel a scroll container. */
.live-md-side { touch-action: pan-y pinch-zoom; overflow-x: clip; }

/* Three-way rows (1 · X · 2): the middle selection sits in the MIDDLE — its label and
   price centred together, so the row reads symmetrically ("X" or "Barazim" used to
   cling to the left with its price on the far right). The outer two keep label left,
   price right. Rows that stack one per line (team markets under 600px outside the
   live page) are left as they are. */
:is(#page-live-match, #page-match-detail) .md-market-odds > .md-odd-btn:nth-child(2):nth-last-child(2),
.md-market-odds:not(.md-team-rows) > .md-odd-btn:nth-child(2):nth-last-child(2) {
    justify-content: center;
}
:is(#page-live-match, #page-match-detail) .md-market-odds > .md-odd-btn:nth-child(2):nth-last-child(2) .md-odd-label,
.md-market-odds:not(.md-team-rows) > .md-odd-btn:nth-child(2):nth-last-child(2) .md-odd-label {
    flex: 0 1 auto;
}
@media (min-width: 601px) {
    .md-market-odds.md-team-rows > .md-odd-btn:nth-child(2):nth-last-child(2) { justify-content: center; }
    .md-market-odds.md-team-rows > .md-odd-btn:nth-child(2):nth-last-child(2) .md-odd-label { flex: 0 1 auto; }
}

/* The slip sheet's header line opens / closes it (App.initBetslipFab); the × clears it. */
.betslip-overlay-header { cursor: pointer; }

/* "Ruaj" (remember the stake) inside the stake box, right of the amount: the label
   over the switch so it fits half the footer bar. The box is a column (label over
   amount), so the toggle is placed against its right edge. */
.bs-foot .bs-stake-input-wrap { position: relative; padding-right: 54px; }
.bs-foot .bs-stake-input-wrap .bs-remember-toggle {
    position: absolute;
    top: 50%;
    right: 10px;
    transform: translateY(-50%);
    margin: 0;
    flex-direction: column;
    gap: 3px;
    cursor: pointer;
}
.bs-foot .bs-stake-input-wrap .bs-remember-label { font-size: 9.5px; line-height: 1; }
.bs-foot .bs-stake-input-wrap .bs-toggle-pill { display: block; }   /* a span now: valid inside <label> */
/* With the keypad open the keypad carries its own remember switch (rule above hides
   this one), so the box gets its padding back. */
body.bs-keyboard-open .betslip-overlay-body .bs-foot .bs-stake-input-wrap { padding-right: 11px; }
/* Open lost / cancelled ticket: what it could have won, read as information, not as money paid. */
.mybets-legs-val.mybets-legs-val-muted { color: var(--text-muted); }
/* Waiting for the bet to be accepted: the Place half stays the brand green (it is
   disabled while waiting, and the grey `.bs-foot .bs-place-btn:disabled` rule above
   used to win), with the spinner beside "Duke pritur…" in the ink of the button. */
.bs-foot .bs-place-btn.bs-placing,
.bs-foot .bs-place-btn.bs-placing:disabled,
body.bs-keyboard-open .betslip-overlay-body .bs-foot .bs-place-btn.bs-placing {
    flex-direction: row;
    gap: 10px;
    background: var(--accent-green);
    color: var(--bg-deep);
    opacity: 1;
    height: 50px;
}
.bs-foot .bs-place-btn.bs-placing .bs-btn-spinner {
    width: 20px;
    height: 20px;
    margin: 0;
    border-width: 3px;
    border-color: color-mix(in srgb, var(--bg-deep) 25%, transparent);
    border-top-color: var(--bg-deep);
}

/* User finance (#FI#), the legacy board's layout: per product a section bar, then
   Info · Xhiro · Fitimi · Diferenca in one row, then Totali. The layout is the
   legacy one; the colours are this site's own surfaces. */
.fin-sec { margin-bottom: 10px; }
.fin-sec-head {
    margin: 0;
    padding: 12px 10px;
    background: var(--header-bg);
    color: var(--text-primary);
    font-size: 15px;
    font-weight: 700;
}
.fin-tbl { width: 100%; border-collapse: collapse; font-size: 12px; font-variant-numeric: tabular-nums; }
.fin-tbl th, .fin-tbl td { padding: 9px 10px; text-align: left; white-space: nowrap; }
.fin-tbl .fin-num { text-align: right; }
.fin-tbl thead th {
    background: var(--bg-secondary);
    color: var(--text-muted);
    font-size: 11px;
    font-weight: 600;
    border-bottom: 1px solid var(--border-color);
}
.fin-tbl tr.fin-row td {
    background: var(--bg-primary);
    color: var(--text-secondary);
    border-bottom: 1px solid var(--border-color);
}
.fin-tbl tr.fin-total td {
    background: var(--bg-tertiary);
    color: var(--text-primary);
    font-weight: 700;
}
.fin-tbl .fin-cur { font-size: 11px; }
/* Overview › ranking by domain: the management table, the domain with its player
   count under it; the last cell (Difference) keeps to one line like the others. */
.mgov-dom-tbl td:last-child { white-space: nowrap; min-width: 0; }
.mgov-dom-sub { display: block; margin-top: 1px; font-size: 11px; color: var(--text-muted); }

/* =====================================================================
   Search page (#Q#) and its results (.sr-*, .srx-*) — ported from gli-33.
   ===================================================================== */
/* Visually hidden but available to screen readers (skip-link target, the
 * landing <h1>, etc.). */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
/* =================================================================
   Search page (#Q#) — the bottom-nav Search.
   ================================================================= */
.sr-page {
    max-width: 760px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding-bottom: 24px;
}
.sr-bar {
    position: sticky;
    top: var(--header-height);
    z-index: 5;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border-radius: var(--radius-lg);
    background: var(--bg-input);
    border: 1.5px solid var(--border-color);
    transition: border-color 0.15s, box-shadow 0.15s;
}
.sr-bar:focus-within {
    border-color: var(--accent-green-neon);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent-green) 10%, transparent);
}
.sr-bar-icon { flex-shrink: 0; color: var(--accent-green-neon); }
#sr-input {
    flex: 1 1 auto;
    min-width: 0;
    height: 36px;
    border: 0;
    background: transparent;
    color: var(--text-primary);
    font: 600 16px var(--font-body);   /* 16px: iOS doesn't zoom the page on focus */
    outline: none;
}
#sr-input::placeholder { color: var(--accent-green-neon); opacity: 0.85; }
#sr-input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; display: none; }
.sr-clear-input {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 0;
    border-radius: 50%;
    background: var(--bg-tertiary);
    color: var(--text-primary);
    cursor: pointer;
    transition: background 0.15s;
}
.sr-clear-input[hidden] { display: none; }
.sr-clear-input:hover { background: var(--bg-lightg); }
.sr-clear-input:focus-visible { outline: 2px solid var(--accent-green-neon); outline-offset: 2px; }
.sr-close {
    flex-shrink: 0;
    height: 36px;
    padding: 0 10px;
    border: 0;
    background: transparent;
    color: var(--accent-green-neon);
    font: 600 14px var(--font-body);
    cursor: pointer;
}
.sr-cats { display: flex; gap: 8px; }
.sr-cat {
    height: 34px;
    padding: 0 14px;
    border-radius: 999px;
    border: 1px solid var(--border-color);
    background: var(--bg-secondary);
    color: var(--text-secondary);
    font: 600 13px var(--font-body);
    cursor: pointer;
}
.sr-cat.active { background: var(--accent-green-neon); border-color: var(--accent-green-neon); color: var(--bg-input); }
.sr-home { display: flex; flex-direction: column; gap: 26px; margin-top: 6px; }
.sr-home[hidden],
.sr-results-wrap[hidden] { display: none; }
.sr-section { display: flex; flex-direction: column; gap: 10px; }
.sr-section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--border-color);
}
.sr-section-head h3 {
    margin: 0;
    font-size: 13px;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--accent-green-neon);
}
.sr-clear {
    border: 0;
    background: transparent;
    color: var(--text-muted);
    font: 600 13px var(--font-body);
    cursor: pointer;
    padding: 4px 0 4px 10px;
}
.sr-empty { margin: 4px 0; font-size: 13px; color: var(--text-muted); }
.sr-head-live { display: flex; align-items: center; gap: 8px; }
.sr-see-all { font-size: 13px; font-weight: 700; color: var(--accent-green-neon); text-decoration: none; }
.sr-see-all:hover { text-decoration: underline; }
/* Recent searches: chips that run the search again, each with its own remove. */
.sr-recent { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.sr-recent-chip {
    display: inline-flex;
    align-items: center;
    height: 38px;
    box-sizing: border-box;
    border-radius: 999px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    transition: border-color 0.15s;
}
.sr-recent-chip:hover { border-color: var(--accent-green-neon); }
.sr-recent-item {
    height: 100%;
    max-width: 220px;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 0 4px 0 12px;
    border: 0;
    background: transparent;
    color: var(--text-primary);
    font: 600 14px var(--font-body);
    cursor: pointer;
}
.sr-recent-item svg { flex-shrink: 0; color: var(--text-muted); }
.sr-recent-item span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sr-recent-del {
    width: 26px;
    height: 26px;
    margin-right: 6px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    border: 0;
    border-radius: 50%;
    background: var(--bg-input);
    color: var(--text-muted);
    cursor: pointer;
}
.sr-recent-del:hover { color: var(--text-primary); background: var(--bg-tertiary); }
.sr-recent-item:focus-visible,
.sr-recent-del:focus-visible { outline: 2px solid var(--accent-green-neon); outline-offset: 2px; border-radius: 999px; }
/* Live now: clock column, both teams with kit + score, chevron. */
.sr-live {
    list-style: none;
    margin: 0;
    padding: 0;
    border-radius: 14px;
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    overflow: hidden;
}
.sr-live li + li { border-top: 1px solid var(--border-subtle); }
.sr-live-item {
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr) 16px;
    column-gap: 10px;
    align-items: center;
    padding: 11px 14px;
    color: var(--text-primary);
    text-decoration: none;
    transition: background 0.15s;
}
.sr-live-item:hover { background: var(--live-row-hover); }
.sr-live-item > svg { color: var(--bg-lightg); }
.sr-live-when { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; }
.sr-live-when img { width: 16px; height: 16px; }
.sr-live-min {
    font-size: 12px;
    font-weight: 800;
    color: var(--accent-green-neon);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.sr-live-teams { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
/* Popular leagues: two-column tiles. */
.sr-leagues { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.sr-league {
    min-height: 56px;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 12px 8px 10px;
    border-radius: var(--radius-lg);
    background: var(--bg-secondary);
    border: 1px solid var(--border-color);
    color: var(--text-primary);
    text-decoration: none;
    transition: border-color 0.15s;
}
.sr-league:hover { border-color: var(--accent-green-neon); }
.sr-league-flag {
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 9px;
    background: var(--bg-input);
}
.sr-league-flag img, .sr-league-flag svg { width: 20px; height: 20px; object-fit: contain; }
.sr-league-txt { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.sr-league-name { font-size: 13px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sr-league-country { font-size: 11px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sr-results { display: flex; flex-direction: column; padding: 0; overflow: visible; }
/* =================================================================
   Sports search results (.srx) — header dropdown, Browse search, #Q#.
   One renderer (App._renderSportsResults). A row is its meta line (sport,
   time or clock, league), both teams with the kit on the name's own line,
   and 1 X 2 on the right. Live matches are cards on a phone — prices under
   the teams, labelled — and ordinary rows once the results are wide enough
   (container query), where the section heading carries the 1 X 2 labels.
   ================================================================= */
.srx {
    container: srx / inline-size;
    --srx-card: var(--bg-secondary);
    --srx-odd-w: 52px;
    --srx-odds-w: 164px;   /* 3 × --srx-odd-w + 2 × 4px gap */
    --srx-pad: 12px;
    display: flex;
    flex-direction: column;
    gap: 18px;
    padding: 6px 0 4px;
}
.browse-search-dropdown .srx { --srx-card: var(--bg-primary); }
.srx-sec { display: flex; flex-direction: column; gap: 8px; }
.srx-head {
    margin: 0;
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-primary);
}
.srx-head-n { font-weight: 700; letter-spacing: 0; color: var(--text-muted); }
.srx-live-dot {
    width: 8px;
    height: 8px;
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--accent-red);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent-red) 22%, transparent);
}
.srx-hit {
    color: var(--accent-green-neon);
    background: color-mix(in srgb, var(--accent-green) 16%, transparent);
    border-radius: 3px;
    padding: 0 1px;
}
/* Sport filter chips */
.srx-chips {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    scrollbar-width: none;
    padding: 2px 0;
    margin-bottom: -4px;
}
.srx-chips::-webkit-scrollbar { display: none; }
.srx-chip {
    flex-shrink: 0;
    height: 36px;
    box-sizing: border-box;
    padding: 0 8px 0 14px;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    border-radius: 999px;
    border: 1px solid var(--border-color);
    background: var(--bg-secondary);
    color: var(--text-primary);
    font: 700 13px var(--font-body);
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s;
}
.srx-chip.has-ico { padding-left: 5px; }
.srx-chip:hover { border-color: var(--accent-green-neon); }
.srx-chip:focus-visible { outline: 2px solid var(--accent-green-neon); outline-offset: 2px; }
.srx-chip.is-on { background: var(--accent-green-neon); border-color: var(--accent-green-neon); color: var(--bg-input); }
.srx-chip-ico {
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--bg-input);
}
.srx-chip-ico img { width: 17px; height: 17px; }
.srx-count {
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    box-sizing: border-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: var(--bg-tertiary);
    color: var(--text-secondary);
    font-size: 11px;
    font-weight: 800;
}
.srx-chip.is-on .srx-count { background: var(--bg-input); color: var(--accent-green-neon); }
/* Leagues that matched */
.srx-leagues { display: flex; gap: 8px; overflow-x: auto; scrollbar-width: none; }
.srx-leagues::-webkit-scrollbar { display: none; }
.srx-league {
    flex-shrink: 0;
    height: 52px;
    box-sizing: border-box;
    padding: 0 14px 0 10px;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    border-radius: var(--radius-lg);
    background: var(--srx-card);
    border: 1px solid var(--border-color);
    color: var(--text-primary);
    text-decoration: none;
    transition: border-color 0.15s;
}
.srx-league:hover { border-color: var(--accent-green-neon); }
.srx-league-ico {
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 9px;
    background: var(--bg-input);
}
.srx-league-ico img { width: 20px; height: 20px; }
.srx-league-txt { display: flex; flex-direction: column; gap: 1px; }
.srx-league-name { font-size: 13px; font-weight: 700; white-space: nowrap; }
.srx-league-country { font-size: 11px; color: var(--text-muted); white-space: nowrap; }
/* Day heading; its 1 X 2 labels sit over the price column. */
.srx-day {
    display: grid;
    grid-template-columns: minmax(0, 1fr) var(--srx-odds-w);
    column-gap: 10px;
    align-items: center;
    padding: 6px calc(var(--srx-pad) + 1px) 0 2px;
}
.srx-day-live { padding-top: 0; }
.srx-day-label { min-width: 0; font-size: 13px; font-weight: 700; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.srx-day-label span { font-weight: 600; color: var(--text-muted); }
.srx-odds-head {
    display: grid;
    grid-template-columns: repeat(3, var(--srx-odd-w));
    gap: 4px;
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
    text-align: center;
}
.srx-day-live .srx-odds-head { visibility: hidden; }
/* Rows */
.srx-group {
    border-radius: 14px;
    background: var(--srx-card);
    border: 1px solid var(--border-color);
    overflow: hidden;
}
.srx-row {
    display: grid;
    grid-template-columns: minmax(0, 1fr) var(--srx-odds-w);
    column-gap: 10px;
    align-items: center;
    padding: 10px var(--srx-pad) 11px;
    transition: background 0.15s;
}
.srx-group .srx-row + .srx-row { border-top: 1px solid var(--border-subtle); }
.srx-group .srx-row:hover { background: var(--live-row-hover); }
.srx-link {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
    color: var(--text-primary);
    text-decoration: none;
    border-radius: var(--radius-sm);
}
.srx-link:focus-visible { outline: 2px solid var(--accent-green-neon); outline-offset: 3px; }
.srx-meta {
    display: flex;
    align-items: center;
    gap: 6px;
    min-width: 0;
    font-size: 11px;
    color: var(--text-muted);
}
.srx-sport { width: 14px; height: 14px; flex-shrink: 0; }
.srx-when { flex-shrink: 0; font-weight: 800; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.srx-sport-name { flex-shrink: 0; font-weight: 700; color: var(--text-secondary); }
.srx-sep { flex-shrink: 0; color: var(--bg-lightg); }
.srx-league-line { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.srx-team { display: flex; align-items: center; gap: 9px; min-width: 0; }
.srx-kit {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}
.srx-kit-img { width: 22px; height: 22px; object-fit: contain; }
.srx-mono {
    width: 22px;
    height: 22px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    color: var(--text-primary);
    font-size: 8px;
    font-weight: 800;
    letter-spacing: 0.02em;
}
.srx-mono-0 { background: var(--accent-blue); }
.srx-mono-1 { background: var(--green-soft); }
.srx-mono-2 { background: var(--bg-lightg); }
.srx-mono-3 { background: var(--accent-offer); }
.srx-name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 14px;
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.srx-score {
    flex-shrink: 0;
    min-width: 22px;
    text-align: right;
    font-size: 16px;
    font-weight: 800;
    color: var(--accent-green-neon);
    font-variant-numeric: tabular-nums;
}
.srx-score.is-behind { color: var(--text-muted); }
/* Prices — ordinary [data-koefi] buttons; the betslip adds them and marks .selected. */
.srx-odds {
    display: grid;
    grid-template-columns: repeat(3, var(--srx-odd-w));
    gap: 4px;
}
.srx-odd {
    height: 75px;
    padding: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    border: 1px solid transparent;
    border-radius: var(--radius-md);
    background: var(--bg-input);
    color: var(--text-primary);
    font: 800 14px var(--font-odds);
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    transition: background 0.15s, border-color 0.15s, transform 0.1s;
}
.srx-odd:hover { border-color: var(--accent-green-neon); }
.srx-odd:active { transform: translateY(1px); }
.srx-odd:focus-visible { outline: 2px solid var(--accent-green-neon); outline-offset: 2px; }
.srx-odd.selected { background: var(--accent-green-neon); border-color: var(--accent-green-neon); color: var(--bg-input); }
.srx-odd.disabled { cursor: not-allowed; color: var(--text-muted); }
.srx-odd.disabled:hover { border-color: transparent; }
.srx-odd.is-empty { background: transparent; color: var(--bg-lightg); cursor: default; }
.srx-odd-lbl { display: none; font-size: 12px; font-weight: 700; color: var(--text-muted); }
.srx-odd.selected .srx-odd-lbl { color: var(--bg-input); }
/* Live cards (narrow results) */
.srx-live-list { display: flex; flex-direction: column; gap: 10px; }
.srx-row.is-live {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 12px;
    padding: 12px 14px 14px;
    border-radius: 14px;
    background: linear-gradient(170deg, var(--live-row-hover) 0%, var(--srx-card) 70%);
    border: 1px solid var(--border-color);
}
.srx-row.is-live .srx-link { gap: 8px; }
.srx-row.is-live .srx-meta { font-size: 12px; }
.srx-row.is-live .srx-sport { width: 16px; height: 16px; }
.srx-row.is-live .srx-kit,
.srx-row.is-live .srx-kit-img,
.srx-row.is-live .srx-mono { width: 28px; height: 28px; }
.srx-row.is-live .srx-mono { border-radius: 8px; font-size: 10px; }
.srx-row.is-live .srx-name { font-size: 16px; font-weight: 700; }
.srx-row.is-live .srx-score { font-size: 20px; }
.srx-clock {
    flex-shrink: 0;
    margin-left: auto;
    height: 22px;
    padding: 0 8px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border-radius: 6px;
    background: var(--bg-input);
    color: var(--accent-green-neon);
    font-size: 12px;
    font-weight: 800;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.srx-live-tag {
    padding: 1px 5px;
    border-radius: 3px;
    background: var(--accent-red);
    color: var(--text-primary);
    font-size: 10px;
    letter-spacing: 0.04em;
}
.srx-row.is-live .srx-odds { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.srx-row.is-live .srx-odd {
    height: 44px;
    padding: 0 12px;
    justify-content: space-between;
    border-color: var(--border-color);
    font-size: 15px;
}
.srx-row.is-live .srx-odd:hover { border-color: var(--accent-green-neon); }
.srx-row.is-live .srx-odd-lbl { display: inline; }
.srx-row.is-live .srx-odd.is-empty { visibility: hidden; }
.srx-more {
    height: 44px;
    margin-top: 4px;
    border-radius: var(--radius-lg);
    border: 1px solid var(--border-color);
    background: transparent;
    color: var(--accent-green-neon);
    font: 700 14px var(--font-body);
    cursor: pointer;
    transition: border-color 0.15s;
}
.srx-more:hover { border-color: var(--accent-green-neon); }
@container srx (max-width: 379px) {
    .srx-day, .srx-row { --srx-odd-w: 46px; --srx-odds-w: 146px; }
}
@container srx (min-width: 560px) {
    .srx-row.is-live {
        grid-template-columns: minmax(0, 1fr) var(--srx-odds-w);
        column-gap: 10px;
        padding: 11px var(--srx-pad) 12px;
    }
    .srx-row.is-live .srx-kit,
    .srx-row.is-live .srx-kit-img,
    .srx-row.is-live .srx-mono { width: 24px; height: 24px; }
    .srx-row.is-live .srx-name { font-size: 15px; }
    .srx-row.is-live .srx-score { font-size: 17px; }
    .srx-row.is-live .srx-odds { grid-template-columns: repeat(3, var(--srx-odd-w)); gap: 4px; }
    .srx-row.is-live .srx-odd {
        height: 46px;
        padding: 0;
        justify-content: center;
        border-color: transparent;
        font-size: 14px;
    }
    .srx-row.is-live .srx-odd-lbl { display: none; }
    .srx-row.is-live .srx-odd.is-empty { visibility: visible; }
    .srx-day-live .srx-odds-head { visibility: visible; }
}
#sr-tabs:empty { display: none; }
/* Sport chips in a dropdown's header bar (beside the close button). */
.search-sport-tabs .srx-chips { margin: 0; padding: 0; }


/* =====================================================================
   SKELETONS (2026-10-11) - the page's own shape while its data (and, on a
   phone's live match page, bet365's sheets) are on the way, on the
   management's shimmer (mg-shimmer). js/skeleton.js; each is replaced by
   the first real render of its container.
   ===================================================================== */
.skel {
    display: block;
    border-radius: var(--radius-sm);
    background: linear-gradient(90deg, var(--bg-secondary) 25%, var(--bg-hover) 37%, var(--bg-secondary) 63%);
    background-size: 400% 100%;
    animation: mg-shimmer 1.4s ease infinite;
}
/* On a card's or a row's surface the shimmer runs on the darker base (as .mgov-skel-panel). */
.skel-card .skel,
.skel-market .skel,
.skel-row .skel {
    background-image: linear-gradient(90deg, var(--bg-primary) 25%, var(--bg-tertiary) 37%, var(--bg-primary) 63%);
}
@media (prefers-reduced-motion: reduce) { .skel { animation: none; } }

.skel-line { height: 12px; }
.skel-w30 { width: 30%; } .skel-w38 { width: 38%; } .skel-w45 { width: 45%; }
.skel-w50 { width: 50%; } .skel-w55 { width: 55%; } .skel-w62 { width: 62%; }
.skel-odds { display: flex; gap: 6px; flex: none; }
.skel-odd { width: 58px; height: 38px; }

/* Match rows: the home's live board and upcoming list, the live overview. */
.skel-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    background: var(--bg-secondary);
    border-bottom: 1px solid var(--border-subtle);
}
.skel-teams { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; }
.skel-group { margin-bottom: 10px; }
.skel-group-head { height: 34px; width: 100%; margin-bottom: 2px; }

/* The featured matches' compact cards. */
.skel-cards { display: flex; gap: 10px; overflow: hidden; }
.skel-card {
    flex: 0 0 260px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 12px;
    background: var(--bg-card);
}
.skel-card .skel-odds { margin-top: 4px; }
.skel-card .skel-odd { flex: 1; width: auto; }

/* The live match page: a layer over the page while the match loads (live.js openMatchDetail)
   and, on a phone, until bet365's sheets are in (js/live-mobile.js) - the page lays itself out
   under it as it always does, the pitch module measuring its real box. */
#page-live-match { position: relative; }
#page-live-match > .skel-match { display: none; }
#page-live-match.md-loading > .skel-match,
#page-live-match.lmm-on.lmm-pending > .skel-match {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    min-height: calc(100dvh - var(--header-height));
    z-index: 70;
    background: var(--bg-primary);
}
.skel-match-main { display: flex; flex-direction: column; min-width: 0; }
.skel-matchhead {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    height: 51px;
    padding: 0 12px;
    background: var(--bg-secondary);
}
.skel-matchhead .skel { background-image: linear-gradient(90deg, var(--bg-primary) 25%, var(--bg-tertiary) 37%, var(--bg-primary) 63%); }
.skel-back { width: 22px; height: 22px; flex: none; margin-right: auto; }
.skel-matchhead .skel-line { width: 26%; }
.skel-score { width: 20px; height: 26px; flex: none; }
.skel-pitch { width: 100%; aspect-ratio: 16 / 9; }
.skel-bar {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 18px;
    height: 50px;
    border-bottom: 1px solid var(--border-subtle);
}
.skel-pill { width: 64px; height: 16px; }
.skel-market {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin: 8px 10px 0;
    padding: 12px;
    background: var(--bg-card);
}
.skel-mhead { height: 16px; }
.skel-market .skel-odds .skel-odd { flex: 1; width: auto; }
.skel-match-side { display: none; }
.skel-stat { padding: 12px 16px; }
@media (min-width: 981px) {
    #page-live-match.md-loading > .skel-match {
        display: grid;
        grid-template-columns: minmax(400px, 1fr) minmax(280px, 430px);
        gap: 20px;
        align-items: start;
    }
    .skel-pitch-phone,
    .skel-phone-only { display: none; }
    .skel-match-side { display: flex; flex-direction: column; }
    .skel-market { margin-left: 0; margin-right: 0; }
}
