/* ============================================
   KOTT Public Pages — Minimal Tech Design
   True black + frosted glass + cyan accent
   ============================================ */

/* Wave 6 a11y (2026-05-06) — skip-to-content link.
   Hidden offscreen via left:-9999px (NOT display:none — display:none
   removes the element from the focus order entirely; offscreen-shifting
   keeps it in the keyboard tab path). When focused, slides on-screen at
   the top-left corner with high contrast so the user clearly sees where
   keyboard focus is. */
.skip-to-content {
    position: absolute;
    left: -9999px;
    top: -9999px;
    z-index: 10000;
    background: var(--accent, #00e0ff);
    color: #000;
    padding: 10px 16px;
    font-weight: 700;
    text-decoration: none;
    border-radius: 4px;
}
.skip-to-content:focus {
    left: 8px;
    top: 8px;
    outline: 2px solid #fff;
    outline-offset: 2px;
}

/* ============================================
   Wave 5 sub-theme 5.6 (2026-05-06) — canonical breakpoint scale.
   ============================================
   public.css media queries grew organically (480 / 640 / 720 / 768 /
   820 / 900 / 920 / 1024 / 1200 — 9 distinct breakpoints).
   New rules SHOULD use the four-tier scale below; older rules stay
   put for now (refactoring them all in one pass would touch every
   visual surface — sub-theme 5.6's request was to document the scale
   and start migrating).

     375px — minimum supported phone (small Android, iPhone SE).
     640px — large phone landscape / small tablet portrait.
     900px — tablet landscape; admin sidebar threshold.
     1200px — desktop content-column max-width.

   Four-tier matches the most common resolved breakpoints already in
   use; 720/768/820 collapse to 900, 480 collapses to 375 in the
   migration plan.
   ============================================ */

/* --- Design Tokens ---
   The canonical :root now lives in tokens.css (linked FIRST in App.razor);
   every shared token + the derived scales (and the public-origin tokens
   --bg-card / --accent-purple / --danger-dim / --danger-border / the --text-*
   scale / --home-content-width / --glass-bg / --border-subtle) are inherited
   from there. This sheet keeps ONLY the public surface's intentional
   per-surface overrides, scoped to .public-shell so load order no longer
   decides them.

   These five tokens differ on purpose between public (brighter neon) and
   admin (calmer Tailwind-ish). Before reconciliation admin.css loaded last,
   so admin's values silently won on public pages too (a bug — public's
   bright green/red/amber were never rendering). Pinning per-surface restores
   public's intended palette. Values below are public's existing design set,
   verbatim. */
.public-shell {
    --success: #8aff8a;
    --danger: #ff6b6b;
    --warning: #ffb347;
    --text-tertiary: #8b939f;
    --border-hover: rgba(255, 255, 255, 0.10);
}

/* --- Base panel utility used across public pages --- */
/* 2026-07-08 atmosphere pass — blur radii capped at 8px site-wide (was 12px).
   The fixed .ambient-layer now puts real content behind every frosted panel,
   turning ~20 previously-free backdrop-filter sites into actual GPU work;
   8px keeps the frosted look at roughly half the sampling cost. */
.glass-panel {
    background: var(--bg-panel);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid var(--border);
    border-radius: 5px;
}

/* --- Reset --- */
html, body { margin: 0; padding: 0; border: none; background: #000000; }
.public-shell * { box-sizing: border-box; margin: 0; padding: 0; }
.public-shell { font-family: var(--font-body); background: var(--bg-primary); color: var(--text-primary); font-size: 14px; line-height: 1.6; min-height: 100vh; display: flex; flex-direction: column; }
.public-shell a { color: var(--link); text-decoration: none; transition: color 0.12s ease; }
.public-shell a:hover { color: var(--link-hover); }

/* a11y (2026-06-08) — global keyboard focus ring for interactive controls.
   Keyboard-only (:focus-visible) so mouse clicks don't get a ring; ensures
   every link/button across the public shell shows a visible focus indicator. */
.public-shell a:focus-visible,
.public-shell button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* a11y (2026-06-08) — visually-hidden utility. Standard clip pattern: removes
   the element from visual flow but keeps it in the accessibility tree + focus
   order (unlike display:none), so screen-reader-only labels work. */
.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;
}

/* --- Top Nav — Frosted glass --- */
.topnav { background: rgba(8, 12, 18, 0.85); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 100; }
.topnav-inner { max-width: 1200px; margin: 0 auto; padding: 0 24px; display: flex; align-items: center; gap: 24px; height: 56px; }
.topnav-brand { font-family: var(--font-display); font-size: 20px; font-weight: 700; color: var(--accent) !important; letter-spacing: 3px; text-transform: uppercase; flex-shrink: 0; }
.topnav-brand:hover { color: var(--accent-hover) !important; }
.topnav-links { display: flex; gap: 2px; }
.topnav-links a, .topnav-links a:visited { font-family: var(--font-display); color: var(--text-tertiary); font-size: 13px; font-weight: 600; padding: 8px 14px; border-radius: 4px; transition: all 0.12s ease; text-transform: uppercase; letter-spacing: 0.5px; }
.topnav-links a:hover { color: var(--text-primary); background: var(--bg-hover); }
.topnav-links a.active { color: var(--accent); background: var(--accent-dim); }
/* .topnav-host-cta REMOVED 2026-08-02. "Host a server" spent one iteration as a filled cyan CTA
   inside .topnav-auth (nav "option A"), which put a loud marketing button immediately beside the
   account controls: search field, filled CTA, bare name, outlined Logout — four elements at three
   weights with no grouping, so Logout read as a peer of the primary conversion action. It is a
   plain .topnav-links item between Teams and Help now, and inherits that row's styling. */
.topnav-discord { color: var(--accent) !important; }
.topnav-discord:hover { background: var(--accent-dim) !important; }
.topnav-search { margin-left: auto; position: relative; }
.nav-search-input { background: rgba(255, 255, 255, 0.04); border: 1px solid rgba(255, 255, 255, 0.10); color: var(--text-primary); padding: 6px 14px; border-radius: 4px; font-size: 13px; font-family: var(--font-body); width: 220px; transition: border-color 0.12s ease, width 0.2s ease; }
.nav-search-input:focus { outline: none; border-color: var(--border-accent-strong); width: 280px; box-shadow: 0 0 0 1px var(--border-accent); }
.nav-search-input::placeholder { color: var(--text-muted); }
.search-dropdown { position: absolute; top: 100%; left: 0; right: 0; background: var(--bg-panel-solid);  border: 1px solid var(--border-hover); border-radius: 0 0 4px 4px; overflow-y: auto; z-index: 200; margin-top: 2px; max-height: 300px; }
.search-result { display: block; padding: 8px 14px; font-size: 13px; color: var(--text-primary) !important; transition: background 0.1s; }
.search-result:hover { background: var(--bg-hover); }
.topnav-toggle { display: none; background: none; border: none; color: var(--text-tertiary); font-size: 20px; cursor: pointer; padding: 4px 8px; }
.topnav-mobile { display: none; }

/* --- Announcement Banner --- */
.announcement-banner { padding: 10px 24px; text-align: center; font-size: 14px; font-family: var(--font-display); position: relative; color: #fff; }
.announcement-banner strong { font-weight: 700; }
.announcement-info { background: rgba(0, 224, 255, 0.15); border-bottom: 1px solid rgba(0, 224, 255, 0.3); }
.announcement-warning { background: rgba(251, 191, 36, 0.15); border-bottom: 1px solid rgba(251, 191, 36, 0.3); color: #fbbf24; }
.announcement-maintenance { background: rgba(239, 68, 68, 0.15); border-bottom: 1px solid rgba(239, 68, 68, 0.3); color: #f87171; }
.announcement-season { background: rgba(139, 92, 246, 0.15); border-bottom: 1px solid rgba(139, 92, 246, 0.3); color: #a78bfa; }
.announcement-dismiss { position: absolute; right: 16px; top: 50%; transform: translateY(-50%); background: none; border: none; color: inherit; font-size: 18px; cursor: pointer; opacity: 0.6; }
.announcement-dismiss:hover { opacity: 1; }

/* --- Main Content --- */
.public-content { flex: 1; max-width: 1200px; width: 100%; margin: 0 auto; padding: 28px 24px; }

/* --- Footer --- */
/* 2026-06-08 — compacted to a 2-row layout (redesign 01-footer): row 1 is the
   inline identity (Hosted-on-KOTT badge + wordmark) plus a single flat link row
   that flex:1 fills the remaining width (no titled columns, no centre gutter);
   row 2 is one hairline-topped baseline strip carrying copyright + Discord +
   the strictly-necessary-cookie fine print. Both rows constrained to the 1200px
   content width so the footer aligns with the page above. */
.public-footer { padding: 24px 24px 16px; color: var(--text-muted); font-size: 12px; border-top: 1px solid var(--border); }
.footer-main { max-width: 1200px; margin: 0 auto; display: flex; flex-wrap: wrap; align-items: center; gap: 16px 40px; }
.footer-identity { display: flex; flex-direction: row; align-items: center; gap: 12px; }
.footer-brand { font-family: var(--font-display); font-weight: 600; letter-spacing: 0.5px; text-transform: uppercase; color: var(--text-tertiary); }
/* NEW (redesign 01-footer) — single flat inline link row; dot dividers via
   ::after on every link except the last. flex:1 lets it fill the width that the
   old right-anchored columns used to leave as an empty centre gutter. */
/* 2026-08-02 — three labelled columns instead of one 13-link interpunct-separated row, where
   "Servers" sat next to "Security" and you had to read the whole thing to find anything. The
   dot separators go with it: they were the glue holding a flat list together, and a grouped
   list does not need them. */
.footer-links { flex: 1; display: flex; flex-wrap: wrap; align-items: flex-start; gap: 24px 48px; }
.footer-col { display: flex; flex-direction: column; gap: 7px; min-width: 128px; }
.footer-col-h {
    font-family: var(--font-display); font-size: 10px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.1em;
    color: var(--text-tertiary); margin-bottom: 2px;
}
.footer-links a { font-size: 13px; color: var(--text-muted); transition: color 0.12s ease; line-height: 1.35; }
.footer-links a:hover { color: var(--accent); }
.footer-discord { display: inline-flex; align-items: center; gap: 6px; color: var(--text-tertiary); font-family: var(--font-display); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; transition: color 0.12s ease; }
.footer-discord:hover { color: #5865F2; }
.footer-discord:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Baseline strip — one flex row (space-between on desktop) holding copyright,
   the relocated Discord link, and the cookie sentence; replaces the old
   centred dedicated cookie band. */
.footer-base { max-width: 1200px; margin: 16px auto 0; padding-top: 14px; border-top: 1px solid var(--border); display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 8px 16px; text-align: left; }
.footer-cookie { font-size: 11px; color: var(--text-muted); opacity: 0.9; }
.footer-cookie a { color: var(--text-tertiary); text-decoration: underline; }
.footer-cookie a:hover { color: var(--accent); }
@media (max-width: 640px) {
    .footer-main { flex-direction: column; align-items: flex-start; gap: 14px; }
    .footer-links { justify-content: flex-start; }
    .footer-base { flex-direction: column; align-items: center; text-align: center; gap: 6px; }
}

/* --- Page Title --- */
.page-title { font-family: var(--font-display); font-size: var(--text-xl); font-weight: 700; color: var(--text-primary); margin-bottom: 20px; display: flex; align-items: center; gap: 10px; letter-spacing: 0.5px; outline: none; }
/* Wave 5 sub-theme 5.7 (visual-design F47) — page subtitle. Sits below
   .page-title on Leaderboard / Matches / etc.; lifts the page title's
   bottom margin so the pair reads as one block. */
.page-subtitle { color: var(--text-secondary); font-size: var(--text-sm); margin: -16px 0 16px; line-height: 1.55; }
.page-title + .page-subtitle { margin-top: -16px; }

/* --- Hero h1 modifier (Home / mode landing pages) — bumps to 44px desktop, 32px mobile.
   Applied to existing hero headings without changing the canonical .page-title rule.
   2026-07-08 atmosphere pass — fluid clamp() declared SECOND so it wins where
   supported (everywhere modern) while the 44px line stays as the legacy
   fallback + the pinned VisualDesignTopFiveGuards anchor. The clamp spans the
   old mobile override (32px) to the old desktop size (44px). */
.h1-hero {
    font-size: 44px;
    font-size: clamp(32px, 24.8px + 1.5vw, 44px);
    letter-spacing: -1px;
    line-height: 1.1;
}

/* --- Buttons --- */
.btn { font-family: var(--font-display); font-weight: 600; font-size: 13px; padding: 7px 16px; border-radius: 4px; border: 1px solid var(--border); background: transparent; color: var(--text-secondary); cursor: pointer; transition: all 0.12s ease; text-transform: uppercase; letter-spacing: 0.5px; text-decoration: none; display: inline-flex; align-items: center; justify-content: center; }
.btn:hover { border-color: var(--border-hover); color: var(--text-primary); }
.btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #000; }
.btn.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); }
.btn.danger { border-color: rgba(248, 113, 113, 0.2); color: var(--danger); }
.btn.danger:hover { background: rgba(248, 113, 113, 0.08); border-color: var(--danger); }
/* 2026-06-08 — merged the duplicate .btn-sm (was re-declared ~5691 overriding
   font-size→12px + padding→5px 10px; those later values folded in here and the
   duplicate deleted — computed result unchanged). */
.btn-sm { font-family: var(--font-display); font-size: 12px; padding: 5px 10px; border-radius: 4px; background: transparent; border: 1px solid var(--border-accent); color: var(--accent) !important; font-weight: 600; text-decoration: none; transition: all 0.12s ease; letter-spacing: 0.5px; text-transform: uppercase; }
.btn-sm:hover { background: var(--accent-dim); border-color: var(--accent); }
.btn-sm:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.btn-xs { font-family: var(--font-display); font-size: 9px; padding: 2px 8px; border-radius: 3px; background: transparent; border: 1px solid rgba(255,255,255,0.15); color: var(--text-muted) !important; font-weight: 600; text-decoration: none; transition: all 0.12s ease; letter-spacing: 0.5px; text-transform: uppercase; margin-left: auto; }
.btn-xs:hover { border-color: var(--accent); color: var(--accent) !important; }

/* --- Tables — Hairline borders --- */
.pub-table { width: 100%; border-collapse: collapse; font-size: 13px; }
.pub-table thead { position: sticky; top: 56px; z-index: 10; }
.pub-table th { text-align: left; padding: 6px 14px; background: #000000; color: var(--text-tertiary); font-family: var(--font-display); font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; border-bottom: 1px solid var(--border-hover); line-height: 1.3; }
.pub-table td { padding: 5px 14px; border-bottom: 1px solid var(--border); line-height: 1.35; }
.pub-table tr { transition: background 0.1s ease; }
.pub-table tbody tr:hover { background: var(--bg-hover); }
.pub-table th.right, .pub-table td.right { text-align: right; }
.pub-table th.center, .pub-table td.center { text-align: center; }

/* --- Tier Badges — Sharp tags with thin borders ---
   line-height: 1 + vertical-align: middle for the same reason as .rank-num (which shares its
   row): 11px × the cell's 1.35 + 4 padding + 2 border = 20.85px, taller than the 17.55px strut,
   so the badge — not the data — set the height of every leaderboard row. It was the only badge
   in this family without the align fix. */

/* --- Rank Number --- */
/* vertical-align: middle — an inline-block sits on the baseline by default, so the strut's
   descender adds ~3px of dead space under the tallest cell in every row. The rank span is alone
   in its td, so re-aligning it is height-only.
   line-height: 1 — the align fix alone wasn't enough: the box was still 15px × the cell's 1.35
   = 20.25px, i.e. taller than the 17.55px text strut it sits next to, so it kept setting the row
   height on all 9 pages that use it. At 1 the box is 15px and the text wins. */
.rank-num { font-family: var(--font-display); font-size: 15px; font-weight: 700; color: var(--text-muted); min-width: 28px; display: inline-block; vertical-align: middle; line-height: 1; }
.rank-num.top1 { color: var(--tier-champion); }
.rank-num.top2 { color: var(--tier-diamond); }
.rank-num.top3 { color: var(--tier-gold); }

/* --- Rating Display --- */
.rating { font-family: var(--font-display); font-weight: 700; font-variant-numeric: tabular-nums; }
.rating-label { font-size: 11px; color: var(--text-muted); margin-left: 2px; }
.rating-change { font-family: var(--font-display); font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; }
.rating-change.positive { color: var(--success); }
.rating-change.negative { color: var(--danger); }

/* --- Win Rate --- */
.winrate { font-family: var(--font-display); font-variant-numeric: tabular-nums; }
.winrate.high { color: var(--success); }
.winrate.mid { color: var(--text-primary); }
.winrate.low { color: var(--danger); }

/* --- Match Result --- */
.result-win { color: var(--success); font-weight: 700; }
.result-loss { color: var(--danger); font-weight: 700; }
.vs-text { color: var(--text-muted); font-size: 12px; font-weight: 600; padding: 0 6px; }
.match-ranked { font-family: var(--font-display); font-size: 10px; font-weight: 600; text-transform: uppercase; padding: 1px 6px; border-radius: 4px; border: 1px solid; }
.match-ranked.ranked { background: var(--accent-dim); color: var(--accent); border-color: var(--border-accent); }
.match-ranked.unranked { background: rgba(107, 114, 128, 0.08); color: var(--text-tertiary); border-color: rgba(107, 114, 128, 0.15); }
.match-reason { font-size: 11px; color: var(--text-muted); }
.match-time { font-size: 12px; color: var(--text-muted); white-space: nowrap; }

/* --- Player Profile Header — Glass panel --- */
.profile-header { background: var(--bg-panel);  border: none; border-radius: 5px; padding: 28px; margin-bottom: 24px; display: flex; align-items: center; gap: 24px; }
.profile-avatar { width: 72px; height: 72px; border-radius: 50%; background: rgba(255,255,255,0.03); border: none; display: flex; align-items: center; justify-content: center; font-family: var(--font-display); font-size: 28px; color: var(--text-muted); flex-shrink: 0; }
/* min-width: 0 on the flex child — without it a long unbroken player name
   refuses to shrink and pushes the header past a 360px viewport. */
.profile-info { min-width: 0; }
.profile-info h1 { font-family: var(--font-display); font-size: 24px; font-weight: 700; color: var(--text-primary); margin-bottom: 6px; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; overflow-wrap: anywhere; min-width: 0; }
.profile-meta { display: flex; gap: 20px; font-size: 13px; color: var(--text-secondary); flex-wrap: wrap; }
.profile-meta strong { color: var(--text-primary); font-family: var(--font-display); }

/* --- Stats Grid — Glass cards --- */
/* 2026-06-08 — merged the duplicate .stats-grid (was re-declared ~1736 with
   auto-fill/160px + margin:16px 0 fully winning via cascade; folded those
   later values in here and deleted the duplicate — computed result unchanged). */
.stats-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; margin: 16px 0; }
.stat-card { background: var(--bg-panel);  border: none; border-radius: 5px; padding: 16px 18px; }
/* Display-face numerals must not carry prose leading: at .public-shell's 1.6 a 22px glyph got a
   35.2px line box — 13px of dead air per tile, on ~7 pages × 4-6 tiles. Same treatment the file
   already gives .player-count-num and .cd-num. */
.stat-card .stat-label { font-family: var(--font-display); font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px; line-height: 1.3; }
.stat-card .stat-value { font-family: var(--font-display); font-size: 22px; font-weight: 700; color: var(--text-primary); font-variant-numeric: tabular-nums; line-height: 1.1; }
.stat-card .stat-value.success { color: var(--success); }
.stat-card .stat-value.danger { color: var(--danger); }

/* --- Server Cards — Glass panels --- */
.server-section-label { font-family: var(--font-display); font-size: 13px; font-weight: 600; color: var(--text-tertiary); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 10px; margin-top: 24px; }
.server-section-label:first-of-type { margin-top: 0; }
.section-desc { font-size: 13px; color: var(--text-muted); margin: -4px 0 14px; line-height: 1.5; }
.section-desc a { color: var(--accent); }
.server-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 14px; margin-bottom: 12px; }

/* Cross-mode footer links — appears at the bottom of every mode page
   (Queue, KOTH, Time Attack) so users always have a one-click path to the
   other two modes without dead-ending. Previously .servers-other-* but
   renamed to .mode-footer-* since it's shared across mode pages now. */
.mode-footer-links {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
    max-width: var(--home-content-width);
    margin: 28px auto 32px;
}
.mode-footer-link {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 14px 18px;
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 5px;
    background: rgba(255,255,255,0.02);
    text-decoration: none;
    color: inherit !important;
    transition: all 0.15s ease;
}
.mode-footer-link:hover {
    border-color: var(--border-accent-strong);
    background: var(--bg-hover);
    transform: translateY(-1px);
}
.mode-footer-label {
    font-family: var(--font-display);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    padding: 4px 10px;
    border-radius: 3px;
    border: 1px solid;
    flex-shrink: 0;
}
.mode-footer-label.ta { color: var(--accent-purple); border-color: rgba(180, 156, 255, 0.35); background: rgba(180, 156, 255, 0.08); }
.mode-footer-label.mm { color: var(--accent); border-color: var(--border-accent-strong); background: var(--accent-dim); }
.mode-footer-label.servers { color: var(--accent); border-color: var(--border-accent-strong); background: var(--accent-dim); }
.mode-footer-label.lb { color: var(--text-primary); border-color: rgba(255, 255, 255, 0.20); background: rgba(255, 255, 255, 0.04); }
.mode-footer-text { color: var(--text-secondary); font-size: var(--text-base); }

/* Community-servers block: "see also" section, de-emphasized header */
.servers-community-title {
    font-family: var(--font-display);
    font-size: var(--text-lg);
    font-weight: 600;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin: 36px 0 6px;
    padding-top: 20px;
    border-top: 1px solid var(--border-hover);
}
.servers-community-sub {
    color: var(--text-muted);
    font-size: var(--text-sm);
    margin: 0 0 14px;
    line-height: 1.5;
}
@media (max-width: 640px) {
    .mode-footer-links { grid-template-columns: 1fr; }
}
.server-card { background: var(--bg-panel);  border: none; border-radius: 5px; padding: 18px; }
.server-card.online { border: 1px solid rgba(52, 211, 153, 0.15); }
.server-card.offline { opacity: 0.55; position: relative; }
.server-card.offline::after { content: "OFFLINE"; position: absolute; top: 12px; right: 12px; font-family: var(--font-display); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: var(--danger); background: rgba(248, 113, 113, 0.08); border: 1px solid rgba(248, 113, 113, 0.15); padding: 2px 8px; border-radius: 4px; }
.server-card-header { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.server-card-header .server-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.server-dot.green { background: var(--success); box-shadow: 0 0 6px rgba(52, 211, 153, 0.4); }
.server-dot.red { background: var(--danger); }
.server-card-header strong { font-family: var(--font-display); font-size: 15px; color: var(--text-primary); }
/* 1.8 was MORE than the site's own prose leading, and it was set for the label/value
   .server-card-row markup ServerCard.razor no longer renders — it now only reaches
   .player-count-max/-word, whose descent (not the 30px number) was setting the baseline-aligned
   player-count line. 1.45 matches the .server-description it wraps. */
.server-card-body { font-size: 13px; color: var(--text-secondary); line-height: 1.45; }
.server-card-body .label { color: var(--text-muted); }
.server-card-body .player-count { font-family: var(--font-display); font-weight: 600; color: var(--text-primary); }

/* Unified server card — shared between KOTH, Time Attack, and community modes.
   Role modifiers set accent color; the structural layout (header with mode badge,
   label/value rows, footer connect button) is the same across modes so users
   scan one consistent pattern. */
.server-card { display: flex; flex-direction: column; transition: border-color 0.2s; }
.server-card:hover { border-color: var(--border-hover); }
.server-card.role-timeattack.online { border: 1px solid rgba(180, 156, 255, 0.30); }
/* Free Roam (Wave F) — warm amber, distinct from KOTH cyan / TA-MM purple. */
.server-card.role-freeroam.online { border: 1px solid rgba(255, 184, 107, 0.30); }
.server-card.role-community.online { border: 1px solid rgba(255, 255, 255, 0.10); }
.server-card-header { flex-direction: column; align-items: flex-start; gap: 6px; }
.server-card-header-left { display: flex; align-items: center; gap: 8px; min-width: 0; width: 100%; }
/* min-width:0 + flex:1 (2026-07-09 mobile audit): a flex child refuses to shrink below its
   nowrap content by default, so a 90-char community server name forced the card — and the whole
   page — to ~750px wide on a 360px phone (horizontal scroll + giant stretched map boxes). */
.server-card-header-left strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1; }
.server-mode-badge { font-family: var(--font-display); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.8px; padding: 3px 8px; border-radius: 4px; flex-shrink: 0; white-space: nowrap; }
.server-mode-badge.mode-ta { background: rgba(180, 156, 255, 0.12); color: #b49cff; border: 1px solid rgba(180, 156, 255, 0.30); }
.server-mode-badge.mode-freeroam { background: rgba(255, 184, 107, 0.12); color: #ffb86b; border: 1px solid rgba(255, 184, 107, 0.30); }
/* Wave 5 sub-theme 5.7 (visual-design F42) — was --text-muted (#7a8493);
   bumped to --text-secondary (#9ca3af, ~7.5:1 vs #000) for badge legibility
   on the dark card chrome. */
.server-mode-badge.mode-community { background: rgba(255, 255, 255, 0.05); color: var(--text-secondary); border: 1px solid rgba(255, 255, 255, 0.18); }
/* SRP route battles: the "Highway" flavour chip (network course model) — cyan, the route accent. */
.server-mode-badge.mode-highway { background: rgba(0, 224, 255, 0.10); color: #00e0ff; border: 1px solid rgba(0, 224, 255, 0.32); }
.server-card-row { display: flex; align-items: baseline; gap: 10px; padding: 3px 0; font-size: 13px; line-height: 1.5; flex-wrap: wrap; /* Wave 5 sub-theme 5.7 — weather row wraps on narrow viewports rather than ellipsing the rain/grip suffix off-screen. */ }
.server-card-row .label { color: var(--text-muted); font-family: var(--font-display); font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; min-width: 64px; flex-shrink: 0; }
.server-card-row .value { color: var(--text-secondary); flex: 1; min-width: 0; }
.server-card-row.muted .value { color: var(--text-muted); font-style: italic; }
.server-card-row .record-time { color: #b49cff; font-family: var(--font-mono, monospace); font-weight: 600; font-size: 15px; margin-right: 8px; }
.server-card-row .record-holder { color: var(--text-tertiary); font-size: 11px; }
.server-card-row .ta-delta { margin-left: 6px; font-size: 12px; font-weight: 600; }
/* 2026-05-05 Tier 1 — server card extras (community + managed). */
.server-flag { font-size: 14px; line-height: 1; flex-shrink: 0; }
.server-lock { margin-left: 4px; font-size: 12px; opacity: 0.85; }
.server-description { font-size: 12px; color: var(--text-tertiary); line-height: 1.45; margin: 0 0 8px; padding: 0 0 8px; border-bottom: 1px dashed var(--border); font-style: italic; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.track-layout { color: var(--text-tertiary); font-size: 12px; }

/* --- Phase 5 / Task 5.3 — TA cards live data ---
   Top-3 deltas + recent PB activity sections, refreshed every 30s by
   PollTaLiveDataAsync on Public/Servers.razor. The borders + subtle
   dividers visually separate live data from the static record/PB rows. */
.ta-top3, .ta-activity { margin-top: 10px; padding-top: 8px; border-top: 1px solid rgba(180, 156, 255, 0.10); font-size: 12px; line-height: 1.5; }
.ta-top3-title, .ta-activity-title { font-family: var(--font-display); font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted); margin-bottom: 4px; }
.ta-top3-row, .ta-activity-row { display: flex; align-items: baseline; gap: 8px; padding: 1px 0; }
.ta-top3-rank { color: var(--text-tertiary); font-family: var(--font-mono, monospace); font-size: 11px; min-width: 24px; }
.ta-top3-driver, .ta-activity-driver { display: flex; flex-direction: column; flex: 1; min-width: 0; }
.ta-top3-name, .ta-activity-name { color: var(--text-secondary); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ta-top3-car, .ta-activity-car { color: var(--text-muted); font-size: 10px; line-height: 1.15; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ta-top3-name:hover, .ta-activity-name:hover { color: #b49cff; }
.ta-top3-time, .ta-activity-time { color: #b49cff; font-family: var(--font-mono, monospace); font-weight: 600; }
.ta-top3-delta { font-size: 11px; font-weight: 600; }
.ta-activity-ago { color: var(--text-muted); font-size: 11px; }

.server-card-footer { margin-top: auto; padding-top: 14px; }
.server-card-connect { display: block; width: 100%; text-align: center; }
.server-card-connect.disabled { opacity: 0.35; pointer-events: none; }
.server-links { margin-top: 10px; display: flex; gap: 8px; }
/* Wave 5 sub-themes 5.4 + 5.7 (2026-05-06) — server-card additions:
   FULL badge for at-capacity servers; per-card freshness line; promoted
   Connect button to the cyan filled style. */
.server-full-badge {
    display: inline-block;
    margin-left: 6px;
    padding: 2px 8px;
    border-radius: 3px;
    background: rgba(255, 107, 107, 0.15);
    border: 1px solid rgba(255, 107, 107, 0.45);
    color: var(--danger);
    font-family: var(--font-display);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
}
.server-card-meta {
    margin-top: 10px;
    padding-top: 8px;
    border-top: 1px dashed var(--border);
    font-size: 11px;
    color: var(--text-tertiary);
    line-height: 1.4;
}
.server-card-freshness {
    font-family: var(--font-mono, monospace);
    color: var(--text-tertiary);
}
.server-card-freshness-offline {
    color: var(--danger);
    opacity: 0.85;
}
/* 2026-06-06 — unified <ServerCard> action bar: Connect (primary, grows) + Live view (outline)
   + Copy-IP icon. One row, online-only. Replaces the old per-page footer / server-links layouts. */
.server-card-actions { display: flex; align-items: stretch; gap: 8px; margin-top: auto; padding-top: 14px; }
.server-card-actions .btn-connect { flex: 1 1 auto; }
.server-card-actions .btn-connect.disabled { opacity: 0.35; pointer-events: none; }
.server-card-actions .btn-live { flex: 0 0 auto; }
.server-card-actions .btn-copyip { flex: 0 0 auto; width: 36px; padding-left: 0; padding-right: 0; font-size: 14px; letter-spacing: 0; }
/* Track row carries a compact right-aligned weather chip (condition icon + air temp). */
.server-card-row .track-value { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.server-card-row .track-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.server-card-row .weather-chip { color: var(--text-tertiary); font-size: 12px; white-space: nowrap; flex-shrink: 0; }
/* 2026-06-06 — game-mode accent per card (KOTH cyan default / Time Attack purple) drives the hero
   player-count colour; the badge + card border already carry the mode colour. A min-height floor +
   clamped description keep cards a consistent size without forced-stretch whitespace. */
.server-card { --mode-accent: var(--accent); min-height: 200px; min-width: 0; }
.server-card.role-timeattack { --mode-accent: #b49cff; }
.server-card.role-freeroam { --mode-accent: #ffb86b; }
/* ===== SERVER-CARD TRACK MAP HERO (redesign 03-server-card-track-map) =====
   Static lazy <img> minimap bled to the card's top edge (negative margins cancel
   the 18px card padding). Fixed 16:9 box + object-fit:contain + dark backing +
   0.6 opacity + a top/bottom scrim normalize AC's inconsistent map.png art. The
   .has-no-map state (set by the <img> onerror handler) hides the broken image and
   shows a --mode-accent-tinted "Map unavailable" panel so the grid never shifts. */
.server-card-map { position: relative; width: calc(100% + 36px); margin: -18px -18px 14px; aspect-ratio: 16 / 9; background: #05080c; border-radius: 5px 5px 0 0; overflow: hidden; }
.server-card-map-img { width: 100%; height: 100%; object-fit: contain; opacity: 0.6; display: block; background: #05080c; }
.server-card-map::after { content: ''; position: absolute; inset: 0; pointer-events: none; background: linear-gradient(180deg, rgba(0,0,0,0.35) 0%, transparent 35%, transparent 70%, rgba(0,0,0,0.45) 100%); }
.server-card-map-fallback { display: none; position: absolute; inset: 0; align-items: center; justify-content: center; gap: 6px; font-family: var(--font-display); font-size: 11px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--text-muted); }
.server-card-map.has-no-map .server-card-map-img { display: none; }
.server-card-map.has-no-map .server-card-map-fallback { display: flex; }
.server-card-map.has-no-map { background: color-mix(in srgb, var(--mode-accent) 7%, #05080c); }
/* .is-line-map (set by server-card-dots.js when map-meta.json's mapMode is "line" — a stub map that
   cannot hold the track, e.g. shomaru): the stub <img> hides and the dots canvas carries the KOTT
   line bounds-fit instead, so the card shows the same line map the live page draws. */
.server-card-map.is-line-map .server-card-map-img { display: none; }
.server-card-map.is-line-map .server-card-map-fallback { display: none; }
.server-card-map-weather { position: absolute; top: 8px; right: 8px; z-index: 2; background: rgba(0,0,0,0.55); backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px); border: 1px solid var(--border); border-radius: 4px; padding: 2px 7px; font-size: 12px; color: var(--text-secondary); white-space: nowrap; }
/* In-game time-of-day half of the combined weather chip — dimmer than the temp, with a thin separating border so the two halves read distinctly. */
.server-card-map-weather .tod { color: var(--text-tertiary); padding-left: 5px; margin-left: 2px; border-left: 1px solid var(--border); }
/* Live position dots overlay — fills the 16:9 map box, never blocks card clicks.
   z-index 1 keeps it above the map img + ::after gradient but below the weather
   chip (z-index 2). */
.server-card-map-dots { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 1; pointer-events: none; }
/* Track reads as a heading + layout pill (replaces the old Track label/value row). */
.server-card-track { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin: 0 0 10px; }
.server-card-track-name { font-family: var(--font-display); font-size: 18px; font-weight: 700; color: var(--text-primary); letter-spacing: 0.3px; line-height: 1.15; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.server-card-layout-badge { font-family: var(--font-display); font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; padding: 2px 7px; border-radius: 4px; background: rgba(255,255,255,0.05); border: 1px solid var(--border); color: var(--text-secondary); white-space: nowrap; flex-shrink: 0; }
.server-card.offline .server-card-map-img { opacity: 0.3; filter: grayscale(1); }
/* Hero player count — the "should I join?" stat. */
.server-card-players { display: flex; align-items: baseline; gap: 6px; margin: 2px 0 12px; }
.server-card-players .player-count-num { font-family: var(--font-display); font-weight: 700; font-size: 30px; line-height: 1; color: var(--mode-accent); }
.server-card-players .player-count-max { font-size: 16px; font-weight: 600; color: var(--text-muted); }
.server-card-players .player-count-word { font-size: 11px; text-transform: uppercase; letter-spacing: 0.6px; color: var(--text-muted); align-self: center; }
.server-card-players.is-full .player-count-num { color: var(--text-muted); }
.server-card-players.is-stale .player-count-num { color: var(--text-tertiary); opacity: 0.7; }
/* Clamp the optional free-text description so a long blurb doesn't blow out one card's height. */
.server-description { display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
/* Empty-state compact variant — used when the section has its own header
   (e.g. Community Servers explainer always renders, the empty state under
   it is just one line, not a full hero). */
.empty-state-compact {
    padding: 16px;
    text-align: left;
    color: var(--text-muted);
}

/* --- Operators directory (Phase 4 / Task 4.3) ---
   Public-facing tenant browser at /operators. Lists every active tenant
   that's opted-in via tenants.list_publicly. Card pattern mirrors the
   server-card grid for visual consistency, but each card is a single
   anchor leading to /community/{slug}/. */
.ops-header { margin-bottom: 22px; }
.ops-title { font-family: var(--font-display); font-size: 32px; font-weight: 700; letter-spacing: 0.5px; color: var(--text-primary); margin: 0 0 8px 0; }
.ops-explainer { color: var(--text-secondary); font-size: 14px; line-height: 1.65; max-width: 720px; margin: 0; }
/* min(320px, 100%) — a hard 320px floor overflowed the container on narrow
   phones (card text touched the viewport edge past the content padding). */
.ops-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(320px, 100%), 1fr)); gap: 14px; margin-bottom: 24px; }
.ops-card { display: flex; flex-direction: column; padding: 18px; text-decoration: none; color: inherit; transition: border-color 0.18s, transform 0.18s; }
/* 2026-05-07 — community detail expansion. Bump hover to -2px + brighter
   accent border so the click-affordance reads as obvious "this is a
   navigable card" (was -1px / 0.35-alpha — too subtle once the link
   target became a real /community/{slug} detail page). */
.ops-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.ops-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ops-card-header { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
.ops-name { font-family: var(--font-display); font-size: 17px; font-weight: 700; color: var(--text-primary); letter-spacing: 0.3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ops-slug { font-family: var(--font-mono, monospace); font-size: 11px; color: var(--accent); opacity: 0.85; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ops-card-meta { display: flex; align-items: center; gap: 12px; margin-bottom: 10px; font-size: 12px; color: var(--text-secondary); font-family: var(--font-display); text-transform: uppercase; letter-spacing: 0.5px; }
.ops-server-count { display: inline-flex; align-items: center; gap: 6px; }
.ops-dot { width: 8px; height: 8px; border-radius: 50%; }
.ops-dot.online { background: var(--success); box-shadow: 0 0 6px rgba(52, 211, 153, 0.4); }
.ops-dot.offline { background: var(--text-muted); opacity: 0.5; }
.ops-blurb { font-size: 13px; color: var(--text-secondary); line-height: 1.55; margin: 0; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
/* 2026-05-05 Tier 1 — operator card enrichment from heartbeat info section.
   Wave 5 sub-theme 5.7 (2026-05-06) — explicit font-weight: 400 so the flag
   doesn't inherit the bold weight even if a parent <strong> wrapper sneaks
   back in. */
.ops-flag { font-size: 16px; margin-right: 6px; line-height: 1; vertical-align: -2px; font-weight: 400; }
.ops-name-row { display: flex; align-items: center; gap: 4px; min-width: 0; }
/* Wave 5 sub-theme 5.5 (2026-05-06) — section headers used by the
   First-party / Community split. Match .section-title weight so they
   slot into the page's existing typographic scale. */
.ops-section-title {
    font-family: var(--font-display);
    font-size: var(--text-lg);
    font-weight: 700;
    color: var(--text-primary);
    margin: 16px 0 4px;
    letter-spacing: 0.3px;
}
.ops-section-title:first-child { margin-top: 0; }
.ops-section-sub {
    font-size: var(--text-sm);
    color: var(--text-secondary);
    margin: 0 0 12px;
}
.ops-player-count { color: var(--text-tertiary); font-weight: 500; }
.ops-modes { display: inline-flex; gap: 4px; margin-left: auto; }
/* Wave I (2026-05-12) F-313 — bump from --text-tertiary (#6b7280, ~4.2:1) to
   --text-secondary (#9ca3af, ~7.5:1 vs #000) so the communities-directory mode
   badge reads as clearly as the server-card community badge (fixed in Wave 5.7). */
.ops-mode-badge { font-family: var(--font-display); font-size: 10px; font-weight: 700; letter-spacing: 0.5px; padding: 2px 8px; border-radius: 3px; text-transform: uppercase; border: 1px solid var(--border); color: var(--text-secondary); }
.ops-mode-matchmaking { color: var(--accent); border-color: rgba(0, 224, 255, 0.4); background: rgba(0, 224, 255, 0.08); }
.ops-mode-time-attack { color: #b49cff; border-color: rgba(180, 156, 255, 0.35); background: rgba(180, 156, 255, 0.08); }
.ops-mode-free-roam { color: #ffb86b; border-color: rgba(255, 184, 107, 0.35); background: rgba(255, 184, 107, 0.08); }
.ops-sample { display: flex; align-items: center; gap: 10px; margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--border); font-size: 12px; color: var(--text-tertiary); }
.ops-sample-track { font-family: var(--font-mono, monospace); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ops-weather-chip { display: inline-flex; align-items: center; gap: 4px; font-family: var(--font-display); font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 999px; background: rgba(255, 255, 255, 0.04); border: 1px solid var(--border); color: var(--text-secondary); }

/* --- Track Selector --- */
.track-selector { display: flex; gap: 6px; margin-bottom: 20px; flex-wrap: wrap; }
.track-btn { font-family: var(--font-display); background: transparent; border: 1px solid var(--border); color: var(--text-tertiary); padding: 6px 16px; border-radius: 4px; font-size: 12px; font-weight: 600; cursor: pointer; transition: all 0.12s ease; text-transform: uppercase; letter-spacing: 0.5px; }
.track-btn:hover { border-color: var(--border-hover); color: var(--text-primary); }
.track-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.track-btn.active { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }

/* --- Section Title --- */
.section-title { font-family: var(--font-display); font-size: var(--text-base); font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.5px; margin: 24px 0 12px; padding-bottom: 8px; border-bottom: 1px solid var(--border); }

/* --- Loading / Empty --- */
/* 2026-06-08 — centered flex column + gap so markup can drop the <br/> spacers
   between the spinner and the loading label. */
.pub-loading { text-align: center; padding: 60px 20px; color: var(--text-muted); font-size: 14px; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.pub-loading .spinner { display: inline-block; width: 20px; height: 20px; border: 2px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: pub-spin 0.6s linear infinite; /* 2026-06-08 — bottom margin dropped; .pub-loading now spaces children via flex gap. */ }
@keyframes pub-spin { to { transform: rotate(360deg); } }
.pub-empty { background: var(--bg-panel);  border: none; border-radius: 5px; padding: 48px 28px; text-align: center; }
.pub-empty h3 { color: var(--text-secondary); font-family: var(--font-display); font-size: 15px; margin-bottom: 6px; }
.pub-empty p { color: var(--text-muted); font-size: 13px; }

/* --- Player Link --- */
.player-link { color: var(--text-primary) !important; font-weight: 500; transition: color 0.1s; display: inline-block; max-width: 18ch; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: bottom; }
.player-link:hover { color: var(--accent) !important; }
.player-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* On wider match rows / cards, allow more characters. */
.pub-table .player-link, .match-players .player-link { max-width: 28ch; }

/* --- Lap detail links --- */
.lap-link { color: inherit; text-decoration: none; border-bottom: 1px dashed rgba(0, 224, 255, 0.4); transition: color 0.1s, border-color 0.1s; }
.lap-link:hover { color: var(--accent, #00e0ff); border-bottom-color: var(--accent, #00e0ff); }

/* --- Auto-refresh indicator --- */
.refresh-indicator { font-family: var(--font-display); font-size: 11px; color: var(--text-muted); display: inline-flex; align-items: center; gap: 6px; cursor: default; }
.refresh-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); animation: pulse-refresh 2s infinite; }
.refresh-dot.pulsing { animation: refresh-spin 0.6s linear infinite; box-shadow: 0 0 6px var(--accent); }
.refresh-text { letter-spacing: 0.5px; }
@keyframes refresh-spin { 0% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.6); opacity: 0.4; } 100% { transform: scale(1); opacity: 1; } }
@keyframes pulse-refresh { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

/* --- Leaderboard Podium --- */
.leaderboard-podium { display: flex; justify-content: center; align-items: flex-end; gap: 16px; margin-bottom: 28px; padding: 20px 0; }
.podium-card { background: var(--bg-panel);  border: none; border-radius: 5px; padding: 20px 24px; text-align: center; flex: 0 0 200px; }
.podium-1 { border: 1px solid var(--border-accent); padding: 28px 24px; }
.podium-1:hover { border-color: var(--accent); }
.podium-rank { font-family: var(--font-display); font-size: 28px; font-weight: 700; margin-bottom: 8px; }
.podium-1 .podium-rank { color: var(--tier-champion); font-size: 36px; }
.podium-2 .podium-rank { color: var(--tier-diamond); }
.podium-3 .podium-rank { color: var(--tier-gold); }
.podium-name { font-family: var(--font-display); font-size: 16px; font-weight: 600; color: var(--text-primary) !important; display: block; margin-bottom: 6px; }
.podium-name:hover { color: var(--accent) !important; }
.podium-rating { font-family: var(--font-display); font-size: 20px; font-weight: 700; color: var(--text-primary); margin-bottom: 6px; }
.podium-record { font-size: 12px; color: var(--text-tertiary); margin-top: 6px; }

/* --- Current Player Row Highlight --- */
.current-player-row { background: var(--accent-dim) !important; border-left: 2px solid var(--accent); }
.current-player-row td:first-child { padding-left: 12px; }

/* --- Pagination --- */
.pagination { display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 20px; padding: 16px 0; }
.pagination-info { font-family: var(--font-display); font-size: 13px; color: var(--text-muted); font-weight: 500; }

/* --- Phase 5 / Task 5.5 — leaderboard infinite scroll ---
   Sentinel is intentionally empty (height + width 1px) so it doesn't
   alter the visual layout — the IntersectionObserver in
   /js/infinite-scroll.js fires on it. The status strip below shows
   "Loading more…" / "End of leaderboard" / current count. */
.lb-status-strip { display: flex; justify-content: center; align-items: center; gap: 10px; padding: 18px 0 6px 0; font-family: var(--font-display); font-size: 13px; color: var(--text-muted); font-weight: 500; min-height: 28px; }
.lb-status-loading { display: inline-flex; align-items: center; gap: 8px; }
.lb-status-end { color: var(--text-tertiary); font-style: italic; }
.spinner-inline { width: 14px; height: 14px; border: 2px solid var(--text-muted); border-top-color: var(--accent); border-radius: 50%; animation: pub-spin 0.8s linear infinite; display: inline-block; }

/* --- Auth Nav --- */
.topnav-auth { display: flex; align-items: center; gap: 10px; margin-left: 12px; flex-shrink: 0; }
.auth-btn { font-family: var(--font-display); font-size: 12px; font-weight: 600; padding: 6px 14px; border-radius: 4px; transition: all 0.12s ease; white-space: nowrap; text-transform: uppercase; letter-spacing: 0.5px; }
.steam-btn { background: transparent; color: var(--text-secondary) !important; border: 1px solid rgba(255,255,255,0.15); }
.steam-btn:hover { border-color: var(--accent); color: var(--accent) !important; }
/* Site sign-in = Terms acceptance (2026-09-14): the one line beside every Login-with-Steam link. */
.auth-consent { display: block; font-size: 10px; line-height: 1.2; color: var(--text-secondary); max-width: 180px; margin-top: 4px; }
.auth-consent a { color: inherit; text-decoration: underline; }
/* Signed-in account cluster (2026-08-02). Replaces .player-name-link + .logout-btn, which were two
   loose siblings of the Host-a-server CTA — a bare name with no affordance next to an outlined
   button, giving Logout the same weight as the primary conversion CTA. One bordered unit instead,
   with an internal divider: the identity is the bright half, Logout the muted half.

   `!important` on colour matches the surrounding auth rules and is load-bearing here — the
   `.public-shell a` link colour (0,1,1) outranks a bare class (0,1,0), which is exactly how the
   invisible-button bug on /operators-pitch happened. */
.topnav-account {
    display: inline-flex; align-items: center;
    border: 1px solid var(--border); border-radius: 4px;
    overflow: hidden;
    line-height: 1.2;   /* dense component: admin/public shells set prose leading globally */
    /* A little more air than .topnav-auth's 10px gap: the filled CTA and the account are different
       kinds of thing (convert vs manage), and at an even gap they read as one row of controls. */
    margin-left: 4px;
}
.topnav-account-name {
    padding: 6px 11px; font-size: 13px; font-weight: 500;
    color: var(--text-primary) !important;
    transition: background 0.12s ease, color 0.12s ease;
}
.topnav-account-name:hover { background: var(--bg-hover); color: var(--accent) !important; }
.topnav-account-logout {
    padding: 7px 11px 6px;
    font-family: var(--font-display); font-size: 11px; font-weight: 600;
    text-transform: uppercase; letter-spacing: 0.5px; white-space: nowrap;
    color: var(--text-muted) !important;
    border-left: 1px solid var(--border);
    transition: background 0.12s ease, color 0.12s ease;
}
.topnav-account-logout:hover { background: var(--bg-hover); color: var(--text-primary) !important; }

/* --- Queue Discord Link --- */
.queue-discord-link { text-align: center; margin-bottom: 20px; }
.discord-queue-btn { font-family: var(--font-display); display: inline-block; background: transparent; color: #8b9bf7 !important; border: 1px solid rgba(88, 101, 242, 0.3); padding: 8px 20px; border-radius: 4px; font-weight: 600; font-size: 13px; text-decoration: none; transition: all 0.15s; text-transform: uppercase; letter-spacing: 0.5px; }
.discord-queue-btn:hover { background: rgba(88, 101, 242, 0.1); border-color: #5865F2; color: #a4b0fb !important; }

/* --- Queue Page --- */
.queue-status-bar { display: flex; gap: 12px; margin-bottom: 24px; flex-wrap: wrap; }
.queue-stat { background: var(--bg-panel);  border: none; border-radius: 5px; padding: 14px 20px; flex: 1; min-width: 140px; }
.queue-stat-label { display: block; font-family: var(--font-display); font-size: 11px; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px; }
.queue-stat-value { font-family: var(--font-display); font-size: 24px; font-weight: 700; color: var(--text-primary); line-height: 1.1; }

.queue-card { background: var(--bg-panel);  border: none; border-radius: 5px; padding: 32px; max-width: 560px; margin: 0 auto; }

/* Unified idle-state queue card. Consolidates what used to be four separate
   pieces (stats bar, "queue is open" empty-state, user identity card, buttons)
   into one cohesive panel so the whole queue-join flow reads as one action. */
.queue-card-primary { padding: 28px; max-width: 620px; }
.queue-card-primary .queue-card-head { display: flex; align-items: center; gap: 12px; padding-bottom: 18px; margin-bottom: 22px; border-bottom: 1px solid rgba(255, 255, 255, 0.06); flex-wrap: wrap; }
.queue-card-primary .queue-card-head .queue-player-rating { margin-left: auto; }
.queue-card-primary .queue-card-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0; margin-top: 22px; padding-top: 18px; border-top: 1px solid rgba(255, 255, 255, 0.06); }
.queue-card-primary .queue-stat-cell { text-align: center; padding: 4px 12px; border-right: 1px solid rgba(255, 255, 255, 0.06); display: flex; flex-direction: column; align-items: center; gap: 4px; }
.queue-card-primary .queue-stat-cell:last-child { border-right: none; }
.queue-card-primary .queue-stat-cell .queue-stat-value { font-family: var(--font-display); font-size: 22px; font-weight: 700; color: var(--text-primary); line-height: 1; }
.queue-card-primary .queue-stat-cell .queue-stat-label { font-family: var(--font-display); font-size: 10px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.8px; }
.queue-card-primary .queue-stat-cell.queue-stat-disabled { opacity: 0.4; }
.queue-card-primary .queue-stat-cell.queue-stat-disabled .queue-stat-value { color: var(--text-muted); font-size: 14px; font-weight: 600; padding-top: 6px; }

/* "or queue from Discord" secondary link under the join buttons — replaces
   the lonely top-of-page Discord button. Quiet styling: Discord's tinted
   underline on hover, no background box. */
.queue-discord-alt { display: block; text-align: center; margin-top: 14px; color: #8b9bf7 !important; font-family: var(--font-display); font-size: 12px; font-weight: 500; text-transform: uppercase; letter-spacing: 0.8px; text-decoration: none; transition: color 0.15s; }
.queue-discord-alt:hover { color: #a4b0fb !important; text-decoration: underline; }

/* Unavailable state */
/* Legacy — kept in case any tests still reference the old class names */
.queue-unavailable { text-align: center; padding: 64px 24px; max-width: 480px; margin: 0 auto; }

/* ===== QUEUE OFFLINE STATE (compact notice + alternatives) ===== */
.queue-offline-card {
    max-width: var(--home-content-width);
    margin: 16px auto 28px;
    padding: 18px 22px;
    display: flex;
    align-items: center;
    gap: 1.25rem;
    flex-wrap: wrap;
    border: 1px solid rgba(255, 179, 71, 0.25);
    background: rgba(255, 179, 71, 0.04);
    border-radius: 5px;
}
.queue-offline-label {
    font-family: var(--font-display);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    color: var(--warning);
    background: rgba(255, 179, 71, 0.12);
    border: 1px solid rgba(255, 179, 71, 0.35);
    padding: 4px 10px;
    border-radius: 3px;
    flex-shrink: 0;
}
.queue-offline-body {
    flex: 1;
    min-width: 220px;
    color: var(--text-secondary);
    font-size: var(--text-base);
    line-height: 1.5;
    margin: 0;
}
.queue-offline-cta {
    font-family: var(--font-display);
    font-size: var(--text-sm);
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: var(--accent) !important;
    text-decoration: none;
    padding: 8px 16px;
    border: 1px solid var(--border-accent-strong);
    border-radius: 4px;
    transition: all 0.15s;
    flex-shrink: 0;
}
.queue-offline-cta:hover {
    background: var(--accent-dim);
    border-color: var(--accent);
}

/* .queue-alternatives / .queue-alt-* rules deleted 2026-07-09 — the queue
   alternatives grid was cut from Queue.razor in the simplification pass. */
@media (max-width: 820px) {
    .queue-offline-card { flex-direction: column; align-items: flex-start; }
    .queue-offline-cta { align-self: stretch; text-align: center; }
}

/* Login card */
.queue-login-card { text-align: center; padding: 48px 32px; }
.queue-card-icon { font-size: 40px; margin-bottom: 12px; }
.queue-login-card h2 { font-family: var(--font-display); font-size: 20px; font-weight: 700; color: var(--text-primary); margin-bottom: 8px; }
.queue-login-card p { color: var(--text-secondary); font-size: 14px; margin-bottom: 24px; }
.queue-steam-btn { display: inline-block; background: transparent; color: var(--text-secondary) !important; border: 1px solid rgba(255,255,255,0.15); padding: 12px 28px; border-radius: 4px; font-family: var(--font-display); font-size: 14px; font-weight: 600; transition: all 0.15s ease; text-transform: uppercase; letter-spacing: 0.5px; }
.queue-steam-btn:hover { border-color: var(--accent); color: var(--accent) !important; }

/* Player info */
.queue-player-info { display: flex; align-items: center; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; }
.queue-player-name { font-family: var(--font-display); font-size: 17px; font-weight: 600; color: var(--text-primary); }
.queue-player-rating { font-family: var(--font-display); font-size: 14px; color: var(--text-secondary); font-weight: 500; }

/* Error */
.queue-error { background: rgba(248, 113, 113, 0.06); border: 1px solid rgba(248, 113, 113, 0.15); color: var(--danger); padding: 10px 14px; border-radius: 4px; font-size: 13px; margin-bottom: 16px; }

/* Optional Discord-link tip — informational, sits under the join buttons.
   Not a gate: web players can queue with Steam-only and rely on browser
   notifications + the page poll loop to learn when matched. */
.queue-link-tip { display: flex; gap: 10px; align-items: flex-start; margin-top: 14px; padding: 10px 12px; background: rgba(255, 255, 255, 0.025); border: 1px solid rgba(255, 255, 255, 0.06); border-radius: 4px; }
.queue-link-tip-icon { font-size: 14px; line-height: 1.5; flex-shrink: 0; }
.queue-link-tip-text { font-size: 12px; color: var(--text-muted); line-height: 1.5; }
.queue-link-tip-text a { color: var(--accent); text-decoration: none; }
.queue-link-tip-text a:hover { text-decoration: underline; }

/* Manual-connect fallback shown alongside the Connect Now button — visible even
   when the acmanager:// link works, so a tester whose protocol handler isn't
   registered has an obvious copy-pasteable IP:port without needing to know
   what's broken. Label line gives the failure mode, body line gives the fix. */
.match-connect-fallback-label { display: block; font-size: 11px; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.6px; margin-bottom: 4px; }

/* Join buttons */
.queue-join-buttons { display: flex; gap: 12px; }
.queue-join-btn { font-family: var(--font-display); flex: 1; padding: 14px 20px; border-radius: 4px; font-size: 14px; font-weight: 600; cursor: pointer; border: 1px solid; transition: all 0.15s ease; display: flex; align-items: center; justify-content: center; gap: 8px; text-transform: uppercase; letter-spacing: 0.5px; }
.queue-join-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.queue-join-btn:disabled { opacity: 0.5; cursor: not-allowed; }
/* Primary CTA — solid accent fill + dark text. Previous version used accent-dim
   (translucent cyan) with accent-colored text: cyan-on-cyan-tint, very low contrast.
   Now reads as a proper "this is the button" call-to-action, matching the welcome-btn. */
.queue-join-btn.ranked { background: var(--accent); border-color: var(--accent); color: #001018; font-weight: 700; box-shadow: 0 0 0 1px rgba(0, 224, 255, 0.25), 0 4px 14px rgba(0, 224, 255, 0.15); }
.queue-join-btn.ranked:hover:not(:disabled) { background: var(--accent-hover, #33e7ff); box-shadow: 0 0 0 1px rgba(0, 224, 255, 0.4), 0 4px 18px rgba(0, 224, 255, 0.25); }
.queue-join-btn.unranked { background: transparent; border-color: rgba(255, 255, 255, 0.20); color: var(--text-secondary); }
.queue-join-btn.unranked:hover:not(:disabled) { background: rgba(255, 255, 255, 0.04); border-color: rgba(255, 255, 255, 0.35); color: var(--text-primary); }
.queue-join-btn-disabled { background: rgba(255,255,255,0.03) !important; border-color: rgba(255,255,255,0.08) !important; color: var(--text-muted) !important; opacity: 0.5; }
.queue-stat-disabled { opacity: 0.45; }
.queue-stat-disabled .queue-stat-value { color: var(--text-muted); }
.queue-both-off-note { margin-top: 12px; font-size: 13px; color: var(--text-muted); text-align: center; }

/* Searching state */
.queue-searching { text-align: center; padding: 48px 32px; }
.queue-searching h2 { font-family: var(--font-display); font-size: 18px; font-weight: 600; color: var(--text-primary); margin-bottom: 8px; }
.queue-searching-anim { display: flex; justify-content: center; gap: 6px; margin-bottom: 20px; }
.queue-searching-anim .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--accent); animation: queue-dot 1.4s infinite ease-in-out; }
.queue-searching-anim .dot:nth-child(2) { animation-delay: 0.2s; }
.queue-searching-anim .dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes queue-dot { 0%, 80%, 100% { opacity: 0.2; transform: scale(0.8); } 40% { opacity: 1; transform: scale(1.2); } }
.queue-position-text { color: var(--text-secondary); font-size: 14px; margin-bottom: 4px; }
.queue-wait-time { color: var(--text-muted); font-size: 13px; margin-bottom: 24px; }
.queue-cancel-btn { font-family: var(--font-display); background: transparent; border: 1px solid rgba(248, 113, 113, 0.15); color: var(--danger); padding: 8px 24px; border-radius: 4px; font-size: 13px; font-weight: 600; cursor: pointer; transition: all 0.12s ease; text-transform: uppercase; letter-spacing: 0.5px; }
.queue-cancel-btn:hover { background: rgba(248, 113, 113, 0.08); border-color: var(--danger); }

/* Matched state */
.queue-matched { text-align: center; }
.queue-matched-header { font-family: var(--font-display); font-size: 22px; font-weight: 700; color: var(--accent); margin-bottom: 20px; text-transform: uppercase; letter-spacing: 2px; }
.queue-match-players { display: flex; align-items: center; justify-content: center; gap: 12px; margin-bottom: 24px; font-family: var(--font-display); font-size: 18px; }
.queue-match-you { font-weight: 700; color: var(--text-primary); }
.queue-match-opponent { font-weight: 700; color: var(--accent) !important; }

.queue-match-details { text-align: left; background: rgba(0,0,0,0.3); border: 1px solid var(--border); border-radius: 4px; padding: 16px; margin-bottom: 20px; }
.queue-match-row { display: flex; justify-content: space-between; align-items: center; padding: 6px 0; font-size: 13px; }
.queue-match-row:not(:last-child) { border-bottom: 1px solid var(--border); }
.queue-match-row .label { color: var(--text-muted); }
.queue-password { display: flex; align-items: center; gap: 8px; }
.queue-password code { font-family: var(--font-mono); background: rgba(0,0,0,0.5); padding: 3px 10px; border-radius: 4px; font-size: 13px; color: var(--text-primary); letter-spacing: 1px; }

.match-status-badge { font-family: var(--font-display); font-size: 11px; font-weight: 600; text-transform: uppercase; padding: 2px 10px; border-radius: 4px; letter-spacing: 0.5px; border: 1px solid; }
.match-status-badge.assigned { background: rgba(0, 224, 255, 0.06); color: var(--accent); border-color: var(--border-accent); }
.match-status-badge.connecting { background: rgba(251, 191, 36, 0.06); color: var(--warning); border-color: rgba(251, 191, 36, 0.2); }
.match-status-badge.racing { background: rgba(52, 211, 153, 0.06); color: var(--success); border-color: rgba(52, 211, 153, 0.2); }


.queue-match-step { color: var(--text-muted); font-family: var(--font-display); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 4px; }
.queue-match-hint { color: var(--text-muted); font-size: 12px; margin-top: 4px; margin-bottom: 12px; }
.queue-match-warning { color: var(--text-muted); font-size: 12px; font-style: italic; }

/* --- Queue Season Banner --- */
.queue-season-banner { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; padding: 10px 16px; background: var(--bg-panel); border-left: 3px solid var(--accent); border-radius: 4px; }
.queue-season-banner .season-name { font-family: var(--font-display); font-size: 15px; font-weight: 700; color: var(--accent); }
.queue-season-banner .season-since { font-size: 12px; color: var(--text-muted); }

/* --- Queue Estimated Wait --- */
.queue-est-wait { color: var(--text-muted); font-size: 12px; margin-bottom: 16px; font-style: italic; }

/* --- Queue Recent Matches --- */
.queue-recent { max-width: 560px; margin: 24px auto 0; }
.queue-recent h3 { font-family: var(--font-display); font-size: 13px; font-weight: 600; color: var(--text-tertiary); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 10px; }
.recent-match-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 12px; background: var(--bg-panel); border-radius: 4px; margin-bottom: 4px; font-size: 13px; line-height: 1.3; }
.recent-match-row a { color: var(--text-primary); text-decoration: none; }
.recent-match-row a:hover { color: var(--accent); }
.recent-players { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vs-small { color: var(--text-muted); font-size: 11px; margin: 0 4px; }
.recent-result { color: var(--success); font-family: var(--font-display); font-size: 12px; font-weight: 600; white-space: nowrap; }
.recent-time { color: var(--text-muted); font-size: 11px; white-space: nowrap; }

/* --- Queue Match Result --- */
.queue-result-card { background: var(--bg-panel);  border: none; border-radius: 5px; padding: 32px; text-align: center; max-width: 480px; margin: 0 auto; }
.result-banner { font-family: var(--font-display); font-size: 24px; font-weight: 700; margin: 16px 0; padding: 12px; border-radius: 4px; border: 1px solid; text-transform: uppercase; letter-spacing: 2px; }
.result-banner.win { background: rgba(52, 211, 153, 0.08); color: var(--success); border-color: rgba(52, 211, 153, 0.2); }
.result-banner.loss { background: rgba(248, 113, 113, 0.08); color: var(--danger); border-color: rgba(248, 113, 113, 0.2); }
.result-banner.draw { background: rgba(107, 114, 128, 0.08); color: var(--text-tertiary); border-color: rgba(107, 114, 128, 0.15); }
.result-details { text-align: left; margin: 20px 0; line-height: 2; }
.result-actions { display: flex; gap: 12px; justify-content: center; margin-top: 20px; }

/* --- My Profile: Welcome Card --- */
/* --- Phase 5 / Task 5.4 — first-login onboarding card ---
   Four-step welcome card on /me. Shows on first /me visit + for 7 days
   after first login if not yet dismissed (then hidden permanently via
   players.onboarding_dismissed_at). The outer .glass-panel + cyan accent
   matches the public-page design tokens; the optional-tag pill is muted
   because Discord linking is a UX convenience, not a queueing gate. */
.onboarding-card { padding: 24px; margin: 0 0 24px 0; border-left: 3px solid var(--accent); }
.onboarding-card-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 16px; gap: 12px; }
.onboarding-card-header h3 { font-family: var(--font-display); color: var(--accent); font-size: 18px; margin: 0; }
.onboarding-dismiss-form { margin: 0; }
.onboarding-dismiss-btn { background: transparent; border: none; color: var(--text-muted); font-size: 22px; line-height: 1; cursor: pointer; padding: 0 6px; border-radius: 4px; transition: color 0.15s, background 0.15s; }
.onboarding-dismiss-btn:hover { color: var(--text-primary); background: rgba(255,255,255,0.04); }
.onboarding-steps { list-style: decimal inside; padding: 0; margin: 0; counter-reset: onboarding-step; display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 16px; }
.onboarding-steps li { list-style: none; counter-increment: onboarding-step; padding: 16px; background: rgba(255,255,255,0.02); border-radius: 4px; position: relative; }
.onboarding-steps li::before { content: counter(onboarding-step); position: absolute; top: 12px; right: 12px; font-family: var(--font-display); font-size: 24px; font-weight: 700; color: var(--accent); opacity: 0.25; }
.onboarding-steps li strong { font-family: var(--font-display); color: var(--text-primary); display: block; margin-bottom: 6px; }
.onboarding-steps li p { color: var(--text-secondary); font-size: 13px; margin: 0 0 10px 0; line-height: 1.5; }
.onboarding-step-optional strong { color: var(--text-secondary); }
.onboarding-step-optional-tag { display: inline-block; background: rgba(255,255,255,0.06); color: var(--text-muted); font-size: 10px; font-weight: 600; padding: 2px 6px; border-radius: 3px; margin-left: 6px; text-transform: uppercase; letter-spacing: 0.5px; }
.onboarding-cta { color: var(--accent); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; }
.onboarding-cta-done { color: #8aff8a; cursor: default; }

/* 2026-06-08 — merged the duplicate .welcome-card (was re-declared ~5547 with
   max-width:860px + margin:2rem auto + padding:2rem winning via cascade; those
   later values folded in here and the duplicate base deleted — computed result
   unchanged; the second block's h2/.welcome-sub/.welcome-modes children stay). */
.welcome-card { background: var(--bg-panel);  border: none; border-radius: 5px; text-align: center; max-width: 860px; margin: 2rem auto; padding: 2rem; }
.welcome-card h3 { font-family: var(--font-display); color: var(--accent); font-size: 20px; margin-bottom: 8px; }
.welcome-card p { color: var(--text-secondary); margin-bottom: 20px; }
.welcome-actions { display: flex; gap: 12px; justify-content: center; }
/* `.public-shell a { color: var(--link) }` wins on specificity over `.welcome-btn`
   (0,1,1 vs 0,1,0), which made the primary button's text render in the accent
   color against its accent background — invisible. Prefix with .public-shell to
   tie and let the later rule's color stick. */
.public-shell .welcome-btn { font-family: var(--font-display); display: inline-block; background: var(--accent); color: #000; padding: 10px 24px; border-radius: 4px; font-weight: 700; text-decoration: none; transition: background 0.15s; text-transform: uppercase; letter-spacing: 0.5px; }
.public-shell .welcome-btn:hover { background: var(--accent-hover); color: #000; }
.public-shell .welcome-btn-alt { background: transparent; border: 1px solid var(--accent); color: var(--accent); }
.public-shell .welcome-btn-alt:hover { background: var(--accent-dim); color: var(--accent); }

/* --- Discord Linking Section --- */
.discord-section { background: var(--bg-panel);  border: none; border-radius: 5px; padding: 24px; margin: 24px 0; }
.discord-section .section-title { margin-top: 0; }
.discord-prompt { color: var(--text-secondary); margin-bottom: 16px; }
.discord-link-btn { font-family: var(--font-display); display: inline-block; background: transparent; color: #8b9bf7; border: 1px solid rgba(88, 101, 242, 0.3); padding: 10px 24px; border-radius: 4px; font-weight: 600; text-decoration: none; transition: all 0.15s; text-transform: uppercase; letter-spacing: 0.5px; }
.discord-link-btn:hover { background: rgba(88, 101, 242, 0.1); border-color: #5865F2; }
.discord-guide-link { display: inline-block; margin-left: 16px; color: var(--text-tertiary); text-decoration: underline; font-size: 13px; }
.discord-guide-link:hover { color: var(--text-secondary); }
.discord-linked-badge { display: inline-flex; align-items: center; gap: 8px; background: rgba(88, 101, 242, 0.08); border: 1px solid rgba(88, 101, 242, 0.2); color: #8b9bf7; padding: 8px 16px; border-radius: 4px; font-size: 14px; }
.discord-icon { font-size: 16px; }
.discord-id { color: var(--text-tertiary); font-size: 12px; }
.discord-success { background: rgba(52, 211, 153, 0.06); border: 1px solid rgba(52, 211, 153, 0.15); color: var(--success); padding: 10px 16px; border-radius: 4px; margin-bottom: 16px; font-size: 14px; }
.discord-error { background: rgba(248, 113, 113, 0.06); border: 1px solid rgba(248, 113, 113, 0.15); color: var(--danger); padding: 10px 16px; border-radius: 4px; margin-bottom: 16px; font-size: 14px; }

/* --- Link Guide Page --- */
.link-intro { color: var(--text-secondary); margin-bottom: 24px; font-size: 15px; }
.link-methods { display: flex; flex-direction: column; gap: 16px; }
.link-method-card { background: var(--bg-panel);  border: none; border-radius: 5px; padding: 24px; }
.link-method-card h3 { font-family: var(--font-display); color: var(--text-primary); font-size: 17px; margin-bottom: 16px; }
.link-recommended { font-family: var(--font-display); display: inline-block; background: var(--accent); color: #000; font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 4px; margin-left: 8px; vertical-align: middle; text-transform: uppercase; }
.link-steps { color: var(--text-secondary); padding-left: 20px; margin-bottom: 12px; line-height: 1.8; }
.link-steps code { font-family: var(--font-mono); background: rgba(0,0,0,0.3); padding: 2px 6px; border-radius: 3px; font-size: 13px; color: var(--accent); }
.link-step-action { color: var(--accent); text-decoration: underline; }
.link-step-action:hover { color: var(--accent-hover); }
.link-note { color: var(--text-tertiary); font-size: 13px; font-style: italic; }

/* Wave 5 sub-theme 5.7 (2026-05-06) — colored "pending publication"
   indicator banner on Privacy / Terms when the active legal text is
   still the placeholder seed. Amber-warning palette so it reads as
   "this is a known incomplete state" not "scary error". */
.legal-placeholder-banner {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0 0 1.25rem;
    padding: 12px 16px;
    border-radius: 4px;
    background: rgba(255, 179, 71, 0.08);
    border: 1px solid rgba(255, 179, 71, 0.3);
    color: var(--warning);
    font-size: var(--text-sm);
}
.legal-placeholder-icon {
    font-size: 18px;
    line-height: 1;
}
.legal-placeholder-text {
    font-family: var(--font-display);
    font-weight: 600;
    letter-spacing: 0.3px;
}

/* Wave 5 sub-theme 5.8 (2026-05-06) — Account & Privacy section on /me.
   Two-row card: a grid of helper links (Privacy / Terms / Notifications
   / Export) on top, then a danger row with the typed-confirm self-serve
   erasure trigger. */
.account-privacy-card {
    padding: 20px;
    margin-top: 12px;
}
.account-privacy-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 8px 16px;
    padding-bottom: 16px;
    border-bottom: 1px dashed var(--border);
    margin-bottom: 16px;
}
.account-privacy-link {
    color: var(--accent) !important;
    font-family: var(--font-display);
    font-size: var(--text-sm);
    padding: 6px 0;
    text-decoration: none;
    border-bottom: 1px dashed transparent;
    transition: border-color 0.15s;
}
.account-privacy-link:hover { border-bottom-color: var(--accent); }
.account-privacy-danger {
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.account-privacy-danger > div:first-child { color: var(--text-secondary); }
.account-privacy-danger strong {
    color: var(--danger);
    display: block;
    margin-bottom: 4px;
    font-family: var(--font-display);
    font-size: var(--text-md);
}
.account-privacy-help { color: var(--text-muted); font-size: var(--text-sm); line-height: 1.5; }
.account-privacy-confirm {
    background: rgba(255, 107, 107, 0.05);
    border: 1px solid rgba(255, 107, 107, 0.3);
    border-radius: 4px;
    padding: 14px 16px;
}
.account-privacy-confirm p { margin: 0 0 10px; color: var(--text-primary); font-size: var(--text-sm); }
.account-privacy-confirm strong { color: var(--accent); display: inline; margin: 0; font-size: inherit; }
.account-privacy-input {
    width: 100%;
    background: var(--bg-input);
    border: 1px solid var(--border-hover);
    border-radius: 4px;
    padding: 8px 12px;
    font-family: var(--font-mono, monospace);
    color: var(--text-primary);
    font-size: var(--text-sm);
    margin-bottom: 8px;
}
.account-privacy-buttons { display: flex; gap: 8px; justify-content: flex-end; }
.account-privacy-error {
    color: var(--danger);
    font-size: var(--text-sm);
    margin-bottom: 8px;
}
.account-privacy-success {
    background: rgba(138, 255, 138, 0.08);
    border: 1px solid rgba(138, 255, 138, 0.3);
    border-radius: 4px;
    padding: 12px 16px;
    color: var(--success);
    font-family: var(--font-display);
    font-weight: 600;
}
.btn.btn-danger {
    background: rgba(255, 107, 107, 0.12);
    border: 1px solid rgba(255, 107, 107, 0.4);
    color: var(--danger);
}
.btn.btn-danger:hover:not(:disabled) {
    background: rgba(255, 107, 107, 0.2);
    border-color: var(--danger);
}
.btn.btn-danger:disabled { opacity: 0.4; cursor: not-allowed; }

/* Wave 5 sub-theme 5.10 (2026-05-06) — Help page Table of Contents.
   Sits below the page subtitle, above the first section. Compact list
   of #anchor jumps so readers can scan to a question without scrolling
   past every section. */
.help-toc {
    margin: 0 0 28px;
    padding: 16px 20px;
    border: 1px solid var(--border);
    border-left: 3px solid var(--accent);
    border-radius: 4px;
    background: rgba(0, 224, 255, 0.04);
}
.help-toc-title {
    font-family: var(--font-display);
    font-size: var(--text-sm);
    font-weight: 700;
    color: var(--text-tertiary);
    text-transform: uppercase;
    letter-spacing: 1px;
    margin: 0 0 10px;
}
.help-toc ul {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 4px 16px;
}
.help-toc li { padding: 0; }
.help-toc a {
    display: block;
    padding: 4px 0;
    font-size: var(--text-sm);
    color: var(--text-secondary);
    text-decoration: none;
    border-bottom: 1px dashed transparent;
    transition: border-color 0.15s, color 0.15s;
}
.help-toc a:hover {
    color: var(--accent);
    border-bottom-color: var(--accent);
}
/* :target highlight on the landed-on section */
.guide-section:target {
    scroll-margin-top: 80px;
    background: rgba(0, 224, 255, 0.04);
    border-radius: 4px;
    padding: 8px;
    margin-left: -8px;
    margin-right: -8px;
}

/* --- How to Play / Guide (legacy base styles, still used by Privacy/Terms) --- */
.guide-page { max-width: 800px; margin: 0 auto; }
.guide-section { margin-bottom: 32px; }
.guide-section h2 { font-family: var(--font-display); font-size: 18px; margin-bottom: 12px; color: var(--text-primary); border-bottom: 1px solid var(--border); padding-bottom: 8px; text-transform: uppercase; letter-spacing: 0.5px; }
.guide-section ol, .guide-section ul { padding-left: 24px; line-height: 1.8; }
.guide-section li { margin-bottom: 4px; }
.guide-section code { font-family: var(--font-mono); background: rgba(0,0,0,0.3); padding: 2px 6px; border-radius: 4px; font-size: 13px; }
/* 2026-06-08 — was UNDEFINED: legal "Last updated"/subtitle lines (Help, Privacy,
   Terms) rendered at full-weight body size. Mutes + tightens to subtitle scale,
   pulling up under the page title. */
.guide-subtitle { color: var(--text-muted); font-size: 14px; margin: -8px 0 20px; line-height: 1.5; }
/* 2026-06-08 — standalone base for bare .help-text usages (Banned / Appeal /
   OperatorApply) which sit OUTSIDE .form-group, so the scoped admin.css rule
   never applied and they rendered at default size. The .form-group .help-text
   scoped rule stays in admin.css for form contexts. */
.help-text { font-size: 12px; color: var(--text-muted); }
.guide-table { width: 100%; border-collapse: collapse; }
.guide-table td { padding: 8px 12px; border-bottom: 1px solid var(--border); }
.guide-table td:first-child { white-space: nowrap; width: 160px; font-family: var(--font-mono); color: var(--accent); }
.tier-list { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 12px; }

/* =============================================================
   HOW TO PLAY — redesigned card-based guide (replaces .guide-*)
   Each section is a glass-panel card with a display-font header,
   a muted subtitle, and numbered-step content. Mode-specific
   sections (Matchmaking / Time Attack / KOTH) get a left accent
   bar in their mode color so the page scans at a glance.
   ============================================================= */

.htp-hero {
    text-align: center;
    padding: 2.5rem 1rem 1.75rem;
    margin-bottom: 1.25rem;
}
.htp-title {
    font-family: var(--font-display);
    font-size: var(--text-hero);
    font-weight: 700;
    letter-spacing: 3px;
    text-transform: uppercase;
    color: var(--accent);
    text-shadow: 0 0 40px rgba(0, 224, 255, 0.35);
    line-height: 1.1;
    margin: 0;
}
.htp-subtitle {
    color: var(--text-secondary);
    font-size: var(--text-md);
    margin: 0.6rem auto 0;
    max-width: 600px;
    letter-spacing: 0.3px;
}

/* Base section card — one per section */
.htp-card {
    max-width: var(--home-content-width);
    margin: 0 auto 1.5rem;
    padding: 1.75rem 2rem;
    background: var(--bg-panel);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: 6px;
    display: block;
}

/* Mode-accent variants — left border bar in the mode color */
.htp-card-mm { border-left: 3px solid var(--accent); }
.htp-card-ta { border-left: 3px solid var(--accent-purple); }
.htp-card-fr { border-left: 3px solid #ffb86b; }

.htp-section-head {
    margin-bottom: 1.25rem;
}
.htp-section-title {
    font-family: var(--font-display);
    font-size: var(--text-xl);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 1.5px;
    color: var(--text-primary);
    margin: 0 0 0.3rem;
    line-height: 1.2;
}
.htp-title-mm { color: var(--accent); }
.htp-title-ta { color: var(--accent-purple); }
.htp-title-fr { color: #ffb86b; }

.htp-section-sub {
    color: var(--text-secondary);
    font-size: var(--text-base);
    margin: 0;
    line-height: 1.5;
    max-width: 680px;
}
.htp-section-sub strong { color: var(--text-primary); font-weight: 600; }

.htp-section-body {
    color: var(--text-secondary);
    font-size: var(--text-base);
    line-height: 1.7;
}
.htp-section-body p {
    margin: 0 0 0.9rem;
}
.htp-section-body p:last-child { margin-bottom: 0; }
.htp-section-body a {
    color: var(--accent);
    border-bottom: 1px dashed transparent;
    transition: border-color 0.12s;
}
.htp-section-body a:hover {
    color: var(--accent-hover);
    border-bottom-color: var(--accent-hover);
}

/* Small inline mode pill for the "What is KOTT?" intro paragraph */
.htp-pill {
    display: inline-block;
    font-family: var(--font-display);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    padding: 2px 8px;
    border-radius: 3px;
    border: 1px solid;
    vertical-align: baseline;
}
.htp-pill-mm { color: var(--accent); border-color: var(--border-accent-strong); background: var(--accent-dim); }
.htp-pill-ta { color: var(--accent-purple); border-color: rgba(180, 156, 255, 0.35); background: rgba(180, 156, 255, 0.08); }
.htp-pill-fr { color: #ffb86b; border-color: rgba(255, 184, 107, 0.35); background: rgba(255, 184, 107, 0.08); }

/* Mode badge at the top of the section head — louder than .htp-pill */
.htp-mode-badge {
    display: inline-block;
    font-family: var(--font-display);
    font-size: var(--text-xs);
    font-weight: 700;
    letter-spacing: 2px;
    text-transform: uppercase;
    padding: 3px 10px;
    border-radius: 3px;
    margin-bottom: 0.6rem;
}
.htp-mode-badge.mm { background: var(--accent-dim); color: var(--accent); }
.htp-mode-badge.ta { background: rgba(180, 156, 255, 0.15); color: var(--accent-purple); }
.htp-mode-badge.fr { background: rgba(255, 184, 107, 0.14); color: #ffb86b; }
/* Wave 5 sub-theme 5.10 (2026-05-06) — htp-pill rendered as <a> anchors;
   the cursor + decoration cues need to read as clickable. Smooth-scroll
   hint via :target highlight on the section landed-on. */
a.htp-pill {
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.15s, transform 0.05s;
}
a.htp-pill:hover { transform: translateY(-1px); }
a.htp-pill-mm:hover { background: rgba(0, 224, 255, 0.18); color: var(--accent-hover); }
a.htp-pill-ta:hover { background: rgba(180, 156, 255, 0.16); }
a.htp-pill-fr:hover { background: rgba(255, 184, 107, 0.16); }
.htp-card:target {
    outline: 2px solid rgba(0, 224, 255, 0.3);
    outline-offset: 4px;
    scroll-margin-top: 80px;
}
/* Wave 5 sub-theme 5.2 — "← Start here" tag inside the recommended-mode
   badge (Time Attack). Pairs with .home-mode-card-recommended on Home. */
.htp-mode-recommended {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 6px;
    border-radius: 3px;
    background: rgba(180, 156, 255, 0.25);
    color: var(--accent-purple);
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    vertical-align: middle;
}

/* Requirements list: numbered circle + name + detail (mirrors Home pattern) */
.htp-req-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
}
.htp-req-list > li {
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
    padding: 12px 14px;
    background: rgba(0, 224, 255, 0.02);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 5px;
}
.htp-req-num {
    flex-shrink: 0;
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--accent-dim);
    color: var(--accent);
    border: 1px solid var(--border-accent-strong);
    border-radius: 50%;
    font-family: var(--font-display);
    font-size: var(--text-sm);
    font-weight: 700;
}
.htp-req-name {
    display: block;
    font-family: var(--font-display);
    font-size: var(--text-base);
    font-weight: 700;
    letter-spacing: 0.5px;
    color: var(--text-primary) !important;
    line-height: 1.2;
    margin-bottom: 2px;
    border-bottom: none !important;
}
.htp-req-name:hover { color: var(--accent) !important; }
.htp-req-detail {
    font-size: var(--text-sm);
    color: var(--text-secondary);
    line-height: 1.4;
}

/* Numbered step list — used for Getting Started + Matchmaking + KOTH */
.htp-steps {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.htp-steps > li {
    display: flex;
    gap: 1rem;
    align-items: flex-start;
}
.htp-step-num {
    flex-shrink: 0;
    width: 32px;
    height: 32px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--accent-dim);
    color: var(--accent);
    border: 1px solid var(--border-accent-strong);
    border-radius: 50%;
    font-family: var(--font-display);
    font-size: var(--text-base);
    font-weight: 700;
    margin-top: 2px;
}
.htp-step-num.mm { background: var(--accent-dim); color: var(--accent); border-color: var(--border-accent-strong); }
.htp-step-num.ta { background: rgba(180, 156, 255, 0.12); color: var(--accent-purple); border-color: rgba(180, 156, 255, 0.4); }
.htp-step-num.fr { background: rgba(255, 184, 107, 0.12); color: #ffb86b; border-color: rgba(255, 184, 107, 0.4); }

.htp-step-body {
    flex: 1;
    min-width: 0;
}
.htp-step-body strong {
    display: block;
    font-family: var(--font-display);
    font-size: var(--text-base);
    font-weight: 700;
    color: var(--text-primary);
    letter-spacing: 0.3px;
    margin-bottom: 3px;
}
.htp-step-body p {
    color: var(--text-secondary);
    font-size: var(--text-base);
    line-height: 1.55;
    margin: 0;
}

/* Plain bullet list (Time Attack) */
.htp-bullets {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.htp-bullets > li {
    position: relative;
    padding: 10px 14px 10px 28px;
    background: rgba(255, 255, 255, 0.02);
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: 4px;
    color: var(--text-secondary);
    line-height: 1.55;
}
.htp-bullets > li::before {
    content: "";
    position: absolute;
    left: 12px;
    top: 18px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--accent-purple);
}

/* <kbd> styling — pill with 3D-ish shading */
.htp-section-body kbd,
.htp-key-combo kbd {
    display: inline-block;
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 600;
    padding: 2px 8px;
    min-width: 20px;
    text-align: center;
    color: var(--text-primary);
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-bottom-width: 2px;
    border-radius: 4px;
    line-height: 1.4;
    vertical-align: baseline;
}

/* <code> inline — softer chip */
.htp-section-body code {
    font-family: var(--font-mono);
    font-size: 13px;
    background: rgba(0, 0, 0, 0.35);
    color: var(--accent);
    padding: 2px 7px;
    border-radius: 3px;
    border: 1px solid rgba(0, 224, 255, 0.15);
}

/* Collapsed reference lists (keybinds, tier ladder) — native <details>,
   no JS. Content dial-back 2026-07-09. */
.htp-details > summary {
    cursor: pointer;
    list-style: none;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-family: var(--font-display);
    font-size: var(--text-sm);
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: var(--accent);
    padding: 6px 0;
    user-select: none;
}
.htp-details > summary::-webkit-details-marker { display: none; }
.htp-details > summary::before {
    content: "▸";
    font-size: 11px;
    transition: transform 0.15s ease;
}
.htp-details[open] > summary::before { transform: rotate(90deg); }
.htp-details > summary:hover { color: var(--accent-hover); }
.htp-details > .htp-keys,
.htp-details > .htp-tier-ladder { margin-top: 0.75rem; }

/* Tier ladder — compact grid with range on the right */
.htp-tier-ladder {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 8px;
    margin-top: 1rem;
}
.htp-tier-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 8px 12px;
    background: rgba(255, 255, 255, 0.02);
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: 4px;
}
.htp-tier-range {
    font-family: var(--font-mono);
    font-size: var(--text-sm);
    color: var(--text-tertiary);
}

/* Keybind rows — replaces .guide-table for keybinds */
.htp-keys {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.htp-key-row {
    display: grid;
    grid-template-columns: 160px 1fr auto;
    align-items: center;
    gap: 1rem;
    padding: 8px 14px;
    background: rgba(255, 255, 255, 0.02);
    border: 1px solid rgba(255, 255, 255, 0.05);
    border-radius: 4px;
}
.htp-key-combo {
    display: flex;
    align-items: center;
    gap: 4px;
    flex-wrap: wrap;
}
.htp-key-or {
    color: var(--text-muted);
    margin: 0 2px;
}
.htp-key-action {
    color: var(--text-primary);
    font-size: var(--text-base);
}
.htp-key-mode {
    font-family: var(--font-display);
    font-size: var(--text-xs);
    letter-spacing: 0.5px;
    color: var(--text-tertiary);
    text-transform: uppercase;
    white-space: nowrap;
}

/* Discord one-liner (replaced the bot-command reference table 2026-07-09) */
.htp-discord-line {
    margin: 0;
    color: var(--text-secondary);
    line-height: 1.55;
}
.htp-discord-line a { color: var(--accent); }
.htp-discord-line a:hover { color: var(--accent-hover); }

/* Responsive */
@media (max-width: 720px) {
    .htp-title { font-size: 2rem; letter-spacing: 2px; }
    .htp-card { padding: 1.25rem 1rem; }
    .htp-req-list { grid-template-columns: 1fr; }
    .htp-key-row { grid-template-columns: 1fr; gap: 4px; }
    .htp-key-mode { grid-column: 1; text-align: left; }
}

/* --- Responsive --- */
@media (max-width: 768px) {
    .topnav-links { display: none; }
    .topnav-search { display: none; }
    .topnav-toggle { display: block; margin-left: auto; }
    .topnav-mobile { display: flex; flex-direction: column; padding: 8px 12px; border-top: 1px solid var(--border); }
    .topnav-mobile a { font-family: var(--font-display); color: var(--text-tertiary); padding: 12px 16px; font-size: 14px; font-weight: 600; border-radius: 4px; min-height: 44px; display: flex; align-items: center; text-transform: uppercase; letter-spacing: 0.5px; }
    .topnav-mobile a:hover { background: var(--bg-hover); color: var(--text-primary); }
    .topnav-mobile a.active { color: var(--accent); }

    .btn { min-height: 44px; min-width: 44px; padding: 12px 16px; font-size: 14px; }
    .auth-btn { min-height: 44px; padding: 10px 16px; }

    .public-content { padding: 16px 12px; }
    .profile-header { flex-direction: column; text-align: center; padding: 20px; }
    .profile-meta { justify-content: center; }
    .stats-grid { grid-template-columns: repeat(2, 1fr); }
    .server-grid { grid-template-columns: 1fr; }
    .pub-table { font-size: 12px; }
    .pub-table th, .pub-table td { padding: 5px 10px; }
    .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
    /* The desktop sticky thead (position: sticky; top: 56px) is trapped by the
       overflow container above on mobile, mis-pinning the header so the first row
       clips behind it. Reset to static on mobile — header scrolls normally. */
    .pub-table thead { position: static; }
    .leaderboard-podium { flex-direction: column; align-items: center; }
    .podium-card { flex: 0 0 auto; width: 100%; max-width: 300px; }
    .podium-1, .podium-2, .podium-3 { order: unset !important; }
    .topnav-auth { display: none; }
    .queue-join-buttons { flex-direction: column; }
    .queue-status-bar { flex-direction: column; }
    .queue-match-players { flex-direction: column; gap: 6px; }
}

@media (max-width: 480px) {
    .stats-grid { grid-template-columns: 1fr 1fr; gap: 8px; }
    .stat-card { padding: 12px 14px; }
    .stat-card .stat-value { font-size: 18px; }
    .pub-table .col-hide-xs { display: none; }
    /* 2026-07-09 mobile pass — the nowrap+overflow override made the track
       pill row run off the right edge with no visible scroll affordance;
       the base flex-wrap: wrap now applies at every width. */
}

/* --- Reduced Motion --- */
@media (prefers-reduced-motion: reduce) {
    .queue-searching-anim .dot { animation: none; opacity: 1; }
    .spinner, .pub-loading .spinner { animation: none; }
    .refresh-dot { animation: none; }
}

/* --- Kill all panel borders (override) --- */
/* 2026-06-08 — .server-card removed from this list: its role borders are
   meaningful (green = online, cyan = KOTH, purple = Time Attack) and this
   blanket override was wiping them. The rule still flattens the other static
   panels as intended. */
.podium-card, .stat-card, .queue-stat, .queue-card,
.profile-header, .profile-avatar, .welcome-card, .discord-section,
.link-method-card, .queue-result-card, .pub-empty { border: none !important; }

/* --- Match Detail & Records --- */
.breadcrumb-link { color: var(--text-muted); text-decoration: none; margin-right: 12px; font-size: 0.85rem; }
.breadcrumb-link:hover { color: var(--accent); }

/* .stats-grid duplicate removed 2026-06-08 — merged into the canonical rule in
   the Stats Grid block (auto-fill/160px + margin folded in). */
.stat-value-sm { font-size: 0.85rem; }

.clickable-row { cursor: pointer; transition: background 0.15s; }
.clickable-row:hover { background: rgba(0, 224, 255, 0.04); }

/* Wave 6 a11y (2026-05-06) — round-header is now a <button>; reset native
   button chrome (border, default text alignment, font inheritance) so the
   visual treatment is unchanged from the prior <div>. width:100% keeps the
   row spanning the full container the way the div did. */
.round-header { padding: 10px 16px; margin: 16px 0 8px; background: var(--bg-elevated); border: none; color: inherit; font-family: inherit; font-size: inherit; text-align: left; width: 100%; border-radius: 4px; cursor: pointer; display: flex; align-items: center; gap: 10px; font-weight: 600; }
.round-header:hover { background: rgba(12, 18, 26, 0.9); }
.round-toggle { font-size: 0.7rem; color: var(--accent); }
.round-winner { color: var(--accent); font-weight: 600; }

.events-section { margin: 16px 0; }
.events-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; font-weight: 600; }
.event-filters { display: flex; gap: 4px; }

.events-timeline { background: var(--bg-elevated); border-radius: 4px; padding: 8px; max-height: 400px; overflow-y: auto; }
/* line-height 1.3: this list lives in a fixed 400px max-height scroller, so prose leading cost
   real rows — and it also caps .event-badge, which at 1.6 was nearly as tall as the row itself. */
.event-row { display: flex; align-items: center; gap: 10px; padding: 4px 8px; border-bottom: 1px solid rgba(255,255,255,0.04); font-size: 0.82rem; line-height: 1.3; }
.event-row:last-child { border-bottom: none; }
.event-time { min-width: 52px; color: var(--text-muted); font-variant-numeric: tabular-nums; }
.event-badge { padding: 1px 6px; border-radius: 3px; font-size: 0.72rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }
.badge-checkpoint { background: rgba(0, 224, 255, 0.12); color: var(--accent); }
.badge-collision { background: rgba(239, 68, 68, 0.15); color: #ef4444; }
.badge-offtrack { background: rgba(245, 158, 11, 0.15); color: #f59e0b; }
.badge-lead { background: rgba(34, 197, 94, 0.12); color: #22c55e; }
.event-player { color: var(--text-primary); font-weight: 500; }
.event-detail { color: var(--text-muted); }

.record-time { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--accent); }

/* ── Recent Laps table styling (used on MyProfile + PlayerProfile) ── */
.lap-pb-badge {
    display: inline-block; margin-left: 6px; padding: 1px 6px;
    font-family: var(--font-display); font-size: 10px; font-weight: 700;
    letter-spacing: 0.5px; text-transform: uppercase;
    color: var(--tier-champion); border: 1px solid var(--tier-champion);
    border-radius: 3px; vertical-align: middle;
}
.lap-invalid {
    color: var(--text-muted); text-decoration: line-through;
    font-variant-numeric: tabular-nums; font-weight: 500;
}
.lap-detail-link {
    font-size: 12px; color: var(--accent); text-decoration: none;
    padding: 2px 8px; border: 1px solid rgba(0, 224, 255, 0.3);
    border-radius: 3px; transition: background 120ms;
}
.lap-detail-link:hover { background: rgba(0, 224, 255, 0.1); }

/* ── Admin lap moderation bar (admin-only, /laps/{id}) ── */
.lap-admin-bar {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    margin-bottom: 16px; padding: 10px 14px;
    border: 1px solid var(--danger-border, rgba(248, 113, 113, 0.25));
    border-radius: 4px; background: var(--danger-dim, rgba(248, 113, 113, 0.06));
}
.lap-admin-bar-label {
    font-family: var(--font-display); font-weight: 700; font-size: 11px;
    letter-spacing: 1px; text-transform: uppercase; color: var(--danger, #f87171);
}
.lap-admin-reason {
    flex: 1 1 200px; min-width: 160px; padding: 6px 10px;
    background: rgba(255, 255, 255, 0.04); border: 1px solid var(--border);
    border-radius: 4px; color: var(--text-primary); font-size: 13px;
}
.lap-admin-current { color: var(--danger, #f87171); font-size: 13px; }
.lap-admin-status { color: var(--accent, #00e0ff); font-size: 13px; }

/* ── Rating History Chart ── */
.rating-chart {
    display: flex;
    align-items: flex-end;
    gap: 2px;
    height: 80px;
    background: var(--bg-elevated);
    border-radius: 4px;
    padding: 8px 10px;
    margin-bottom: 8px;
}
.rating-bar {
    flex: 1;
    min-width: 3px;
    max-width: 12px;
    background: var(--accent);
    border-radius: 2px 2px 0 0;
    opacity: 0.8;
    transition: opacity 0.15s ease;
}
.rating-bar:hover { opacity: 1; }
.rating-bar:last-child { background: var(--accent-hover); opacity: 1; }

.rating-chart-meta {
    display: flex;
    gap: 20px;
    font-size: 12px;
    color: var(--text-secondary);
    flex-wrap: wrap;
}
.rating-chart-meta strong { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.rating-delta.positive { color: var(--success); }
.rating-delta.negative { color: var(--danger); }

/* ── Head-to-Head ── */
.h2h-section {
    background: var(--bg-panel);
    border-radius: 5px;
    padding: 16px 18px;
    margin-bottom: 24px;
}
.h2h-title {
    font-size: 13px;
    color: var(--text-secondary);
    margin-bottom: 8px;
}
.h2h-record {
    font-size: 18px;
    font-weight: 700;
    margin-bottom: 10px;
}
.h2h-record .h2h-wins { color: var(--success); }
.h2h-record .h2h-losses { color: var(--danger); }
.h2h-bar {
    display: flex;
    height: 6px;
    border-radius: 3px;
    overflow: hidden;
    background: var(--bg-elevated);
}
.h2h-bar-win {
    background: var(--success);
    transition: width 0.3s ease;
}
.h2h-bar-loss {
    background: var(--danger);
    transition: width 0.3s ease;
}

/* ── Car Stats ── */
.car-stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 10px;
    margin-bottom: 24px;
}
.car-stat-card {
    background: var(--bg-panel);
    border-radius: 5px;
    padding: 14px 16px;
}
.car-stat-name {
    font-size: 13px;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 6px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.car-stat-row {
    display: flex;
    justify-content: space-between;
    font-size: 12px;
    color: var(--text-secondary);
    margin-top: 3px;
}
.car-stat-row strong { color: var(--text-primary); font-variant-numeric: tabular-nums; }

/* ── Live Match Widget ── */
.live-widget {
    background: var(--bg-panel);
    border: 1px solid var(--border-accent);
    border-radius: 5px;
    padding: 12px 16px;
    margin-bottom: 16px;
}
.live-widget-idle {
    text-align: center;
    color: var(--text-muted);
    font-size: 13px;
    padding: 12px;
}
.live-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 8px;
    font-size: 11px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.live-elapsed { margin-left: auto; }
.live-indicator {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: #ef4444;
    font-weight: 700;
}
.live-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: #ef4444;
    animation: live-pulse 1.5s ease-in-out infinite;
}
@keyframes live-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.4; }
}
.live-round {
    color: var(--accent);
    font-weight: 600;
}
.live-elapsed {
    font-variant-numeric: tabular-nums;
}
.live-players {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 6px;
}
.live-player {
    display: flex;
    align-items: center;
    gap: 8px;
}
.live-player-dot {
    width: 10px;
    height: 10px;
    border-radius: 50%;
    flex-shrink: 0;
}
.live-player-dot.king {
    background: var(--accent);
    box-shadow: 0 0 6px var(--accent-glow);
}
.live-player-dot.challenger {
    background: var(--danger);
    box-shadow: 0 0 6px rgba(248, 113, 113, 0.3);
}
.live-player-name {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-primary);
}
.live-player.right { text-align: right; }
.live-vs {
    font-size: 12px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 1px;
    font-weight: 700;
}
.live-progress {
    position: relative;
    height: 16px;
    background: var(--bg-elevated);
    border-radius: 5px;
    overflow: hidden;
    margin-bottom: 6px;
}
.live-player-marker {
    position: absolute;
    top: 1px;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    transition: left 0.8s ease;
}
.live-marker-king {
    background: var(--accent);
    box-shadow: 0 0 6px var(--accent-glow);
}
.live-marker-challenger {
    background: var(--danger);
    box-shadow: 0 0 6px rgba(248, 113, 113, 0.3);
}
.live-stats {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 24px;
    font-size: 13px;
    color: var(--text-secondary);
}
.live-state-label {
    font-size: 13px;
}
.live-gap {
    font-size: 18px;
    font-weight: 700;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}
.live-state-badge {
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    padding: 2px 8px;
    border-radius: 3px;
    background: rgba(255,255,255,0.06);
    color: var(--text-muted);
}
.live-state-badge.waiting { background: rgba(255,255,255,0.06); color: var(--text-muted); }
.live-state-badge.warmup { background: rgba(251, 191, 36, 0.1); color: #fbbf24; }
.live-state-badge.countdown { background: rgba(0, 224, 255, 0.1); color: var(--accent); }
.live-state-badge.racing { background: rgba(52, 211, 153, 0.1); color: #34d399; }
.live-state-badge.round_result { background: rgba(0, 224, 255, 0.1); color: var(--accent); }
.live-state-badge.finished { background: rgba(255,255,255,0.06); color: var(--text-muted); }
.live-separation {
    margin-top: 2px;
}
.live-sep-header {
    display: flex;
    justify-content: space-between;
    font-size: 10px;
    color: var(--text-muted);
    margin-top: 3px;
}
.live-sep-label { text-transform: uppercase; letter-spacing: 0.5px; }
.live-sep-value { font-variant-numeric: tabular-nums; color: var(--text-secondary); }
.live-sep-value.warning { color: #fbbf24; }
.live-sep-value.danger { color: #ef4444; }
.live-sep-bar {
    height: 4px;
    background: var(--bg-elevated);
    border-radius: 2px;
    overflow: hidden;
}
.live-sep-fill {
    height: 100%;
    background: var(--accent);
    border-radius: 2px;
    transition: width 0.8s ease;
}
.live-sep-fill.warning { background: #fbbf24; }
.live-sep-fill.danger { background: #ef4444; animation: sep-pulse 0.8s ease-in-out infinite; }
@keyframes sep-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.6; }
}
.live-actions {
    display: flex;
    justify-content: flex-end;
    margin-top: 6px;
}

/* ── Page Controls (pagination) ── */
.page-controls {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 12px;
    margin-top: 16px;
    font-size: 13px;
    color: var(--text-secondary);
}
.page-controls .btn { min-width: 80px; }

@media (max-width: 480px) {
    .car-stats-grid { grid-template-columns: 1fr; }
    .live-player-name { font-size: 14px; }
    .live-gap { font-size: 15px; }
    .h2h-record { font-size: 15px; }
    .rating-chart { height: 60px; }
}

/* ===== HOME PAGE ===== */
.home-hero {
    text-align: center;
    padding: 2.25rem 1rem 1.25rem;
    margin-bottom: 1rem;
}
/* "KOTT" brand eyebrow above the hero title — muted vs the accent h1 so it reads as
   a brand tag, not a second title. padding-left offsets the wide tracking's trailing
   space so the word stays optically centered. */
.home-eyebrow {
    font-family: var(--font-display);
    font-size: 0.85rem;
    font-weight: 700;
    letter-spacing: 0.55em;
    padding-left: 0.55em;
    text-transform: uppercase;
    color: var(--text-secondary);
    margin: 0 0 0.5rem;
}
.home-title {
    font-family: var(--font-display);
    font-size: var(--text-hero);
    font-weight: 700;
    letter-spacing: 3px;
    text-transform: uppercase;
    color: var(--accent);
    text-shadow: 0 0 40px rgba(0, 224, 255, 0.35);
    line-height: 1.1;
}
.home-tagline {
    font-family: var(--font-body);
    color: var(--text-secondary);
    font-size: 1rem;
    margin-top: 0.6rem;
    letter-spacing: 0.5px;
}
/* Mode chips under the hero tagline — one word each, color-coded per mode */

/* Wave I (2026-05-12) F-803 — one-shot Discord-link success card on /me. */
.linked-success-card { display: flex; align-items: center; gap: 14px; padding: 14px 18px; margin: 0 0 20px; border-left: 3px solid var(--success); }
.linked-success-icon { display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; width: 28px; height: 28px; border-radius: 50%; background: rgba(138, 255, 138, 0.12); color: var(--success); font-weight: 700; font-size: 15px; }
.linked-success-body { display: flex; flex-direction: column; gap: 2px; font-size: 13px; color: var(--text-secondary); }
.linked-success-body strong { color: var(--text-primary); font-family: var(--font-display); font-size: 14px; }
.linked-success-body a { color: var(--accent); }
.linked-success-body a:hover { color: var(--accent-hover); }

/* Wave I (2026-05-12) F-806 — Privacy self-erase top callout. */
.privacy-erase-callout { background: var(--bg-elevated); border: 1px solid var(--border); border-left: 3px solid var(--accent); border-radius: 4px; padding: 14px 18px; margin: 0 0 24px; font-size: 14px; color: var(--text-secondary); line-height: 1.6; }
.privacy-erase-callout strong { color: var(--text-primary); margin-right: 4px; }
.privacy-erase-callout a { color: var(--accent); }
.privacy-erase-callout a:hover { color: var(--accent-hover); }

/* Wave I (2026-05-12) — small public-side utilities + F-804 telemetry link. */
.mb-lg { margin-bottom: 1.5rem; }
.th-rank-col { width: 60px; }
.view-telemetry-link { display: inline-block; margin-left: 8px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.4px; color: var(--accent); font-family: var(--font-display); }
.view-telemetry-link:hover { color: var(--accent-hover); }

/* Hero actions — dominant JOIN QUEUE + quiet secondary link */
.home-hero-actions {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.5rem;
    flex-wrap: wrap;
    margin-top: 0.25rem;
}
.home-hero-cta {
    display: inline-block;
    font-family: var(--font-display);
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 2px;
    text-transform: uppercase;
    padding: 14px 38px;
    border-radius: 4px;
    background: var(--accent);
    color: #000 !important;
    text-decoration: none;
    box-shadow: 0 0 24px rgba(0, 224, 255, 0.25);
    transition: all 0.18s ease;
}
.home-hero-cta:hover {
    background: var(--accent-hover);
    box-shadow: 0 0 40px rgba(0, 224, 255, 0.5);
    transform: translateY(-1px);
}
.home-hero-cta:focus-visible { outline: 2px solid var(--accent-hover); outline-offset: 3px; }
.home-hero-link {
    font-family: var(--font-display);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: var(--text-tertiary) !important;
    text-decoration: none;
    transition: color 0.15s;
}
.home-hero-link:hover { color: var(--accent) !important; }

.home-track-chip, .queue-track-chip {
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.12);
    padding: 2px 10px;
    border-radius: 6px;
    font-size: 12px;
    color: rgba(255,255,255,0.7);
}
.home-section-title {
    font-family: var(--font-display);
    font-size: var(--text-lg);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 0.75rem;
    padding: 0 1rem;
    max-width: var(--home-content-width);
    margin-left: auto;
    margin-right: auto;
}
.home-section-header { display: flex; align-items: baseline; justify-content: space-between; max-width: var(--home-content-width); margin: 0 auto; padding: 0 1rem; margin-bottom: 0.75rem; }
.home-section-header .home-section-title { margin-bottom: 0; padding: 0; }
.home-view-all { font-size: 12px; color: var(--accent); text-decoration: none; font-family: var(--font-display); font-weight: 600; letter-spacing: 0.5px; }
.home-view-all:hover { text-decoration: underline; }
.home-recent {
    max-width: var(--home-content-width);
    margin: 0 auto 1.5rem;
}
.home-recent-list { display: flex; flex-direction: column; gap: 0.5rem; padding: 0 1rem; }
.home-recent-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.75rem 1rem;
    text-decoration: none;
    color: inherit;
    transition: background 0.15s;
}
.home-recent-item:hover { background: var(--bg-hover); }
.home-recent-players { display: flex; align-items: center; gap: 0.5rem; }
.home-winner { color: var(--accent); font-weight: 600; }
.home-vs { font-size: var(--text-xs); color: var(--text-muted); text-transform: uppercase; }
.home-recent-meta { display: flex; gap: 0.75rem; font-size: var(--text-sm); color: var(--text-tertiary); }
/* ===== HOME: REQUIREMENTS PANEL ("Before you play") ===== */
/* Wave 5 sub-themes 5.1 + 5.9 (2026-05-06) — paired footer links on the
   Requirements section: full setup walkthrough on the left, "Already set
   up?" jump-to-modes anchor on the right. Wraps on narrow screens so the
   "skip" link doesn't push the walkthrough off-screen. */

/* Wave 5 sub-theme 5.1 (2026-05-06) — anonymous-visitor login CTA in the
   hero. Visible only when AuthState resolves to !IsLoggedIn. Sits between
   the mode chips and the Requirements panel so it dominates the viewport
   above the fold for first-time visitors. */

/* Wave 5 sub-theme 5.2 (2026-05-06) — recommended-mode marker (TA card).
   Pairs with .home-mode-card-featured to lift the canonical first-mode
   pick visually. */

/* ===== HOME: STATUS BAND (one-row season/prelaunch strip) ===== */
.home-status-band {
    max-width: var(--home-content-width);
    margin: 0 auto 1.5rem;
    padding: 14px 22px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    background: var(--bg-panel);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: 4px;
    flex-wrap: wrap;
}
.home-status-main {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    flex-wrap: wrap;
    flex: 1;
}
.home-status-label {
    font-family: var(--font-display);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    color: var(--accent);
    padding: 3px 10px;
    border-radius: 3px;
    background: var(--accent-dim);
    border: 1px solid var(--border-accent-strong);
    flex-shrink: 0;
}
.home-status-name {
    font-family: var(--font-display);
    font-size: 16px;
    font-weight: 600;
    color: var(--text-primary);
}
.home-status-text {
    color: var(--text-secondary);
    font-size: 13px;
}
.home-status-tracks {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
}
.home-status-cta {
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: var(--accent) !important;
    text-decoration: none;
    padding: 6px 14px;
    border: 1px solid var(--border-accent-strong);
    border-radius: 4px;
    transition: all 0.15s;
    flex-shrink: 0;
}
.home-status-cta:hover {
    background: var(--accent-dim);
    border-color: var(--accent);
}
@media (max-width: 720px) {
    .home-req-list { grid-template-columns: repeat(2, 1fr); }
    .home-status-band { flex-direction: column; align-items: flex-start; }
    .home-status-cta { align-self: stretch; text-align: center; }
}

.queue-track-pool {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
    margin-top: 0.5rem;
}

/* ===== LEADERBOARD TABS ===== */
.lb-tab-bar { display: flex; gap: 2px; margin-bottom: 20px; border-bottom: 1px solid var(--border-hover); padding-bottom: 0; }
.lb-tab-btn { font-family: var(--font-display); background: transparent; border: none; border-bottom: 2px solid transparent; color: var(--text-tertiary); padding: 10px 20px; font-size: 13px; font-weight: 600; cursor: pointer; transition: all 0.12s ease; text-transform: uppercase; letter-spacing: 0.5px; }
.lb-tab-btn:hover { color: var(--text-primary); }
.lb-tab-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.lb-tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); }

/* ===== RECORD CATEGORY CHIPS ===== */
.record-category-bar { display: flex; gap: 6px; margin-bottom: 20px; flex-wrap: wrap; }
.record-cat-btn { font-family: var(--font-display); background: transparent; border: 1px solid var(--border); color: var(--text-tertiary); padding: 6px 14px; border-radius: 12px; font-size: 12px; font-weight: 600; cursor: pointer; transition: all 0.12s ease; text-transform: uppercase; letter-spacing: 0.3px; }
.record-cat-btn:hover { border-color: var(--border-hover); color: var(--text-primary); }
.record-cat-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.record-cat-btn.active { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }

/* ===== LAP LEADERBOARD FILTERS (Phase C.2) ===== */
.lap-filter-bar { display: flex; gap: 24px; align-items: center; margin-bottom: 18px; padding: 12px 16px; background: var(--bg-panel); border-radius: 4px; flex-wrap: wrap; }
.lap-filter-group { display: flex; align-items: center; gap: 6px; }
.lap-filter-group label { font-family: var(--font-display); font-size: 11px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-right: 4px; }
.lap-chip { font-family: var(--font-display); background: transparent; border: 1px solid var(--border); color: var(--text-tertiary); padding: 4px 12px; border-radius: 10px; font-size: 11px; font-weight: 600; cursor: pointer; transition: all 0.12s ease; }
.lap-chip:hover { border-color: var(--border-hover); color: var(--text-primary); }
.lap-chip.active { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }
.lap-toggle { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-secondary); cursor: pointer; text-transform: none; letter-spacing: normal; font-weight: 500; }
.lap-toggle input { accent-color: var(--accent); }
.lap-split { font-family: var(--font-mono, monospace); color: var(--text-secondary); font-size: 12px; }
/* Still used by the ADMIN layout-laps table (LayoutLapsTab) after the public leaderboards
   dropped their Source column — all three sheets load globally, so this rule reaches it.
   line-height caps it under the cell strut instead of setting the row height. */
.lap-source-badge { font-family: var(--font-display); font-size: 10px; font-weight: 700; padding: 3px 8px; border-radius: 3px; text-transform: uppercase; letter-spacing: 0.5px; line-height: 1.2; }
.lap-source-race { background: rgba(0, 224, 255, 0.12); color: #00e0ff; border: 1px solid rgba(0, 224, 255, 0.3); }
.lap-source-time_attack { background: rgba(138, 111, 255, 0.12); color: #b49cff; border: 1px solid rgba(138, 111, 255, 0.3); }
/* Legacy aliases — matched by rows written before migration 35 renamed practice_timed→time_attack */
.lap-source-practice_timed { background: rgba(138, 111, 255, 0.12); color: #b49cff; border: 1px solid rgba(138, 111, 255, 0.3); }
.lap-source-practice_free { background: rgba(150, 150, 150, 0.1); color: #888; border: 1px solid rgba(150, 150, 150, 0.25); }

/* ===== COMPACT LEADERBOARD FILTER BAR (redesign 02-leaderboard-filters) =====
   One un-boxed inline row of labelled native <select>s (Source / When / Car)
   replacing the old boxed .lap-filter-bar chip-groups. NO background / box
   padding so it sits flush above the table. The .lap-* rules above stay defined
   (other surfaces / invariant tests reference them) — these are additive. */
.kott-filter-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 18px; margin-bottom: 14px; }
.kott-filter-bar label { font-family: var(--font-display); font-size: 11px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.5px; margin-right: 6px; }
/* Clone of .filter-select (2660) — native <select> in house style. */
.kott-filter-select { background: var(--bg-input); border: 1px solid var(--border-hover); color: var(--text-primary); padding: 6px 12px; border-radius: 4px; font-family: var(--font-display); font-size: 12px; cursor: pointer; }
.kott-filter-select:focus { outline: none; border-color: var(--border-accent-strong); }
/* Collapsed-by-default <details> disclosure holding the "older track layouts" toggle. */
.kott-filter-advanced summary { cursor: pointer; font-family: var(--font-display); font-size: 11px; font-weight: 600; color: var(--text-tertiary); text-transform: uppercase; letter-spacing: 0.5px; list-style: none; }
.kott-filter-advanced summary::-webkit-details-marker { display: none; }
.kott-filter-advanced summary:hover { color: var(--text-primary); }
/* Clear-filters text link — only emitted when a filter differs from default. */
.kott-filter-clear { margin-left: auto; font-size: 12px; color: var(--text-tertiary); cursor: pointer; background: none; border: none; padding: 0; font-family: var(--font-body); }
.kott-filter-clear:hover { text-decoration: underline; color: var(--text-primary); }
.kott-filter-clear:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Inline jump-to-me affordance (community Times tab) — small text button, not the loud bordered pill. */
.kott-filter-jump { display: inline-flex; align-items: center; gap: 8px; margin-left: auto; }
.kott-filter-jump-rank { font-family: var(--font-display); font-size: 12px; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.5px; }
.kott-filter-jump-btn { background: none; border: none; padding: 0; font-family: var(--font-display); font-size: 12px; font-weight: 700; color: var(--accent); cursor: pointer; text-transform: uppercase; letter-spacing: 0.5px; transition: color 0.12s ease; }
.kott-filter-jump-btn:hover { color: var(--accent-hover); }
.kott-filter-jump-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width: 640px) {
    .kott-filter-bar { gap: 10px 14px; }
    .kott-filter-bar > * { flex: 0 1 auto; }
    .kott-filter-clear, .kott-filter-jump { margin-left: 0; flex-basis: 100%; }
}

/* Community Hub (Task F3) — motorsport sector-time colors: purple = overall
   fastest, green = driver personal best, dim = slower. Class names emitted by
   DisplayHelpers.SectorColorClass. */
.sector-purple { color: var(--accent-purple); }
.sector-green { color: var(--success); }
.sector-dim { color: var(--text-muted); }

/* Community Hub (P1 polish, 2026-06-07) — sector micro-bar: a thin bar under each
   S1/S2/S3 split whose width ∝ that sector's time vs the page max for the sector.
   Pure CSS (inline width:%); colour inherits the sector class via currentColor
   (purple = page best, green = driver best, dim = slower). Subtle/premium: the cell
   is position:relative so the bar pins to the bottom edge under the time. */
.pub-table td.lap-split { position: relative; }
.sector-microbar {
    display: block;
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    max-width: 100%;
    background: currentColor;
    opacity: 0.4;
    border-radius: 1px;
    pointer-events: none;
}

/* Community Hub (Task P0-2) — Times board: gap-to-leader column, jump-to-me
   affordance, and numbered pagination. Accent picks up the community brand via
   --accent (scoped by <TenantBrandedLayout>). */
.lap-gap { font-family: var(--font-mono, monospace); color: var(--text-muted); font-size: 12px; font-variant-numeric: tabular-nums; }

.lap-jump-bar { display: flex; align-items: center; gap: 12px; margin: 0 0 14px; flex-wrap: wrap; }
.lap-jump-info { font-family: var(--font-display); font-size: 12px; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.5px; }
.lap-jump-btn { font-family: var(--font-display); background: var(--accent-dim); border: 1px solid var(--accent); color: var(--accent); padding: 5px 14px; border-radius: 10px; font-size: 11px; font-weight: 700; cursor: pointer; transition: all 0.12s ease; text-transform: uppercase; letter-spacing: 0.5px; }
.lap-jump-btn:hover { background: var(--accent); color: #000; }
.lap-jump-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.lap-page-btn { font-family: var(--font-display); background: transparent; border: 1px solid var(--border); color: var(--text-tertiary); padding: 5px 11px; border-radius: 4px; font-size: 12px; font-weight: 600; cursor: pointer; transition: all 0.12s ease; font-variant-numeric: tabular-nums; }
.lap-page-btn:hover:not(:disabled) { border-color: var(--border-hover); color: var(--text-primary); }
.lap-page-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: -1px; }
.lap-page-btn.active { background: var(--accent-dim); border-color: var(--accent); color: var(--accent); }
.lap-page-btn:disabled { opacity: 0.4; cursor: default; }

/* Community Hub (Task P0-3) — Drivers roster: sortable column-header buttons +
   course-record-count chip. The sort buttons sit inside <th> and read as plain
   headers until active, when --accent picks up the community brand. */
.sort-th { font-family: inherit; background: transparent; border: none; color: inherit; padding: 0; font-size: inherit; font-weight: inherit; letter-spacing: inherit; text-transform: inherit; cursor: pointer; transition: color 0.12s ease; }
.sort-th:hover { color: var(--text-primary); }
.sort-th:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sort-th.active { color: var(--accent); }
.record-count { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--accent-purple); white-space: nowrap; }
.text-dim { color: var(--text-muted); }

@media (max-width: 640px) {
    .lap-filter-bar { flex-direction: column; align-items: flex-start; gap: 10px; }
    .col-hide-sm { display: none; }
}

/* ===== NOTIFICATION SETTINGS (moved from inline <style>) ===== */
.notif-card { background: var(--bg-panel); border: 1px solid rgba(255,255,255,0.06); border-radius: 7px; padding: 1.5rem 2rem; max-width: 600px; }
.notif-description { color: var(--text-secondary); margin-bottom: 1.5rem; }
.notif-status { padding: 0.5rem 1rem; border-radius: 4px; margin-bottom: 1rem; font-size: var(--text-sm, 12px); }
.notif-success { background: var(--accent-dim); color: var(--accent); }
.notif-error { background: var(--danger-dim); color: var(--danger); border: 1px solid var(--danger-border); }
.notif-toggles { display: flex; flex-direction: column; gap: 1rem; }
.notif-toggle-row { display: flex; align-items: center; justify-content: space-between; padding: 0.75rem 1rem; background: rgba(255,255,255,0.02); border: 1px solid rgba(255,255,255,0.04); border-radius: 5px; }
.notif-toggle-info { flex: 1; margin-right: 1rem; }
.notif-toggle-label { font-weight: 600; color: var(--text-primary); }
.notif-toggle-desc { font-size: var(--text-sm, 12px); color: var(--text-muted); margin-top: 2px; }
.toggle-switch { position: relative; display: inline-block; width: 44px; height: 24px; flex-shrink: 0; }
.toggle-switch input { opacity: 0; width: 0; height: 0; }
.toggle-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background: rgba(255,255,255,0.1); border-radius: 14px; transition: background 0.2s; }
.toggle-slider::before { content: ""; position: absolute; height: 18px; width: 18px; left: 3px; bottom: 3px; background: #fff; border-radius: 50%; transition: transform 0.2s; }
.toggle-switch input:checked + .toggle-slider { background: var(--accent); }
.toggle-switch input:checked + .toggle-slider::before { transform: translateX(20px); }

/* ===== TIME ATTACK DISCOVERY PAGE (Phase D.2) ===== */
.ta-server-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; margin-top: 20px; }
.ta-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 5px; padding: 16px; display: flex; flex-direction: column; gap: 12px; transition: border-color 0.2s; }
.ta-card:hover { border-color: var(--border-hover); }
.ta-card.online { border-color: rgba(138, 111, 255, 0.35); }
.ta-card.offline { opacity: 0.5; }
.ta-card-header { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.ta-card-track { font-family: var(--font-display); font-size: 15px; font-weight: 700; color: var(--text-primary); }
.ta-card-players { font-size: 11px; color: #b49cff; font-family: var(--font-display); font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; }
.ta-card-body { flex: 1; display: flex; flex-direction: column; gap: 8px; }
.ta-card-name { color: var(--text-secondary); font-size: 12px; }
.ta-card-top { display: flex; flex-direction: column; gap: 2px; font-size: 13px; }
.ta-card-top .label { color: var(--text-muted); font-size: 10px; text-transform: uppercase; letter-spacing: 0.5px; }
.ta-card-top-time { color: #b49cff; font-family: var(--font-mono, monospace); font-size: 18px; }
.ta-card-top-holder { color: var(--text-tertiary); font-size: 11px; }
.ta-card-top.muted { color: var(--text-muted); font-style: italic; font-size: 12px; }
.ta-card-connect { width: 100%; text-align: center; }
.ta-card-deltas { font-size: 13px; color: #ccc; display: flex; gap: 12px; align-items: baseline; margin-top: 2px; flex-wrap: wrap; }
.ta-delta-behind { color: #ff6b6b; }
.ta-delta-ahead { color: #8aff8a; }
.ta-hint { color: #888; font-style: italic; font-size: 12px; }

/* ===== SEASON TAB ===== */
.season-selector { margin-bottom: 16px; }
.season-selector select { background: var(--bg-input); border: 1px solid var(--border-hover); color: var(--text-primary); padding: 8px 14px; border-radius: 4px; font-family: var(--font-display); font-size: 13px; cursor: pointer; min-width: 200px; }
.season-selector select:focus { outline: none; border-color: var(--border-accent-strong); }
.season-banner { background: var(--bg-panel); border-radius: 5px; padding: 16px 20px; margin-bottom: 20px; display: flex; flex-wrap: wrap; gap: 16px; align-items: center; }
.season-banner-name { font-family: var(--font-display); font-size: 16px; font-weight: 700; color: var(--accent); }
.season-banner-meta { display: flex; gap: 16px; font-size: 12px; color: var(--text-secondary); flex-wrap: wrap; }
.season-banner-meta span { display: inline-flex; align-items: center; gap: 4px; }
.season-banner-meta .label { color: var(--text-muted); }

@media (max-width: 768px) {
    .home-title { font-size: 2rem; letter-spacing: 2px; }
    .home-hero-actions { flex-direction: column; gap: 0.9rem; }
    .home-hero-cta { width: 100%; max-width: 260px; text-align: center; }
    .replay-controls { flex-wrap: wrap; }
    .replay-header { flex-direction: column; gap: 0.5rem; text-align: center; }
    .replay-container { padding: 0.75rem; }
    .replay-viewport { padding: 0.5rem; }
    .replay-btn { min-width: 60px; padding: 6px 14px; }
    .lb-tab-btn { padding: 8px 14px; font-size: 12px; }
    /* 2026-07-09 mobile pass — record-category chips wrap (base rule) instead
       of the old nowrap+overflow that ran off the right edge unannounced. */
    .season-banner { flex-direction: column; gap: 8px; }
}
@media (max-width: 480px) {
    .replay-scrubber { min-width: 100px; }
    .replay-speed { font-size: 11px; }
    .lb-tab-bar { overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .match-filters .filter-row { flex-direction: column; }
    .filter-toggle { width: 100%; }
    .filter-search { width: 100%; }
}

/* ===== MATCH FILTERS ===== */
.match-filters { margin-bottom: 16px; padding: 12px 16px; }
.filter-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.filter-select { background: var(--bg-input); border: 1px solid var(--border-hover); color: var(--text-primary); padding: 6px 12px; border-radius: 4px; font-family: var(--font-display); font-size: 12px; cursor: pointer; min-width: 140px; }
.filter-select:focus { outline: none; border-color: var(--border-accent-strong); }
.filter-toggle { display: flex; gap: 4px; }
.filter-search { background: var(--bg-input); border: 1px solid var(--border); color: var(--text-primary); padding: 6px 12px; border-radius: 4px; font-family: var(--font-body); font-size: 13px; min-width: 160px; }
.filter-search::placeholder { color: var(--text-muted); }
.filter-search:focus { outline: none; border-color: var(--border-accent-strong); }
.filter-search-wrap { position: relative; display: inline-block; }
.filter-search-spinner { position: absolute; right: 8px; top: 50%; width: 12px; height: 12px; margin-top: -6px; border: 2px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: filter-spin 0.6s linear infinite; pointer-events: none; }
@keyframes filter-spin { to { transform: rotate(360deg); } }

/* ===== STATUS PAGE ===== */
.status-overall { display: flex; align-items: center; gap: 16px; padding: 20px 24px; border-radius: 5px; border: 1px solid var(--border); background: var(--bg-card); margin-bottom: 1.5rem; }
.status-overall-dot { width: 14px; height: 14px; border-radius: 50%; flex-shrink: 0; }
.status-overall.status-ok .status-overall-dot { background: var(--success); box-shadow: 0 0 10px var(--success); }
.status-overall.status-warn .status-overall-dot { background: var(--warning); box-shadow: 0 0 10px var(--warning); }
.status-overall.status-error .status-overall-dot { background: var(--danger); box-shadow: 0 0 10px var(--danger); }
.status-overall-label { font-family: var(--font-display); font-size: 18px; font-weight: 700; color: var(--text-primary); }
.status-overall-detail { font-size: 12px; color: var(--text-muted); margin-top: 2px; }

.status-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px; margin-bottom: 1.5rem; }
.status-card { padding: 16px; border-radius: 5px; background: var(--bg-card); border: 1px solid var(--border); border-left: 4px solid var(--text-muted); }
.status-card.status-ok { border-left-color: var(--success); }
.status-card.status-warn { border-left-color: var(--warning); }
.status-card.status-error { border-left-color: var(--danger); }
.status-card-label { font-family: var(--font-display); font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-muted); }
.status-card-value { font-family: var(--font-display); font-size: 22px; font-weight: 700; color: var(--text-primary); margin-top: 4px; line-height: 1.1; }
.status-card-sub { font-size: 12px; color: var(--text-tertiary); margin-top: 6px; line-height: 1.5; }
.status-card-sub a { color: var(--accent); }

.status-incidents { display: flex; flex-direction: column; gap: 10px; }
.status-incident { padding: 12px 16px; border-radius: 4px; background: var(--bg-card); border-left: 3px solid var(--text-muted); font-size: 13px; }
.status-incident.incident-warning { border-left-color: var(--warning); }
.status-incident.incident-maintenance { border-left-color: var(--danger); }
.status-incident strong { font-family: var(--font-display); color: var(--text-primary); }
.status-incident-meta { font-size: 11px; color: var(--text-muted); margin-top: 4px; }

.status-footer-note { text-align: center; font-size: 12px; color: var(--text-muted); margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid var(--border); }
.status-footer-note a { color: var(--accent); }

/* ===== STATUS PAGE — Phase 7 Task 7.37 ===== */
/* Top banner rendered by bannerLevel ok|warn|error. Replaces the older
   .status-overall class shown above; kept both for back-compat. */
/* Wave 5 sub-themes 5.5 + 5.8 (2026-05-06) — banner is now an <a>;
   text-decoration suppressed + transition on hover for the click cue.
   Uptime number gets prominence via .status-banner-uptime (was hidden
   in the 90-day grid below). */
.status-banner { display: flex; align-items: center; gap: 16px; padding: 22px 26px; border-radius: 6px; border: 1px solid var(--border); background: var(--bg-card); margin: 12px 0 22px; text-decoration: none !important; color: var(--text-primary); transition: border-color 0.15s, transform 0.05s; }
a.status-banner:hover { border-color: var(--border-hover); transform: translateY(-1px); }
.status-banner-uptime { color: var(--text-secondary); font-family: var(--font-display); font-size: 13px; }
.status-banner-uptime strong { color: var(--text-primary); font-weight: 700; }
.status-banner-refresh { color: var(--text-muted); margin-left: 4px; }
html { scroll-behavior: smooth; }
.status-banner-dot { width: 16px; height: 16px; border-radius: 50%; flex-shrink: 0; }
.status-banner.status-banner-ok .status-banner-dot { background: var(--success); box-shadow: 0 0 12px var(--success); }
.status-banner.status-banner-warn .status-banner-dot { background: var(--warning); box-shadow: 0 0 12px var(--warning); }
.status-banner.status-banner-error .status-banner-dot { background: var(--danger); box-shadow: 0 0 12px var(--danger); }
.status-banner.status-banner-ok { border-left: 5px solid var(--success); }
.status-banner.status-banner-warn { border-left: 5px solid var(--warning); }
.status-banner.status-banner-error { border-left: 5px solid var(--danger); }
.status-banner-label { font-family: var(--font-display); font-size: 20px; font-weight: 700; color: var(--text-primary); }
.status-banner-detail { font-size: 12px; color: var(--text-muted); margin-top: 3px; }

.status-component-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px; }
.status-component { padding: 14px 16px; border-radius: 5px; background: var(--bg-card); border: 1px solid var(--border); border-left: 4px solid var(--text-muted); }
.status-component.status-ok { border-left-color: var(--success); }
.status-component.status-warn { border-left-color: var(--warning); }
.status-component.status-error { border-left-color: var(--danger); }
.status-component-name { font-family: var(--font-display); font-size: 13px; text-transform: uppercase; letter-spacing: 0.4px; color: var(--text-tertiary); }
.status-component-state { font-family: var(--font-display); font-size: 18px; font-weight: 700; margin-top: 4px; color: var(--text-primary); line-height: 1.1; }
.status-component-detail { font-size: 12px; color: var(--text-muted); margin-top: 4px; }

.status-sev-pill { font-family: var(--font-display); font-size: 10px; letter-spacing: 0.5px; padding: 2px 8px; border-radius: 6px; text-transform: uppercase; }
.status-sev-minor { background: rgba(255,179,71,0.15); color: var(--warning); }
.status-sev-major { background: rgba(255,107,107,0.18); color: var(--danger); }
.status-sev-critical { background: rgba(255,107,107,0.28); color: var(--danger); }
.status-sev-maintenance { background: rgba(180,156,255,0.18); color: #b49cff; }

.status-incident-list { display: flex; flex-direction: column; gap: 10px; }
.status-incident-card { padding: 14px 18px; border-radius: 5px; background: var(--bg-card); border: 1px solid var(--border); border-left: 4px solid var(--text-muted); }
.status-incident-card.incident-minor { border-left-color: var(--warning); }
.status-incident-card.incident-major, .status-incident-card.incident-critical { border-left-color: var(--danger); }
.status-incident-card.incident-maintenance { border-left-color: #b49cff; }
.status-incident-card-head { display: flex; align-items: center; gap: 10px; justify-content: space-between; }
.status-incident-card-head strong { font-family: var(--font-display); font-size: 15px; color: var(--text-primary); }
.status-incident-summary { margin-top: 6px; font-size: 13px; color: var(--text-secondary); line-height: 1.5; }
.status-incident-update { margin-top: 8px; padding: 8px 10px; border-radius: 4px; background: rgba(255,255,255,0.03); font-size: 13px; }
.status-incident-update-meta { font-size: 11px; color: var(--text-muted); display: block; margin-bottom: 4px; }

.status-uptime-list { display: flex; flex-direction: column; gap: 12px; }
.status-uptime-row { background: var(--bg-card); border: 1px solid var(--border); border-radius: 5px; padding: 10px 14px; }
.status-uptime-label { display: flex; justify-content: space-between; align-items: baseline; font-family: var(--font-display); font-size: 13px; color: var(--text-primary); margin-bottom: 8px; }
.status-uptime-pct { font-size: 12px; color: var(--text-muted); letter-spacing: 0.3px; }
.status-uptime-bar { display: flex; gap: 2px; align-items: stretch; height: 22px; }
.status-uptime-tick { flex: 1; min-width: 3px; border-radius: 1px; background: var(--success); opacity: 0.5; }
.status-uptime-tick.status-uptime-ok { background: var(--success); opacity: 0.55; }
.status-uptime-tick.status-uptime-deg { background: var(--warning); opacity: 0.9; }

.status-history-wrap { overflow-x: auto; }
.status-history { width: 100%; border-collapse: collapse; font-size: 13px; }
.status-history th, .status-history td { text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--border); }
.status-history th { color: var(--text-tertiary); font-family: var(--font-display); font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; }

@media (max-width: 640px) {
    .status-banner { flex-direction: column; align-items: flex-start; text-align: left; }
    /* 2026-07-09 mobile pass — 90 ticks × (min-width + 2px gap) overflowed a
       360px viewport; 1px each keeps the whole 90-day strip inside the card. */
    .status-uptime-bar { gap: 1px; }
    .status-uptime-tick { min-width: 1px; }
}

/* ===== LOADING SKELETON ===== */
/* Reusable skeleton parts. .skeleton-block stays visible; child .skel-* elements shimmer. */
.skeleton-block { pointer-events: none; }
.skel-line { display: inline-block; height: 12px; border-radius: 3px; background: linear-gradient(90deg, var(--bg-hover) 0%, rgba(255,255,255,0.10) 50%, var(--bg-hover) 100%); background-size: 200% 100%; animation: skel-shimmer 1.2s ease-in-out infinite; }
.skel-line-lg { height: 22px; }
/* Fixed width steps for shape-matched skeleton cells — the F-301 inline-style guard bans
   static style="width:Npx" on admin/community pages, so table skeletons size via these. */
.skel-w-xs { width: 24px; }
.skel-w-sm { width: 44px; }
.skel-w-md { width: 60px; }
.skel-w-lg { width: 80px; }
.skel-circle { background: linear-gradient(90deg, var(--bg-hover) 0%, rgba(255,255,255,0.10) 50%, var(--bg-hover) 100%); background-size: 200% 100%; animation: skel-shimmer 1.2s ease-in-out infinite; border-radius: 50%; width: 84px; height: 84px; }
@keyframes skel-shimmer { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }

/* ===== MATCH DETAIL DISPUTE FORM ===== */
.dispute-section { margin-bottom: 1rem; }
.btn-dispute { background: rgba(251,191,36,0.15); color: var(--warning); border: 1px solid rgba(251,191,36,0.3); padding: 6px 16px; border-radius: 4px; cursor: pointer; font-size: 0.85rem; }
.btn-dispute:hover { background: rgba(251,191,36,0.25); }
.dispute-badge { display: inline-block; padding: 4px 12px; border-radius: 4px; font-size: 0.8rem; font-weight: 600; }
.dispute-badge-open { background: rgba(251,191,36,0.15); color: var(--warning); }
.dispute-badge-accepted { background: rgba(52,211,153,0.15); color: var(--success); }
.dispute-badge-rejected { background: rgba(248,113,113,0.15); color: var(--danger); }
.dispute-success { display: block; margin-bottom: 8px; padding: 8px 14px; background: rgba(52,211,153,0.1); border: 1px solid rgba(52,211,153,0.25); border-radius: 4px; color: var(--success); font-size: 0.85rem; font-weight: 500; max-width: 500px; }
.dispute-form { background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06); border-radius: 5px; padding: 1rem; max-width: 500px; }
.dispute-form textarea { width: 100%; margin-top: 0.5rem; background: rgba(0,0,0,0.3); border: 1px solid rgba(255,255,255,0.1); color: var(--text-primary); border-radius: 4px; padding: 0.5rem; resize: vertical; font-family: var(--font-body); }
.dispute-error { color: var(--danger); font-size: 0.8rem; margin-top: 0.5rem; }
.dispute-form-actions { display: flex; gap: 0.5rem; margin-top: 0.75rem; }
.btn-dispute-submit { background: var(--warning); color: #000; border: none; padding: 6px 16px; border-radius: 4px; cursor: pointer; font-weight: 600; }
.btn-dispute-submit:disabled { opacity: 0.5; cursor: not-allowed; }

/* ===== SPEED COMPARISON BARS ===== */
.speed-compare-section { margin: 1.5rem 0; }
.speed-compare-title { font-family: var(--font-display); font-size: 14px; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 12px; }
.speed-compare-player { margin-bottom: 16px; }
.speed-compare-name { font-family: var(--font-display); font-weight: 600; font-size: 14px; margin-bottom: 6px; color: var(--text-primary); }
.speed-bar-row { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.speed-bar-label { font-size: 11px; color: var(--text-muted); width: 28px; text-align: right; flex-shrink: 0; }
.speed-bar { flex: 1; height: 18px; background: var(--bg-elevated); border-radius: 4px; overflow: hidden; }
.speed-bar-fill { height: 100%; border-radius: 4px; transition: width 0.4s ease; }
.speed-bar-fill.bar-winner { background: linear-gradient(90deg, var(--accent) 0%, rgba(0,224,255,0.6) 100%); }
.speed-bar-fill.bar-loser { background: linear-gradient(90deg, var(--text-muted) 0%, rgba(107,117,136,0.4) 100%); }
.speed-bar-value { font-size: 12px; color: var(--text-secondary); width: 70px; text-align: right; flex-shrink: 0; }

/* ===== 404 / ERROR PAGE ===== */
.notfound-page, .error-page { text-align: center; padding: 4rem 1rem; }
.notfound-code { font-family: var(--font-display); font-size: 6rem; font-weight: 700; color: var(--accent); line-height: 1; margin-bottom: 0.5rem; text-shadow: 0 0 40px var(--accent-glow); }
.notfound-title { font-family: var(--font-display); font-size: 1.5rem; font-weight: 600; color: var(--text-primary); margin-bottom: 0.75rem; }
.notfound-text { color: var(--text-secondary); font-size: 14px; margin-bottom: 2rem; }
.notfound-links { display: flex; gap: 12px; justify-content: center; }
.notfound-links .btn { padding: 10px 24px; border-radius: 4px; font-family: var(--font-display); font-weight: 600; font-size: 14px; text-decoration: none; cursor: pointer; border: none; }
.notfound-links .btn.primary { background: var(--accent); color: #000; }
.notfound-links .btn.primary:hover { background: var(--accent-hover); }
.notfound-links .btn.secondary { background: var(--bg-elevated); color: var(--text-primary); border: 1px solid var(--border); }
.notfound-links .btn.secondary:hover { border-color: var(--accent); color: var(--accent); }

/* ===== HEAD-TO-HEAD ===== */
.h2h-search-panel { background: var(--bg-card); border: 1px solid var(--border); border-radius: 6px; padding: 1.5rem; margin-bottom: 1.5rem; }
.h2h-search-row { display: flex; align-items: flex-start; gap: 1rem; }
.h2h-search-col { flex: 1; position: relative; }
.h2h-search-col label { display: block; font-family: var(--font-display); font-size: 12px; font-weight: 600; color: var(--text-secondary); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 6px; }
.h2h-search-input { width: 100%; padding: 10px 14px; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 4px; color: var(--text-primary); font-size: 14px; outline: none; box-sizing: border-box; }
.h2h-search-input:focus { border-color: var(--accent); }
.h2h-search-dropdown { position: absolute; top: 100%; left: 0; right: 0; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 0 0 4px 4px; z-index: 10; max-height: 200px; overflow-y: auto; }
.h2h-search-option { display: block; width: 100%; padding: 8px 14px; background: none; border: none; color: var(--text-primary); font-size: 14px; text-align: left; cursor: pointer; }
.h2h-search-option:hover { background: rgba(0,224,255,0.1); color: var(--accent); }
.h2h-selected { margin-top: 6px; font-size: 13px; color: var(--accent); font-weight: 600; }
.h2h-vs-label { font-family: var(--font-display); font-size: 1.5rem; font-weight: 700; color: var(--text-muted); padding-top: 24px; flex-shrink: 0; }
.h2h-compare-btn { display: block; margin: 1rem auto 0; padding: 10px 36px; }

.h2h-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: 6px; padding: 2rem; text-align: center; }
.h2h-versus { display: flex; align-items: center; justify-content: center; gap: 1.5rem; margin-bottom: 1.5rem; }
.h2h-player { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.h2h-player-name { font-family: var(--font-display); font-size: 1.1rem; font-weight: 600; color: var(--text-primary); text-decoration: none; display: inline-block; max-width: 16ch; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; vertical-align: bottom; }
.h2h-player-name:hover { color: var(--accent); }
.h2h-win-count { font-family: var(--font-display); font-size: 3rem; font-weight: 700; color: var(--text-secondary); line-height: 1; }
.h2h-win-count.h2h-leading { color: var(--accent); text-shadow: 0 0 20px var(--accent-glow); }
.h2h-dash { font-family: var(--font-display); font-size: 2rem; color: var(--text-muted); }

.h2h-win-bar { display: flex; height: 28px; border-radius: 4px; overflow: hidden; margin-bottom: 0.5rem; }
.h2h-win-bar-p1 { background: linear-gradient(90deg, var(--accent), rgba(0,224,255,0.6)); display: flex; align-items: center; justify-content: center; transition: width 0.4s ease; }
.h2h-win-bar-p2 { background: linear-gradient(90deg, rgba(107,117,136,0.6), var(--text-muted)); display: flex; align-items: center; justify-content: center; transition: width 0.4s ease; }
.h2h-win-bar-p1 span, .h2h-win-bar-p2 span { font-size: 11px; font-weight: 700; color: #000; }
.h2h-total { font-size: 13px; color: var(--text-secondary); }

.match-link { color: var(--accent); text-decoration: none; font-size: 13px; }
.match-link:hover { text-decoration: underline; }

@media (max-width: 768px) {
    .h2h-search-row { flex-direction: column; }
    .h2h-vs-label { padding-top: 0; text-align: center; }
    .h2h-versus { flex-direction: column; gap: 0.5rem; }
    .h2h-win-count { font-size: 2.5rem; }
}

.h2h-detail-link { display: inline-block; margin-top: 8px; color: var(--accent); text-decoration: none; font-size: 13px; font-weight: 600; }
.h2h-detail-link:hover { text-decoration: underline; }

/* Community Hub (Task P0-5) — spacing utilities for the tenant-scoped H2H page
   (the empty-state inside the versus card + the recent-meetings section title). */
.h2h-empty-inset { margin-top: 1rem; }
.h2h-section-spaced { margin-top: 2rem; }

/* Provisional badge */
.provisional-badge {
    display: inline-block;
    font-size: 0.65rem;
    font-style: italic;
    color: rgba(255,255,255,0.4);
    background: rgba(255,255,255,0.05);
    padding: 1px 8px;
    border-radius: 4px;
    margin-left: 6px;
    vertical-align: middle;
    font-weight: 400;
    cursor: help;
}

/* ── Mode header (Queue page) ─────────────────────────────────── */
.mode-header { padding: 16px 0 8px; }
.mode-title { font-family: var(--font-display); font-size: var(--text-2xl); font-weight: 700; color: var(--accent-cyan, #00e0ff); display: flex; align-items: center; gap: 12px; margin: 0; letter-spacing: 0.5px; }
.mode-badge { font-size: 12px; padding: 2px 8px; border: 1px solid #00e0ff; border-radius: 4px; letter-spacing: 0.08em; font-weight: 500; }
.mode-explainer { color: #aaa; font-size: 14px; margin-top: 4px; }
/* Time Attack variant */
.ta-mode-title { color: var(--accent-purple, #b49cff); }
.ta-badge { border-color: var(--accent-purple, #b49cff); color: var(--accent-purple, #b49cff); }
.mm-mode-title { color: var(--accent); }
.mm-badge { border-color: var(--accent); color: var(--accent); }

/* ── Match-found notification card (Queue page) ───────────────── */
@keyframes kott-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(0, 224, 255, 0.7); }
    50%       { box-shadow: 0 0 0 14px rgba(0, 224, 255, 0); }
}
/* ═══════════ MATCH FOUND CARD ═══════════ */
.match-found-card {
    padding: 28px;
    border: 1px solid rgba(0, 224, 255, 0.35);
    border-radius: 6px;
    background: linear-gradient(180deg, rgba(0, 224, 255, 0.08) 0%, rgba(0, 224, 255, 0.03) 100%);
    box-shadow: 0 0 0 1px rgba(0, 224, 255, 0.05), 0 4px 24px rgba(0, 224, 255, 0.08);
    margin: 16px 0;
    max-width: 620px;
    margin-left: auto;
    margin-right: auto;
}
.match-found-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding-bottom: 16px;
    margin-bottom: 18px;
    border-bottom: 1px solid rgba(0, 224, 255, 0.12);
}
.match-found-dot {
    width: 10px; height: 10px; border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 10px var(--accent);
    animation: match-dot-pulse 1.4s ease-in-out infinite;
    flex-shrink: 0;
}
@keyframes match-dot-pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%      { opacity: 0.55; transform: scale(0.85); }
}
.match-found-label {
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 2.5px;
    text-transform: uppercase;
    color: var(--accent);
}
.match-found-countdown {
    margin-left: auto;
    display: flex;
    align-items: baseline;
    gap: 4px;
    font-family: var(--font-display);
}
.match-found-countdown .countdown-seconds {
    font-size: 28px;
    font-weight: 700;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
    line-height: 1;
}
.match-found-countdown .countdown-unit {
    font-size: 11px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 1px;
}

.match-found-opponent {
    display: flex;
    align-items: baseline;
    gap: 14px;
    margin-bottom: 20px;
}
.match-found-vs {
    font-family: var(--font-display);
    font-size: 12px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 2px;
}
.match-found-opponent-name {
    font-family: var(--font-display);
    font-size: 26px;
    font-weight: 700;
    color: var(--text-primary) !important;
    text-decoration: none;
    letter-spacing: 1px;
    transition: color 0.15s;
}
.match-found-opponent-name:hover { color: var(--accent) !important; }

/* Primary CTA — solid fill with dark text, box-shadow glow, pulses gently.
   Prefixed with .public-shell to beat the .public-shell a specificity rule
   that would otherwise paint the label cyan-on-cyan (invisible). */
.public-shell .match-connect-btn {
    display: block;
    width: 100%;
    padding: 18px 20px;
    background: var(--accent);
    color: #001018 !important;
    border: none;
    border-radius: 5px;
    text-align: center;
    text-decoration: none;
    font-family: var(--font-display);
    box-shadow: 0 0 0 1px rgba(0, 224, 255, 0.3), 0 6px 24px rgba(0, 224, 255, 0.22);
    animation: match-connect-pulse 1.6s ease-in-out infinite;
    transition: transform 0.12s, box-shadow 0.15s;
    margin-bottom: 20px;
}
.public-shell .match-connect-btn:hover {
    background: var(--accent-hover, #33e7ff);
    transform: translateY(-1px);
    box-shadow: 0 0 0 1px rgba(0, 224, 255, 0.5), 0 8px 28px rgba(0, 224, 255, 0.35);
    color: #001018 !important;
}
.match-connect-btn-label {
    display: block;
    font-size: 20px;
    font-weight: 700;
    letter-spacing: 3px;
    text-transform: uppercase;
    line-height: 1.1;
}
.match-connect-btn-sub {
    display: block;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 1.5px;
    text-transform: uppercase;
    opacity: 0.65;
    margin-top: 4px;
}
@keyframes match-connect-pulse {
    0%, 100% { box-shadow: 0 0 0 1px rgba(0, 224, 255, 0.3), 0 6px 24px rgba(0, 224, 255, 0.22); }
    50%      { box-shadow: 0 0 0 2px rgba(0, 224, 255, 0.5), 0 8px 34px rgba(0, 224, 255, 0.4); }
}

.match-connect-fallback {
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 4px;
    padding: 14px 16px;
    margin-bottom: 20px;
    font-size: 13px;
    color: var(--text-secondary);
    text-align: center;
}
.match-connect-fallback code {
    background: rgba(0, 224, 255, 0.08);
    color: var(--accent);
    padding: 2px 6px;
    border-radius: 3px;
}

.match-found-meta {
    background: rgba(0, 0, 0, 0.25);
    border: 1px solid rgba(255, 255, 255, 0.05);
    border-radius: 4px;
    padding: 4px 16px;
    margin-bottom: 16px;
}
.match-found-meta-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 0;
    font-size: 13px;
}
.match-found-meta-row:not(:last-child) {
    border-bottom: 1px solid rgba(255, 255, 255, 0.04);
}
.match-found-meta-label {
    font-family: var(--font-display);
    font-size: 11px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.8px;
}
.match-found-meta-value {
    color: var(--text-primary);
    font-weight: 500;
}
.match-found-warning {
    font-size: 12px;
    color: var(--text-muted);
    text-align: center;
    margin: 0;
    font-style: italic;
}

/* Legacy classes still referenced elsewhere — kept for backwards-compat. */
.btn-connect-pulse {
    background: var(--accent-cyan, #00e0ff);
    color: #000 !important;
    font-weight: 700;
    padding: 16px 32px;
    border-radius: 4px;
    animation: kott-pulse 1.2s infinite;
    display: inline-block;
    text-decoration: none;
    margin: 12px 0;
    font-size: 1rem;
    letter-spacing: 0.05em;
    cursor: pointer;
}
.btn-connect-pulse:hover { opacity: 0.9; text-decoration: none; }
.connect-countdown { font-size: 14px; color: #aaa; margin: 8px 0 16px 0; }
.countdown-seconds { color: var(--accent-cyan, #00e0ff); font-weight: 700; font-size: 18px; }

/* ============================================
   Operator-admin license + suspension banners.
   Surfaced on /community/{slug}/admin to warn
   the operator before their fleet 401s.
   ============================================ */

.op-license-banner {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    margin: 12px 0 18px;
    padding: 12px 16px;
    border: 1px solid var(--border-accent);
    border-radius: 4px;
    font-size: 13.5px;
    line-height: 1.5;
}
.op-license-banner strong { font-weight: 700; }
.op-license-banner .btn {
    margin-left: auto;
}
.op-license-warning {
    background: rgba(251, 191, 36, 0.08);
    border-color: rgba(251, 191, 36, 0.35);
    color: #fbbf24;
}
.op-license-warning strong { color: #fde68a; }
.op-license-expired {
    background: rgba(248, 113, 113, 0.10);
    border-color: rgba(248, 113, 113, 0.45);
    color: #fca5a5;
}
.op-license-expired strong { color: #fecaca; }

.op-tenant-banner {
    margin: 12px 0 18px;
    padding: 14px 18px;
    border-radius: 4px;
    font-size: 14px;
    line-height: 1.5;
}
.op-tenant-banner strong { font-weight: 700; display: block; font-size: 15px; margin-bottom: 4px; }
.op-tenant-suspended {
    background: rgba(248, 113, 113, 0.12);
    border: 1px solid rgba(248, 113, 113, 0.5);
    color: #fca5a5;
}
.op-tenant-suspended strong { color: #fecaca; }
.op-tenant-scheduled {
    background: rgba(251, 191, 36, 0.10);
    border: 1px solid rgba(251, 191, 36, 0.45);
    color: #fbbf24;
}
.op-tenant-scheduled strong { color: #fde68a; }

.status-pill {
    display: inline-block;
    padding: 1px 8px;
    border-radius: 6px;
    font-family: var(--font-mono);
    font-size: 11px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid rgba(255, 255, 255, 0.18);
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}
.status-pill.ok {
    background: rgba(16, 185, 129, 0.10);
    border-color: rgba(16, 185, 129, 0.40);
    color: #10b981;
}
.status-pill.warn {
    background: rgba(245, 158, 11, 0.10);
    border-color: rgba(245, 158, 11, 0.40);
    color: #f59e0b;
}
.status-pill.danger {
    background: rgba(248, 113, 113, 0.12);
    border-color: rgba(248, 113, 113, 0.50);
    color: #fca5a5;
}

/* ============================================
   Shared empty / error / loading patterns
   Used across every public page for zero-data
   cards, async loads, and load failures.
   ============================================ */

.empty-state {
    padding: 24px;
    border: 1px dashed var(--border-accent);
    border-radius: 4px;
    background: var(--bg-panel);
    color: var(--text-muted);
    text-align: center;
    font-family: var(--font-body);
    line-height: 1.6;
}
.empty-state h4 {
    color: var(--text-secondary);
    font-family: var(--font-display);
    font-size: 15px;
    letter-spacing: 1px;
    text-transform: uppercase;
    margin-bottom: 8px;
}
.empty-state p { color: var(--text-muted); font-size: 13px; }
.empty-state .cta {
    display: inline-block;
    margin-top: 12px;
    padding: 8px 16px;
    background: var(--accent-dim);
    color: var(--accent);
    border: 1px solid var(--border-accent-strong);
    border-radius: 4px;
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 1px;
    text-transform: uppercase;
    text-decoration: none;
}
.empty-state .cta:hover { background: var(--accent); color: var(--bg-primary); }

.error-state {
    padding: 20px;
    border: 1px solid var(--danger-border);
    border-radius: 4px;
    background: var(--danger-dim);
    color: var(--danger);
    font-family: var(--font-body);
    font-size: 13px;
    text-align: center;
}
.error-state .retry-btn {
    margin-top: 10px;
    padding: 6px 14px;
    background: transparent;
    border: 1px solid var(--danger);
    color: var(--danger);
    border-radius: 4px;
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 1px;
    text-transform: uppercase;
    cursor: pointer;
}
.error-state .retry-btn:hover { background: var(--danger); color: var(--bg-primary); }

.loading-skeleton {
    background: linear-gradient(90deg, var(--bg-panel) 0%, var(--bg-hover) 50%, var(--bg-panel) 100%);
    background-size: 200% 100%;
    animation: skeleton-pulse 1.4s ease-in-out infinite;
    border-radius: 4px;
    min-height: 60px;
}
@keyframes skeleton-pulse {
    0% { background-position: 200% 0; }
    100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
    .loading-skeleton { animation: none; background: var(--bg-panel); }
}

/* ============================================
   Top-nav Play dropdown
   Desktop: CSS hover. Mobile: Blazor click-open.
   ============================================ */

.topnav-dropdown { position: relative; }
.topnav-dropdown-trigger {
    font-family: var(--font-display);
    color: var(--text-tertiary);
    font-size: 13px;
    font-weight: 600;
    padding: 8px 14px;
    border-radius: 4px;
    background: transparent;
    border: none;
    cursor: pointer;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    transition: all 0.12s ease;
}
.topnav-dropdown-trigger:hover,
.topnav-dropdown-trigger[aria-expanded="true"] {
    color: var(--text-primary);
    background: var(--bg-hover);
}
.topnav-dropdown-trigger.active {
    color: var(--accent);
    background: var(--accent-dim);
}
.topnav-dropdown-caret {
    font-size: 10px;
    opacity: 0.7;
    transition: transform 0.15s ease;
}
.topnav-dropdown-trigger[aria-expanded="true"] .topnav-dropdown-caret {
    transform: rotate(180deg);
}

.topnav-dropdown-menu {
    position: absolute;
    /* Flush to the trigger — any gap creates a hover dead-zone the cursor
       crosses when heading to a menu item, which kills the hover state and
       makes the dropdown disappear mid-move. Visual spacing is done via
       padding-top on the menu itself (see below). */
    top: 100%;
    left: 0;
    /* Fully opaque + z-index 200, matching .search-dropdown. Earlier the
       translucent rgba(…, 0.95) + blur let page content behind the menu
       bleed through (page <h1> visible through the open dropdown). The
       search dropdown pattern is right: nav menus should fully occlude
       page content below them. */
    background: var(--bg-panel-solid);
    border: 1px solid var(--border-accent);
    border-radius: 4px;
    min-width: 240px;
    padding: 10px 6px 6px;  /* 4px extra top padding = visual gap without breaking hover */
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
    display: none;
    z-index: 200;
}
.topnav-dropdown:hover .topnav-dropdown-menu,
.topnav-dropdown-menu.open { display: block; }

.topnav-dropdown-item {
    display: block;
    padding: 10px 12px;
    border-radius: 4px;
    text-decoration: none;
    transition: background 0.12s ease;
}
.topnav-dropdown-item:hover { background: var(--bg-hover); }
.topnav-dropdown-item-title {
    display: block;
    font-family: var(--font-display);
    color: var(--text-primary);
    font-size: 13px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 2px;
}
.topnav-dropdown-item-desc {
    display: block;
    color: var(--text-muted);
    font-size: 11px;
    line-height: 1.4;
}

/* Mobile menu: Play group is expandable */
.mobilenav-group-label {
    font-family: var(--font-display);
    color: var(--text-tertiary);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 2px;
    text-transform: uppercase;
    padding: 8px 0 4px;
}
.mobilenav-group-item {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    padding: 8px 12px;
    padding-left: 24px;
    min-height: auto;
}
.mobilenav-group-item-desc {
    display: block;
    color: var(--text-muted);
    font-size: 11px;
    line-height: 1.3;
    font-weight: 400;
    margin-top: 2px;
}

/* ============================================
   Home page — Watch/Learn/Play restructure
   ============================================ */

/* Retained for test compat / misc hero subcopy slot. Not currently used
   by the markup, but keep the rule in case a future iteration needs it. */
.home-subcopy {
    color: var(--text-tertiary);
    font-size: 14px;
    font-family: var(--font-body);
    margin-top: 6px;
    letter-spacing: 0.5px;
}
/* Section label: muted tiny uppercase caption. Replaces the old colored-
   left-border tag (PLAY/LEARN) that read as dev-dashboard chrome. */
.home-section-label {
    display: block;
    font-family: var(--font-display);
    color: var(--text-muted);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 2px;
    text-transform: uppercase;
    margin-bottom: 8px;
}

@media (max-width: 900px) {
    .home-mode-cards { grid-template-columns: 1fr; }
}

/* ============================================
   Home — "Welcome back" strip (logged-in players)
   Compact single-line bar under the hero CTA. Prior iteration was a
   glass card with multiple stat cells which duplicated the profile page.
   ============================================ */

.home-since-card {
    display: inline-flex;
    align-items: center;
    gap: 0.75rem;
    margin: 1.25rem auto 0;
    padding: 8px 16px;
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(255, 255, 255, 0.06);
    border-radius: 999px;
    font-size: 13px;
    color: var(--text-secondary);
    flex-wrap: wrap;
    justify-content: center;
}
.home-since-text strong {
    font-family: var(--font-display);
    color: var(--accent);
    font-variant-numeric: tabular-nums;
    margin: 0 2px;
}
.home-since-meta {
    color: var(--text-muted);
    font-size: 11px;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    margin-right: 2px;
}
.home-since-sep {
    color: var(--text-muted);
    margin: 0 4px;
}
.home-since-view {
    font-family: var(--font-display);
    font-size: 11px;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: var(--accent) !important;
    text-decoration: none;
}
.home-since-view:hover { color: var(--accent-hover) !important; }

/* ============================================
   Leaderboard podium delta badges
   ============================================ */

.podium-delta {
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 1px;
    padding: 2px 8px;
    border-radius: 3px;
    margin-top: 6px;
    display: inline-block;
}
.podium-delta.up { color: var(--success); background: rgba(138, 255, 138, 0.08); }
.podium-delta.down { color: var(--danger); background: rgba(255, 107, 107, 0.08); }

/* ============================================
   LinkGuide — "Before you connect" pre-flight
   ============================================ */

.link-preflight {
    padding: 24px;
    margin: 0 auto 24px;
    max-width: 700px;
    border: 1px solid var(--border-accent-strong);
    border-radius: 5px;
    background: var(--accent-dim);
}
.link-preflight-label {
    font-family: var(--font-display);
    color: var(--accent);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 3px;
    text-transform: uppercase;
    margin-bottom: 8px;
    display: block;
}
.link-preflight h2 {
    font-family: var(--font-display);
    color: var(--text-primary);
    font-size: 20px;
    margin-bottom: 8px;
}
.link-preflight-steps {
    padding-left: 20px;
    margin: 12px 0;
    color: var(--text-secondary);
    font-size: 14px;
    line-height: 1.7;
}
.link-preflight-note {
    color: var(--text-muted);
    font-size: 12px;
    font-style: italic;
}

/* ============================================
   HowToPlay — mode picker (3 card grid)
   ============================================ */

.htp-mode-picker {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
    margin: 0 auto 32px;
    max-width: 700px;
}
.htp-mode-card {
    padding: 20px;
    border: 1px solid var(--border-accent);
    border-radius: 5px;
    background: var(--bg-panel);
    text-decoration: none;
    transition: all 0.15s ease;
    display: block;
}
.htp-mode-card:hover {
    transform: translateY(-2px);
    border-color: var(--border-accent-strong);
}
.htp-mode-card h3 {
    font-family: var(--font-display);
    color: var(--text-primary);
    font-size: 20px;
    margin: 10px 0 6px;
    letter-spacing: 1px;
}
.htp-mode-card p { color: var(--text-secondary); font-size: 13px; }
.htp-mode-card-badge {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 3px;
    font-family: var(--font-display);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 2px;
    text-transform: uppercase;
}
.htp-mode-card-mm .htp-mode-card-badge { background: var(--accent-dim); color: var(--accent); }
.htp-mode-card-ta .htp-mode-card-badge { background: rgba(180, 156, 255, 0.15); color: var(--accent-purple); }
@media (max-width: 900px) {
    .htp-mode-picker { grid-template-columns: 1fr; }
}

/* ============================================
   Servers page — mode explainer chips
   ============================================ */

.servers-mode-chip {
    padding: 10px 16px;
    margin: 16px 0 10px;
    border-radius: 4px;
    font-size: 13px;
    font-family: var(--font-body);
    color: var(--text-secondary);
    display: flex;
    align-items: center;
    gap: 12px;
    border-left: 3px solid;
}
.servers-chip-label {
    font-family: var(--font-display);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 2px;
    text-transform: uppercase;
    padding: 3px 8px;
    border-radius: 3px;
    flex-shrink: 0;
}
.servers-mode-chip.ta { border-color: var(--accent-purple); background: rgba(180,156,255,0.04); }
.servers-mode-chip.ta .servers-chip-label { background: rgba(180,156,255,0.15); color: var(--accent-purple); }
.servers-mode-chip.community { border-color: var(--text-muted); background: rgba(255,255,255,0.02); }
.servers-mode-chip.community .servers-chip-label { background: rgba(255,255,255,0.08); color: var(--text-secondary); }

/* ============================================
   Queue page — 'Queued via Discord' badge
   ============================================ */

.queue-source-badge {
    display: inline-block;
    padding: 2px 8px;
    font-family: var(--font-display);
    font-size: 10px;
    letter-spacing: 1px;
    text-transform: uppercase;
    background: #5865F2;
    color: #fff;
    border-radius: 3px;
    margin-left: 6px;
}

/* ============================================
   Player profile — focus pass
   ============================================ */

.profile-form-card, .profile-rankings-card {
    background: var(--bg-panel);
    border-radius: 5px;
    padding: 16px 20px;
    margin: 0 0 16px;
}
.profile-card-title {
    font-family: var(--font-display);
    color: var(--text-tertiary);
    font-size: 12px;
    letter-spacing: 2px;
    text-transform: uppercase;
    margin-bottom: 10px;
}
.profile-card-title-inline {
    font-family: var(--font-display);
    color: var(--text-tertiary);
    font-size: 11px;
    letter-spacing: 2px;
    text-transform: uppercase;
    margin-right: 8px;
}
.profile-form-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.form-chip {
    width: 28px;
    height: 28px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 12px;
    border-radius: 4px;
}
.form-chip.win { background: rgba(138, 255, 138, 0.18); color: var(--success); }
.form-chip.loss { background: rgba(255, 107, 107, 0.15); color: var(--danger); }
.profile-rankings-row { display: flex; gap: 32px; flex-wrap: wrap; }
.ranking-stat { display: flex; flex-direction: column; align-items: flex-start; }
.ranking-value {
    font-family: var(--font-display);
    font-size: 22px;
    color: var(--text-primary);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}
.ranking-label {
    color: var(--text-muted);
    font-size: 11px;
    letter-spacing: 1px;
    text-transform: uppercase;
    margin-top: 2px;
}
.profile-car-summary {
    color: var(--text-secondary);
    font-size: 13px;
    margin-top: 12px;
    max-width: 700px;
    margin-left: auto;
    margin-right: auto;
}

/* ============================================
   Community Hub (Task P0-4 / P0-5) — tenant-scoped driver profile +
   head-to-head extras. Accent-aware (the host page wraps in
   <TenantBrandedLayout> so --accent is the operator's color).
   ============================================ */

/* Stat-card value that highlights a non-zero count (e.g. course records held). */
.stat-card .stat-value.accent-value { color: var(--accent); }

/* Win/loss pill in the recent-matches feed. */
.result-pill {
    display: inline-block; padding: 1px 8px; border-radius: 3px;
    font-family: var(--font-display); font-size: 10px; font-weight: 700;
    letter-spacing: 0.5px; text-transform: uppercase;
}
.result-pill.win { background: rgba(138, 255, 138, 0.18); color: var(--success); }
.result-pill.loss { background: rgba(255, 107, 107, 0.15); color: var(--danger); }

/* Gap-to-course-record cell on the per-pass best grid. */
.gap-leader {
    font-family: var(--font-display); font-size: 10px; font-weight: 700;
    letter-spacing: 0.5px; text-transform: uppercase; color: var(--accent-purple);
}
.gap-behind { color: var(--text-muted); font-variant-numeric: tabular-nums; }

/* Rivals / mini head-to-head module — card grid linking into the full H2H page. */
.rivals-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 12px; margin: 0 0 24px;
}
.rival-card {
    display: block; background: var(--bg-panel); border-radius: 5px;
    padding: 14px 16px; text-decoration: none; color: var(--text-primary) !important;
    border: 1px solid var(--border); transition: border-color 0.12s ease, background 0.12s ease;
}
.rival-card:hover { border-color: var(--border-accent-strong); background: var(--bg-hover); }
.rival-card-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; margin-bottom: 6px; }
.rival-name {
    font-family: var(--font-display); font-weight: 600; font-size: 14px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 14ch;
}
.rival-meetings { font-size: 11px; color: var(--text-muted); white-space: nowrap; }
.rival-record { font-size: 13px; font-weight: 700; margin-bottom: 8px; }
.rival-record .rival-w { color: var(--success); }
.rival-record .rival-l { color: var(--danger); }
.rival-bar { display: flex; height: 6px; border-radius: 3px; overflow: hidden; background: var(--bg-elevated); }
.rival-bar-win { background: var(--success); transition: width 0.3s ease; }
.rival-bar-loss { background: var(--danger); transition: width 0.3s ease; }

/* ============================================
   MyProfile — recent activity card + quick actions
   ============================================ */

.my-since-card {
    padding: 16px 20px;
    margin: 0 auto 16px;
    max-width: 700px;
    border-radius: 5px;
    background: var(--bg-panel);
}
.my-since-label {
    display: block;
    font-family: var(--font-display);
    color: var(--text-tertiary);
    font-size: 11px;
    letter-spacing: 2px;
    text-transform: uppercase;
    margin-bottom: 10px;
}
.my-since-stats {
    display: flex;
    gap: 28px;
    flex-wrap: wrap;
    align-items: baseline;
}
.my-since-stats > div {
    display: flex;
    flex-direction: column;
}
.my-since-num {
    font-family: var(--font-display);
    font-size: 22px;
    color: var(--text-primary);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}
.my-since-meta {
    color: var(--text-muted);
    font-size: 11px;
    letter-spacing: 1px;
    text-transform: uppercase;
    margin-top: 2px;
}
.my-actions-strip {
    display: flex;
    gap: 8px;
    max-width: 700px;
    margin: 0 auto 16px;
    flex-wrap: wrap;
}

/* Quick actions now live inside the .profile-header card (top-right) so the
   page has one clean top block instead of a header + detached strip below. */
.profile-header-self { justify-content: space-between; flex-wrap: wrap; }
.profile-header-self .profile-info { flex: 1 1 auto; min-width: 220px; }
.profile-header-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-left: auto; }
@media (max-width: 768px) {
    .profile-header-self { flex-direction: column; text-align: center; }
    .profile-header-actions { margin-left: 0; justify-content: center; }
}

/* Rankings card: use a grid that matches the stats-grid pattern so a single
   stat no longer sits forlorn in the left corner of a wide card. */
.profile-rankings-card .profile-rankings-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
    gap: 18px;
}
.profile-rankings-card .ranking-stat { align-items: flex-start; }

/* Car summary: give "Most driven" its own mini-card so it stops floating as
   loose paragraph text. */
.profile-car-summary {
    background: var(--bg-panel);
    border-radius: 5px;
    padding: 10px 16px;
    max-width: none;
    margin: 0 0 16px;
    display: flex;
    align-items: baseline;
    gap: 10px;
    flex-wrap: wrap;
}
.my-action-btn {
    padding: 6px 14px;
    font-family: var(--font-display);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 1px;
    text-transform: uppercase;
    border: 1px solid var(--border-accent);
    border-radius: 4px;
    color: var(--text-secondary);
    text-decoration: none;
    transition: all 0.12s ease;
}
.my-action-btn:hover {
    border-color: var(--border-accent-strong);
    color: var(--accent);
}

/* ============================================
   Phase 7 additions — P2 page polish
   ============================================ */

/* Privacy / Terms — cross-link footer line */
.guide-see-also {
    font-size: 13px;
    color: var(--text-muted);
    border-top: 1px solid var(--border-subtle, rgba(255,255,255,0.06));
    padding-top: 0.75rem;
    margin-top: 0;
}
.guide-see-also a {
    color: var(--accent);
    text-decoration: none;
}
.guide-see-also a:hover { text-decoration: underline; }

/* ============================================
   Global responsive floor — prevent horizontal scroll
   These rules are safe to cascade on top of any
   existing @media rules; most classes already have
   per-component breakpoints above, so this only
   catches any gaps.
   ============================================ */

/* Ensure the guide tables (HowToPlay keybinds / bot
   commands) scroll horizontally rather than overflow. */
.guide-table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }

@media (max-width: 640px) {
    .pub-table-wrap, .table-wrap { overflow-x: auto; }
    .home-mode-cards,
    .htp-mode-picker { grid-template-columns: 1fr; gap: 12px; }
    .my-since-stats,
    .profile-rankings-row { gap: 16px; }
    .servers-mode-chip { flex-wrap: wrap; }
}

/* ──────────────────────────────────────────────
   Reconnect modal
   ──────────────────────────────────────────────
   Targets Blazor's framework-managed element. The framework
   toggles classes on #components-reconnect-modal:
     .components-reconnect-show     — silent retry in progress
     .components-reconnect-hide     — connection restored
     .components-reconnect-failed   — retries exhausted
     .components-reconnect-rejected — server refused the circuit
   We keep the modal hidden during the .show state so the first
   ~3s of automatic retries are silent, and only surface the UI
   on .failed or .rejected. */
.kott-reconnect-modal {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 10000;
    background: rgba(0, 0, 0, 0.72);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    align-items: center;
    justify-content: center;
    padding: 24px;
    font-family: var(--font-body);
    color: var(--text-primary);
}

.kott-reconnect-modal.components-reconnect-failed,
.kott-reconnect-modal.components-reconnect-rejected {
    display: flex;
}

.kott-reconnect-card {
    max-width: 420px;
    width: 100%;
    background: var(--bg-panel-solid);
    border: 1px solid var(--border-accent-strong);
    border-radius: 6px;
    padding: 28px 32px;
    text-align: center;
    box-shadow: 0 0 0 1px rgba(0, 224, 255, 0.08), 0 20px 60px rgba(0, 0, 0, 0.6);
}

.kott-reconnect-spinner {
    width: 36px;
    height: 36px;
    margin: 0 auto 18px;
    border: 2px solid rgba(0, 224, 255, 0.18);
    border-top-color: var(--accent);
    border-radius: 50%;
    animation: kott-reconnect-spin 0.9s linear infinite;
}

@keyframes kott-reconnect-spin {
    to { transform: rotate(360deg); }
}

.kott-reconnect-title {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: var(--text-xl);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--accent);
    margin: 0 0 10px;
}

.kott-reconnect-text {
    font-size: var(--text-base);
    color: var(--text-secondary);
    margin: 0 0 18px;
    line-height: 1.5;
}

/* Show only the message that matches the current state. */
.kott-reconnect-text-default,
.kott-reconnect-text-failed,
.kott-reconnect-text-rejected { display: none; }

.kott-reconnect-modal.components-reconnect-failed .kott-reconnect-text-failed { display: block; }
.kott-reconnect-modal.components-reconnect-rejected .kott-reconnect-text-rejected { display: block; }

.kott-reconnect-button {
    appearance: none;
    border: 1px solid var(--border-accent-strong);
    background: var(--accent-dim);
    color: var(--accent);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: var(--text-base);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 10px 22px;
    border-radius: 4px;
    cursor: pointer;
    transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}

.kott-reconnect-button:hover,
.kott-reconnect-button:focus-visible {
    background: var(--accent);
    color: #001318;
    border-color: var(--accent);
    /* outline removed 2026-06-08 — was suppressing the keyboard focus ring on
       the only control after a circuit error; the global .public-shell
       button:focus-visible ring now applies. */
}

/* ─────────────────────────────────────────────────────────────────
   ErrorBoundary fallback (App.razor wraps <Routes> in this).
   Renders inline (no overlay) when a render-time exception escapes
   the page itself — distinct from the reconnect modal which is for
   SignalR-circuit disconnects. Both share the cyan/dark aesthetic.
   ───────────────────────────────────────────────────────────────── */
.kott-error-boundary {
    min-height: 60vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 60px 24px;
    font-family: var(--font-body);
    color: var(--text-primary);
}

.kott-error-card {
    max-width: 480px;
    width: 100%;
    background: var(--bg-panel-solid);
    border: 1px solid var(--border-accent-strong);
    border-radius: 6px;
    padding: 36px 40px;
    text-align: center;
    box-shadow: 0 0 0 1px rgba(0, 224, 255, 0.08), 0 20px 60px rgba(0, 0, 0, 0.6);
}

.kott-error-card h1 {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: var(--text-2xl);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--accent);
    margin: 0 0 14px;
}

.kott-error-card p {
    font-size: var(--text-base);
    color: var(--text-secondary);
    margin: 0 0 22px;
    line-height: 1.5;
}

.kott-error-card button {
    appearance: none;
    border: 1px solid var(--border-accent-strong);
    background: var(--accent-dim);
    color: var(--accent);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: var(--text-base);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 10px 22px;
    border-radius: 4px;
    cursor: pointer;
    transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}

.kott-error-card button:hover,
.kott-error-card button:focus-visible {
    background: var(--accent);
    color: #001318;
    border-color: var(--accent);
    /* outline removed 2026-06-08 — see .kott-reconnect-button above; keyboard
       users need a focus ring on the error-boundary's only control. */
}

.kott-error-link {
    margin-top: 18px !important;
    margin-bottom: 0 !important;
    font-size: var(--text-sm) !important;
}

.kott-error-link a {
    color: var(--text-muted);
    text-decoration: none;
    border-bottom: 1px dashed var(--border-subtle);
}

.kott-error-link a:hover {
    color: var(--accent);
    border-bottom-color: var(--accent);
}

/* ─────────────────────────────────────────────────────────────────
   Lap detail — unified telemetry view (LapTelemetryView.razor).
   Three coordinated canvases with shared playhead. Layout pattern
   borrowed from MoTeC i2 / AiM RaceStudio: stacked traces with a
   heatmap track map sidebar, position scrubber underneath.
   ───────────────────────────────────────────────────────────────── */
.lap-telemetry-view {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px;
    background: var(--bg-panel-solid, #0d1418);
    border: 1px solid var(--border-accent-strong, rgba(0, 224, 255, 0.18));
    border-radius: 6px;
    margin-top: 16px;
    overflow-x: auto;
}

.lap-telemetry-view canvas {
    display: block;
    background: #0a0a0a;
    border-radius: 4px;
    max-width: 100%;
}

.ltv-hero {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: 12px;
    align-items: start;
}

.ltv-map {
    cursor: crosshair;
    width: 100%;
    /* Shorter than the capture canvas (900x640) so the map fills the column
       width at roughly the stats-sidebar height — keeps the hero a balanced
       full-width row. The JS fits the track to the canvas, so no distortion. */
    aspect-ratio: 900 / 500;
}

.ltv-map-wrap {
    position: relative;
    min-width: 0;
}

/* Map colour-mode toggle — segmented control overlaid on the map's top-left
   (the heat legend sits top-right). Speed / Gas-Brake / Slip. */
.ltv-heat-toggle {
    position: absolute;
    top: 10px;
    left: 10px;
    display: inline-flex;
    gap: 2px;
    padding: 2px;
    background: rgba(0, 0, 0, 0.45);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 4px;
    backdrop-filter: blur(4px);
    z-index: 2;
}
.ltv-heat-toggle button {
    background: transparent;
    border: 0;
    color: #9aa6ad;
    font-family: var(--font-display);
    font-size: 11px;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    padding: 4px 9px;
    border-radius: 4px;
    cursor: pointer;
    transition: background 0.12s, color 0.12s;
}
.ltv-heat-toggle button:hover { color: #d6dee3; background: rgba(0, 224, 255, 0.08); }
.ltv-heat-toggle button.active { background: rgba(0, 224, 255, 0.16); color: #00e0ff; }

/* Lap summary overlay — driver / car / time / sectors pinned to the map's
   bottom-left corner. A DOM overlay (not canvas), so it stays crisp and a
   constant size regardless of the map's wheel-zoom. pointer-events:none so it
   never intercepts map pan / Shift-drag / click gestures underneath it. */
.ltv-map-meta {
    position: absolute;
    left: 10px;
    bottom: 10px;
    width: max-content;
    max-width: 215px;
    padding: 7px 9px;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    border: 1px solid rgba(255, 255, 255, 0.1);
    border-radius: 7px;
    pointer-events: none;
    line-height: 1.25;
}
.ltv-map-meta-driver {
    font-family: var(--font-display);
    font-size: 14px;
    font-weight: 700;
    color: #fff;
    letter-spacing: 0.01em;
}
.ltv-map-meta-car {
    font-size: 9.5px;
    color: #9aa6ad;
    margin-top: 1px;
    word-break: break-word;
}
.ltv-map-meta-time {
    display: flex;
    align-items: baseline;
    gap: 6px;
    margin-top: 4px;
}
.ltv-map-meta-laptime {
    font-family: var(--font-display);
    font-size: 17px;
    font-weight: 700;
    color: #00e0ff;
    font-variant-numeric: tabular-nums;
}
.ltv-map-meta-sub {
    font-size: 9px;
    color: #859096;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-top: 2px;
}
.ltv-map-meta-sectors {
    margin-top: 6px;
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.ltv-map-meta-sectors > div {
    display: flex;
    justify-content: space-between;
    gap: 16px;
    font-size: 10.5px;
    font-variant-numeric: tabular-nums;
}
.ltv-map-meta-sectors > div > span:first-child { color: #7c8890; }
.ltv-map-meta-sectors > div > span:last-child { color: #d6dee3; }
.ltv-badge-pb {
    background: rgba(0, 224, 255, 0.16);
    color: #00e0ff;
    font-size: 10px;
    font-weight: 700;
    padding: 1px 6px;
    border-radius: 4px;
    letter-spacing: 0.05em;
}
.ltv-badge-invalid {
    background: rgba(255, 90, 90, 0.16);
    color: #ff7a7a;
    font-size: 10px;
    font-weight: 700;
    padding: 1px 6px;
    border-radius: 4px;
    letter-spacing: 0.05em;
}

.ltv-stack {
    cursor: ew-resize;
    width: 100%;
    aspect-ratio: 1232 / 320;
}

.ltv-scrubber {
    cursor: pointer;
    width: 100%;
    aspect-ratio: 1232 / 42;
}

/* Δ-vs-PB strip — the red/green band painted above the trace stack when
   the user has toggled the PB compare overlay on. Hidden when no PB is
   loaded (the canvas element isn't rendered in that case). */
.ltv-delta-strip {
    width: 100%;
    aspect-ratio: 1232 / 32;
    margin-bottom: 4px;
    border-radius: 4px;
    overflow: hidden;
}

@media (max-width: 920px) {
    /* On narrow viewports, drop the stats column underneath the map
       rather than letting the map shrink uselessly. */
    .ltv-hero { grid-template-columns: 1fr; }
}

/* Stats panel — point-in-time HTML readouts that update on every playhead
   scrub. Sits beside the map in the hero row as a vertical sidebar. */
.ltv-stats {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.ltv-stats-side {
    background: rgba(0, 0, 0, 0.4);
    border: 1px solid rgba(0, 224, 255, 0.10);
    border-radius: 4px;
    padding: 14px 14px 16px;
    /* Hug content (was a fixed 640px box that left a large empty area below
       the stats). The map is the tallest element and defines the row height. */
    height: auto;
    align-self: start;
}

.ltv-stats-block {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.ltv-stats-title {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 11px;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--accent, #00e0ff);
    margin: 0 0 4px;
    padding-bottom: 4px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}

.ltv-stats-row {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    align-items: baseline;
}

.ltv-stats-row-vert {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px 18px;
}

.ltv-tyre-grid {
    display: grid;
    grid-template-columns: 50px repeat(4, 1fr);
    gap: 6px 8px;
    align-items: center;
}

.ltv-stat {
    display: inline-flex;
    flex-direction: column;
    align-items: flex-start;
    min-width: 60px;
}

.ltv-stat-label {
    /* Body font (Inter) at 11px reads more clearly than display font at 9px —
       Rajdhani's "G" character became visually ambiguous with "B" at small
       sizes, which made the GEAR readout misread as BEAR. */
    font-family: var(--font-body, 'Inter', sans-serif);
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-muted, #888);
    line-height: 1;
    margin-bottom: 4px;
    white-space: nowrap;
}

.ltv-stat-value {
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 20px;
    color: var(--text-primary, #f0f0f0);
    line-height: 1;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.ltv-stat-unit {
    font-size: 12px;
    font-weight: 400;
    color: var(--text-muted, #888);
    margin-left: 2px;
}

.ltv-stat-suspect .ltv-stat-value {
    color: #c46060;
}

.ltv-stat-warn {
    color: #ff6b6b;
    font-size: 11px;
    margin-right: 2px;
}

.ltv-debug {
    margin-top: 14px;
    border-top: 1px dashed rgba(0, 224, 255, 0.18);
    padding-top: 8px;
}

.ltv-debug-toggle {
    background: transparent;
    border: 1px solid rgba(0, 224, 255, 0.18);
    color: #99c8d6;
    font-family: var(--font-mono, ui-monospace, "Cascadia Code", Consolas, monospace);
    font-size: 11px;
    padding: 4px 10px;
    cursor: pointer;
    border-radius: 3px;
    letter-spacing: 0.04em;
}

.ltv-debug-toggle:hover {
    border-color: rgba(0, 224, 255, 0.4);
    color: #c5e6ed;
}

.ltv-debug-hint {
    color: #5c7480;
    margin-left: 10px;
    font-size: 10px;
    letter-spacing: 0;
}

.ltv-debug-body {
    margin-top: 10px;
    padding: 10px 12px;
    background: rgba(0, 0, 0, 0.45);
    border: 1px solid rgba(0, 224, 255, 0.12);
    border-radius: 4px;
}

.ltv-debug-explainer {
    color: #88a0aa;
    font-size: 11px;
    margin-bottom: 8px;
    line-height: 1.5;
}

.ltv-debug-table {
    width: 100%;
    border-collapse: collapse;
    font-family: var(--font-mono, ui-monospace, "Cascadia Code", Consolas, monospace);
    font-size: 11px;
}

.ltv-debug-table th,
.ltv-debug-table td {
    padding: 3px 8px;
    text-align: left;
    border-bottom: 1px solid rgba(255, 255, 255, 0.04);
}

.ltv-debug-table th {
    color: #00e0ff;
    font-weight: 500;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    font-size: 10px;
}

.ltv-debug-table td:nth-child(2),
.ltv-debug-table td:nth-child(3) {
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: #d6dde0;
}

.ltv-debug-table td:nth-child(4) {
    color: #6f8088;
    font-size: 10px;
}

.ltv-debug-table td:nth-child(5) {
    text-align: center;
    color: #6fbf8f;
}

.ltv-debug-row-suspect {
    background: rgba(255, 100, 100, 0.06);
}

.ltv-debug-row-suspect td:nth-child(2),
.ltv-debug-row-suspect td:nth-child(3) {
    color: #ff8e8e;
}

.ltv-debug-row-suspect td:nth-child(5) {
    color: #ff6b6b;
}

.ltv-stat-group {
    font-family: var(--font-display);
    font-size: 10px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--accent, #00e0ff);
    align-self: center;
    padding-right: 4px;
    min-width: 90px;
}

/* ──────────────────────────────────────────────────────────────────
   Lap-detail trace-stack channel picker (LapTelemetryView.razor)
   "+ Add channel" button + chip row + popover grid + availability
   badges. Sits between the trace-stack canvas and the scrubber.
   ────────────────────────────────────────────────────────────────── */
.ltv-add-channel-row {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
    padding: 6px 0;
}

.ltv-add-channel-btn {
    background: rgba(0, 224, 255, 0.08);
    border: 1px dashed rgba(0, 224, 255, 0.4);
    color: var(--accent, #00e0ff);
    font-family: var(--font-display);
    font-size: 11px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 5px 12px;
    border-radius: 4px;
    cursor: pointer;
}

.ltv-add-channel-btn:hover { background: rgba(0, 224, 255, 0.18); }

.ltv-added-chip {
    background: transparent;
    border: 1px solid;
    font-family: var(--font-display);
    font-size: 11px;
    padding: 4px 10px;
    border-radius: 7px;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.ltv-added-chip-x { font-size: 14px; opacity: 0.7; }
.ltv-added-chip:hover .ltv-added-chip-x { opacity: 1; }

.ltv-picker {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 4px;
    padding: 10px;
    background: rgba(0, 0, 0, 0.5);
    border: 1px solid rgba(0, 224, 255, 0.18);
    border-radius: 4px;
    margin-top: 4px;
}

.ltv-picker-item {
    background: transparent;
    border: 1px solid rgba(255, 255, 255, 0.08);
    color: var(--text-primary, #ddd);
    text-align: left;
    padding: 8px 10px;
    border-radius: 4px;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
}

.ltv-picker-item:hover { background: rgba(0, 224, 255, 0.06); border-color: rgba(0, 224, 255, 0.24); }
.ltv-picker-title { flex: 1; font-weight: 500; }
.ltv-picker-unit { color: #888; font-size: 11px; }

.ltv-badge {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
}

.ltv-badge-green { background: #8aff8a; }
.ltv-badge-amber { background: #ffb347; }
.ltv-badge-red   { background: #ff6b6b; }

/* PB-compare toggle (appears in stats sidebar when a PB exists). */
.ltv-compare-block .ltv-stats-title {
    color: #ffb347;
    font-variant-numeric: tabular-nums;
}

.ltv-compare-toggle {
    background: rgba(255, 179, 71, 0.08);
    border: 1px solid rgba(255, 179, 71, 0.4);
    color: #ffb347;
    font-family: var(--font-display);
    font-size: 11px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    padding: 6px 12px;
    border-radius: 4px;
    cursor: pointer;
    width: 100%;
}

.ltv-compare-toggle:hover { background: rgba(255, 179, 71, 0.18); }
.ltv-compare-toggle.ltv-compare-on { background: rgba(255, 179, 71, 0.28); border-color: #ffb347; }

/* Topnav "Admin →" pill — appears when the visitor is signed in as admin.
   Distinct accent (orange) so it's obviously not a player feature. Replaces
   the misleading "Login with Steam" button admins were seeing. */
.admin-link {
    background: rgba(255, 179, 71, 0.08);
    color: #ffb347 !important;
    border: 1px solid rgba(255, 179, 71, 0.4);
}
.admin-link:hover {
    background: rgba(255, 179, 71, 0.18);
    border-color: #ffb347;
}

.mobilenav-admin-link {
    color: #ffb347 !important;
    font-weight: 600;
}

/* ============================================================
   Phase 8 — multi-tenant public surface (Task 8.1).

   Branding boundary (spec § 15.2):
     • .tenant-themed scopes operator overrides (--accent, logo) to
       its descendants only. KOTT-central pages and the
       Hosted-on-KOTT badge live OUTSIDE it and inherit :root.
     • .hosted-on-kott-badge ALWAYS uses literal KOTT cyan, never
       var(--accent), so an operator can't recolor or hide it.
   ============================================================ */

.tenant-themed {
    /* Container is purely for scoping the inline --accent / logo
       overrides emitted by the TenantBrandedLayout. No padding/margin
       so it lays out identically to system-tenant pages. */
    display: contents;
}

/* Identity ribbon at the top of /community/<slug>/... pages. Lives
   outside .tenant-themed so its colors are non-overridable. */
.tenant-identity-ribbon {
    background: rgba(0, 0, 0, 0.85);
    border-bottom: 1px solid rgba(255, 255, 255, 0.06);
    padding: 6px 24px;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    font-family: var(--font-display);
    font-size: 11px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.tenant-identity-ribbon-name {
    color: var(--text-secondary);
    font-weight: 600;
}

.tenant-identity-ribbon-sep {
    opacity: 0.4;
}

/* The mandatory "Hosted on KOTT" badge. Pinned colors — does not
   read --accent and is not stylable from inside .tenant-themed. */
.hosted-on-kott-badge {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 10px;
    border: 1px solid rgba(0, 224, 255, 0.30);
    border-radius: 4px;
    font-family: 'Rajdhani', 'Segoe UI', sans-serif;
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    text-decoration: none;
    /* Hard-coded colors — never use var(--accent) here, the whole point
       is that this badge is never recolored by tenant overrides. */
    color: #9ca3af !important;
    background: rgba(0, 0, 0, 0.4);
    transition: border-color 0.12s ease, color 0.12s ease;
}

.hosted-on-kott-badge:hover {
    border-color: #00e0ff;
    color: #00e0ff !important;
}

.hosted-on-kott-badge-text {
    opacity: 0.7;
}

.hosted-on-kott-badge-brand {
    color: #00e0ff !important;
    letter-spacing: 1.5px;
}

/* Tenant home hero — mirrors the public Home.razor cyan-on-black
   styling but reads --accent so it picks up the operator's color. */
.tenant-home-hero {
    text-align: center;
    padding: 48px 24px 36px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.04);
    margin-bottom: 24px;
}

.tenant-home-hero h1 {
    font-family: var(--font-display);
    font-size: 2.5rem;
    color: var(--accent);
    margin-bottom: 8px;
    letter-spacing: 1px;
}

.tenant-home-hero .tagline {
    color: var(--text-secondary);
    font-size: 16px;
    margin-bottom: 12px;
}

.tenant-home-hero .description {
    color: var(--text-tertiary);
    max-width: 640px;
    margin: 0 auto 16px;
    font-size: 14px;
    line-height: 1.7;
}

.tenant-home-hero .join-cta {
    display: inline-block;
    margin-top: 8px;
}

/* 2026-05-07 — community detail expansion. Socials icon row sits
   between the description + the Join Community CTA on
   /community/{slug}. Each icon is a 24×24 SVG colored via
   currentColor so per-platform brand colors land on hover. */
.tenant-socials {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 12px;
    margin: 16px 0 8px;
}

.tenant-socials .social-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.04);
    color: var(--text-secondary);
    transition: background 120ms ease, color 120ms ease, transform 120ms ease;
    text-decoration: none;
}

.tenant-socials .social-link:hover,
.tenant-socials .social-link:focus-visible {
    background: rgba(255, 255, 255, 0.08);
    transform: translateY(-1px);
}

/* Per-platform brand-color hover — currentColor in the SVGs picks
   these up. Resting state stays neutral so the row reads as a
   single visual unit; the brand color emerges on intent. */
.tenant-socials .social-link.discord:hover,
.tenant-socials .social-link.discord:focus-visible {
    color: #5865f2;
}

.tenant-socials .social-link.twitter:hover,
.tenant-socials .social-link.twitter:focus-visible {
    color: #ffffff;
}

.tenant-socials .social-link.youtube:hover,
.tenant-socials .social-link.youtube:focus-visible {
    color: #ff0000;
}

.tenant-socials .social-link.twitch:hover,
.tenant-socials .social-link.twitch:focus-visible {
    color: #9146ff;
}

/* Server list section on /community/{slug} — same .server-grid as
   Public/Servers.razor, just scoped under the tenant section. */
.tenant-servers {
    margin-top: 32px;
}

.tenant-servers .page-title {
    margin-bottom: 16px;
}

/* ============================================================
   Community Hub (Task F7) — per-community sub-nav tab bar
   ============================================================ */

.community-subnav {
    display: flex;
    gap: 4px;
    align-items: center;
    margin: 0 0 24px;
    padding-bottom: 2px;
    border-bottom: 1px solid var(--border);
    overflow-x: auto;            /* horizontal scroll-safe on narrow screens */
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;       /* Firefox — hide the scrollbar, keep scroll */
}

.community-subnav::-webkit-scrollbar {
    display: none;               /* WebKit — hide the scrollbar, keep scroll */
}

.subnav-tab {
    flex-shrink: 0;
    font-family: var(--font-display);
    font-size: 13px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.6px;
    color: var(--text-muted);
    text-decoration: none;
    padding: 10px 14px;
    border-bottom: 2px solid transparent;
    margin-bottom: -1px;         /* overlap the container border so the active underline aligns */
    white-space: nowrap;
    transition: color 0.12s ease, border-color 0.12s ease;
}

.subnav-tab:hover,
.subnav-tab:focus-visible {
    color: var(--text-primary);
}

.subnav-tab.active {
    color: var(--accent);
    border-bottom-color: var(--accent);
}

/* --- Compact community header (2026-06-20) — logo + name above the tabs,
   replacing the old oversized centered .community-hero. Rendered by
   CommunitySubNav whenever the page supplies Branding. The extras row
   (stat line + socials) renders on the Overview only. --- */
.community-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px 20px;
    margin: 4px 0 14px;
}

.community-header-id {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    min-width: 0;            /* let a long name ellipsize instead of overflowing */
}

.community-header-logo {
    width: 38px;
    height: 38px;
    object-fit: contain;
    border-radius: 5px;
    background: rgba(0, 0, 0, 0.3);
    padding: 4px;
    flex-shrink: 0;
}

.community-header-name {
    font-family: var(--font-display);
    font-size: 1.6rem;
    font-weight: 700;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-loose);
    line-height: 1.1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Operator socials sit opposite the name, vertically centered with it. */
.community-header .tenant-socials { margin-top: 0; }

/* --- Operator-admin hub header + nav (2026-06-26) — rendered by
   <OperatorAdminNav> at the top of every /community/{slug}/admin/* page. Same
   visual family as .community-header but carries an "Operator admin" kicker so
   the operator always knows they're on the management surface, plus a
   view-public-page escape hatch opposite the name. --- */
.operator-admin-header {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px 20px;
    margin: 4px 0 14px;
}

.operator-admin-id {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    min-width: 0;
}

.operator-admin-logo {
    width: 38px;
    height: 38px;
    object-fit: contain;
    border-radius: 5px;
    background: rgba(0, 0, 0, 0.3);
    padding: 4px;
    flex-shrink: 0;
}

.operator-admin-titles {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.operator-admin-kicker {
    font-family: var(--font-display);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 1.4px;
    color: var(--text-muted);
    line-height: 1.2;
}

.operator-admin-name {
    font-family: var(--font-display);
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-loose);
    line-height: 1.1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The operator nav can run long (7+ tabs) — keep it visually distinct from the
   public hub subnav with a touch more breathing room below. */
.operator-subnav { margin-bottom: 20px; }

/* Rich layout picker — one card per (track) layout */
.layout-card-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap: 10px; margin: 8px 0 12px;
}
.layout-card {
    display: flex; flex-direction: column; gap: 6px; text-align: left; cursor: pointer;
    background: rgba(255, 255, 255, 0.03); border: 1px solid var(--border);
    border-radius: 5px; padding: 8px; transition: border-color 0.12s ease, background 0.12s ease;
}
.layout-card:hover { border-color: var(--accent-dim, var(--accent)); background: rgba(255, 255, 255, 0.05); }
.layout-card.selected { border-color: var(--accent); background: var(--accent-glow, rgba(0, 224, 255, 0.08)); }
.layout-card:disabled { opacity: 0.6; cursor: default; }
.layout-card-map {
    height: 94px; border-radius: var(--radius-sm); overflow: hidden;
    /* Lift the tile so the (black-on-transparent) map PNG has something to sit on. */
    background: linear-gradient(160deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.015));
    border: 1px solid var(--border);
    display: flex; align-items: center; justify-content: center;
    font-size: 10px; color: var(--text-tertiary);
}
/* The map PNGs are a dark outline on a transparent ground — invert flips the line to
   white so it's legible on the dark tile (brightness alone leaves black-on-black). */
.layout-card-map img { max-width: 100%; max-height: 100%; object-fit: contain; filter: invert(1) opacity(0.82); }
.layout-card-name {
    font-family: var(--font-display); font-size: 13.5px; font-weight: 600;
    color: var(--text-primary); line-height: 1.15;
}
.layout-card-id { font-family: var(--font-mono); font-size: 10px; color: var(--text-tertiary); }
.layout-card-stats { display: flex; flex-wrap: wrap; gap: 4px; }
.lc-stat {
    font-size: 10.5px; font-weight: 600; color: var(--text-muted);
    background: rgba(255, 255, 255, 0.06); border-radius: 3px; padding: 1px 5px;
    white-space: nowrap;
}
.layout-card-warn { font-size: 10.5px; font-weight: 600; color: var(--warn, #f4b740); }

/* Operator nav can run 7 tabs — fade the right edge on overflow so a clipped row
   signals "more →" instead of silently truncating (the scrollbar is hidden). */
.operator-subnav {
    -webkit-mask-image: linear-gradient(90deg, #000 88%, transparent);
    mask-image: linear-gradient(90deg, #000 88%, transparent);
}

/* Stack the card header on narrow screens so a long name isn't crushed to "Pro…". */
@media (max-width: 600px) {
    .operator-subnav { -webkit-mask-image: none; mask-image: none; flex-wrap: wrap; }
}

/* ============================================================
   Community Hub (P0) — Overview "trailer" + About + Servers
   Accent theming comes from --accent (scoped by TenantBrandedLayout).
   Never hardcodes the pinned semantic hexes — references the tokens.
   ============================================================ */

/* Generic tabular-number cell utility for ratings / W / L / times. */
.pub-table td.tabular { font-variant-numeric: tabular-nums; }

/* --- Live-now pulse indicator (hero stat + section headings) --- */
.live-pulse {
    display: inline-block;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--success);
    box-shadow: 0 0 0 0 rgba(138, 255, 138, 0.6);
    animation: community-live-pulse 1.8s ease-out infinite;
    flex-shrink: 0;
}

@keyframes community-live-pulse {
    0%   { box-shadow: 0 0 0 0 rgba(138, 255, 138, 0.5); }
    70%  { box-shadow: 0 0 0 7px rgba(138, 255, 138, 0); }
    100% { box-shadow: 0 0 0 0 rgba(138, 255, 138, 0); }
}

@media (prefers-reduced-motion: reduce) {
    .live-pulse { animation: none; }
}

/* --- Hero / trailer --- */
.community-hero {
    position: relative;
    border-radius: 6px;
    overflow: hidden;
    margin-bottom: 28px;
    border: 1px solid var(--border);
    /* Accent-driven gradient when no banner image is configured. */
    background:
        radial-gradient(120% 140% at 50% 0%, var(--accent-dim) 0%, transparent 55%),
        linear-gradient(180deg, rgba(8, 12, 18, 0.4) 0%, var(--bg-panel) 100%);
}

/* When a banner image is set, layer a dark overlay over it so text stays
   readable on ANY image. The image comes in via the --community-banner custom
   property set inline by the page (so no operator-controlled raw CSS). */
.community-hero.has-banner {
    background:
        linear-gradient(180deg, rgba(0, 0, 0, 0.45) 0%, rgba(0, 0, 0, 0.82) 100%),
        var(--community-banner) center / cover no-repeat;
}

.community-hero-overlay {
    position: relative;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 52px 24px 40px;
}

.community-hero-logo {
    width: 84px;
    height: 84px;
    object-fit: contain;
    border-radius: 7px;
    margin-bottom: 14px;
    background: rgba(0, 0, 0, 0.3);
    padding: 6px;
}

.community-hero-title {
    font-family: var(--font-display);
    font-size: 2.6rem;
    font-weight: 700;
    color: var(--accent);
    letter-spacing: var(--letter-spacing-loose);
    text-transform: uppercase;
    margin-bottom: 8px;
    line-height: 1.1;
}

.community-hero-tagline {
    color: var(--text-secondary);
    font-size: 16px;
    max-width: 620px;
    margin-bottom: 16px;
}

.community-hero-stats {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 10px 22px;
    margin-bottom: 8px;
}

.community-hero-stat {
    display: inline-flex;
    align-items: baseline;
    gap: 6px;
    font-family: var(--font-display);
}

.community-hero-stat.live-now,
.community-hero-stat.offline-now {
    align-items: center;
}

.community-hero-stat-num {
    font-size: 22px;
    font-weight: 700;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.community-hero-stat-label {
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-tight);
    color: var(--text-muted);
}

.community-hero-stat.live-now .community-hero-stat-label { color: var(--success); }

.community-hero-cta { margin-top: 16px; }

/* About-page hero is a touch shorter than the trailer. */
.about-hero .community-hero-overlay { padding: 44px 24px 32px; }

/* --- Generic community section + section header --- */
.community-section { margin-bottom: 30px; }

.community-section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
}

.community-section-title {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-family: var(--font-display);
    font-size: var(--text-lg);
    font-weight: 700;
    color: var(--text-primary);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-tight);
    margin: 0;
}

/* --- Community Skill Ladder (Driver Standings / Leaderboards "Ladder" tab) --- */
.community-section-note {
    margin: -8px 0 12px;
    font-size: var(--text-sm);
    color: var(--text-tertiary);
}

.lb-ladder-note {
    margin: 0 0 10px;
    font-size: var(--text-sm);
    color: var(--text-tertiary);
}

.lb-ladder-you {
    margin: 0 0 12px;
    font-size: var(--text-sm);
    color: var(--text-secondary);
}

.lb-ladder-you strong { color: var(--accent); font-family: var(--font-display); font-variant-numeric: tabular-nums; }

/* The community-local "Skill" number — deliberately NOT styled like the global
   rating (no tier-badge / rating-label classes), so the de-rank guard stays green. */
.cr-skill {
    font-family: var(--font-display);
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    color: var(--accent);
}

.cr-provisional {
    margin-left: 4px;
    font-size: 0.8em;
    font-weight: 700;
    color: var(--text-tertiary);
    cursor: help;
}

/* --- Recent results "Grid Feed" --- */
.grid-feed { display: flex; flex-direction: column; gap: 6px; }

.grid-feed-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    /* This row flex-wraps, so the inherited 1.6 prose leading was paid TWICE on narrow
       viewports — the mobile cost was double the desktop one. */
    line-height: 1.3;
    padding: 10px 14px;
    transition: border-color 0.12s ease, transform 0.12s ease;
}

.grid-feed-row:hover {
    border-color: var(--border-hover);
    transform: translateY(-1px);
}

.grid-feed-result {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
    flex-wrap: wrap;
    font-size: 14px;
}

.grid-feed-winner {
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--text-primary) !important;
}

.grid-feed-winner:hover { color: var(--accent) !important; }

.grid-feed-def {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-tight);
    color: var(--text-muted);
}

.grid-feed-loser { color: var(--text-secondary) !important; }
.grid-feed-loser:hover { color: var(--text-primary) !important; }

.grid-feed-meta {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-shrink: 0;
    font-size: 12px;
    color: var(--text-muted);
    text-align: right;
}

.grid-feed-track { color: var(--text-tertiary); }
.grid-feed-time { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* --- Medal styling for top-3 standings --- */
.pub-table td.rank-cell { width: 60px; }

.rank-medal {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 28px;
    font-family: var(--font-display);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    font-size: 16px;
    /* 16px × the cell's 1.35 = a 21.6px inline-flex box baseline-aligned in a 17.55px strut —
       a decoration taller than the data beside it, setting the row height on every Records and
       hub-standings row. Same fix as .rank-num / .tier-badge. */
    line-height: 1;
    vertical-align: middle;
}

.rank-medal.medal-none {
    color: var(--text-muted);
    font-size: 14px;
}

/* Top-3 medal tints reuse the canonical gold/silver/bronze tier tokens
   (same family as .rank-num.top1/top2/top3 + the leaderboard podium). */
.rank-medal.medal-gold { color: var(--tier-gold); }
.rank-medal.medal-silver { color: var(--tier-silver); }
.rank-medal.medal-bronze { color: var(--tier-bronze); }

/* --- Newest course-record teaser --- */
.course-record-teaser {
    display: flex;
    align-items: center;
    gap: 16px;
    padding: 16px 18px;
    border-left: 3px solid var(--accent);
    text-decoration: none;
    color: inherit;
    transition: border-color 0.12s ease, transform 0.12s ease;
}

.course-record-teaser:hover {
    border-color: var(--accent);
    transform: translateY(-1px);
}

.course-record-flag { font-size: 24px; flex-shrink: 0; }

.course-record-body {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
    flex: 1;
}

.course-record-label {
    font-family: var(--font-display);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-tight);
    color: var(--text-muted);
}

.course-record-line {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 10px;
    font-size: 14px;
    color: var(--text-secondary);
}

.course-record-line strong { color: var(--text-primary); }
.course-record-time { color: var(--accent); font-weight: 700; }
.course-record-track { color: var(--text-tertiary); }

.course-record-cta {
    flex-shrink: 0;
    font-family: var(--font-display);
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-tight);
    color: var(--accent);
}

/* --- Records / Hall of Fame (P1, 2026-06-07) --- */
/* Pass label in the Course Record Holders board — reads as the track/layout name. */
.record-pass { font-family: var(--font-display); font-weight: 600; color: var(--text-primary); }
/* Layout badge next to the pass name — distinguishes per-layout course records
   (e.g. Downhill vs Uphill) on a multi-layout track. Single-layout passes render
   no badge (PrettyLayout returns "" for the default/empty layout). */
.record-pass-layout { display: inline-block; margin-left: 8px; font-family: var(--font-display); font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; padding: 2px 7px; border-radius: 4px; background: rgba(255,255,255,0.05); border: 1px solid var(--border); color: var(--text-secondary); white-space: nowrap; vertical-align: middle; }
/* Best win-streak count chip on the Longest Win Streak board. */
.streak-count { font-family: var(--font-display); font-variant-numeric: tabular-nums; font-weight: 700; color: var(--accent); }

/* --- About page prose --- */
.community-lede {
    color: var(--text-secondary);
    font-size: 16px;
    line-height: 1.7;
    max-width: 70ch;
    margin: 0 auto 24px;
    text-align: center;
}

.community-prose-panel {
    padding: 22px 26px;
    margin-bottom: 20px;
    max-width: 75ch;
    margin-left: auto;
    margin-right: auto;
}

.community-prose-heading {
    font-family: var(--font-display);
    font-size: var(--text-lg);
    font-weight: 700;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-tight);
    margin-bottom: 14px;
}

/* Readable line-length, styled for the safe-markdown subset emitted by
   CommunityMarkdown.ToSafeHtml (h3/h4/p/ul/li/a/strong/em). */
.community-prose {
    color: var(--text-secondary);
    font-size: 15px;
    line-height: 1.75;
}

.community-prose h3 {
    font-family: var(--font-display);
    font-size: var(--text-md);
    font-weight: 700;
    color: var(--text-primary);
    text-transform: uppercase;
    letter-spacing: var(--letter-spacing-tight);
    margin: 20px 0 8px;
}

.community-prose h4 {
    font-family: var(--font-display);
    font-size: var(--text-base);
    font-weight: 700;
    color: var(--text-primary);
    margin: 16px 0 6px;
}

.community-prose p { margin-bottom: 12px; }
.community-prose p:last-child { margin-bottom: 0; }

.community-prose ul {
    margin: 0 0 12px;
    padding-left: 22px;
    list-style: disc;
}

.community-prose li { margin-bottom: 4px; }

.community-prose a {
    color: var(--accent);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.community-prose a:hover { color: var(--accent-hover); }
.community-prose strong { color: var(--text-primary); font-weight: 700; }
.community-prose em { font-style: italic; }

.about-socials { margin-top: 8px; }

.about-cta-row { text-align: center; margin-top: 18px; }

@media (max-width: 640px) {
    .community-hero-title { font-size: 1.9rem; }
    .community-hero-overlay { padding: 40px 18px 30px; }
    .community-header-name { font-size: 1.3rem; }
    .community-header-logo { width: 32px; height: 32px; }
    .operator-admin-name { font-size: 1.25rem; }
    .operator-admin-logo { width: 32px; height: 32px; }
    .operator-admin-header { gap: 6px 12px; }
    .grid-feed-meta { gap: 10px; }
}

/* ============================================================
   Phase C / Task 2.1 — Mobile bottom navigation bar
   ============================================================ */

/* Hidden on desktop — only shown at ≤768px via the @media block below */
.bottom-nav {
    display: none;
}

.bottom-nav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
    color: rgba(255, 255, 255, 0.45);
    text-decoration: none;
    font-size: 10px;
    font-family: var(--font-body);
    letter-spacing: 0.02em;
    min-width: 48px;
    min-height: 48px;
    padding: 4px 8px;
    justify-content: center;
    transition: color 0.15s;
    border-radius: 4px;
}

.bottom-nav-item.active,
.bottom-nav-item:hover {
    color: var(--accent);
}

.bottom-nav-item svg {
    width: 22px;
    height: 22px;
    stroke: currentColor;
    fill: none;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

@media (max-width: 768px) {
    .bottom-nav {
        display: flex;
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 200;
        background: rgba(8, 10, 16, 0.96);
        backdrop-filter: blur(8px);
        -webkit-backdrop-filter: blur(8px);
        border-top: 1px solid rgba(255, 255, 255, 0.07);
        padding: 6px 4px max(6px, env(safe-area-inset-bottom));
        justify-content: space-around;
        align-items: center;
    }

    body {
        padding-bottom: 72px;
    }

    /* 2026-07-09 mobile pass v2: the map hero keeps its natural 16:9 (~200px at 360px wide) —
       an earlier max-height+cover cap cropped the track outline (in-game feedback: "the whole
       map doesn't show"). The original giant-map problem was the card-width overflow, now fixed. */
}

/* ============================================================
   Phase C / Task 2.2 — Mobile search modal overlay
   ============================================================ */

.mobile-search-btn {
    display: none;
    background: none;
    border: none;
    color: var(--text-tertiary);
    cursor: pointer;
    padding: 6px;
    border-radius: 4px;
    transition: color 0.12s;
    align-items: center;
}

.mobile-search-btn:hover { color: var(--text-primary); }

@media (max-width: 768px) {
    .mobile-search-btn { display: flex; }
}

.search-modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 300;
    background: rgba(0, 0, 0, 0.75);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    display: flex;
    align-items: flex-start;
    padding-top: max(env(safe-area-inset-top, 0px), 0px);
}

.search-modal-panel {
    width: 100%;
    max-width: 520px;
    margin: 0 auto;
    background: rgba(14, 16, 22, 0.98);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 0 0 7px 7px;
    padding: 12px;
}

.search-modal-header {
    display: flex;
    gap: 8px;
    align-items: center;
}

.search-modal-input {
    flex: 1;
    padding: 10px 14px;
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.12);
    border-radius: 5px;
    color: var(--text-primary);
    font-size: 16px; /* 16px prevents iOS auto-zoom */
    font-family: var(--font-body);
}

.search-modal-input:focus {
    outline: none;
    border-color: var(--border-accent);
}

.search-modal-close {
    background: none;
    border: none;
    color: var(--text-tertiary);
    cursor: pointer;
    padding: 6px;
    border-radius: 4px;
    display: flex;
    align-items: center;
    flex-shrink: 0;
}

.search-modal-close:hover { color: var(--text-primary); }

.search-modal-results {
    list-style: none;
    margin: 8px 0 0;
    padding: 0;
}

.search-modal-result-item {
    display: block;
    padding: 10px 12px;
    color: var(--text-primary);
    border-radius: 4px;
    /* Fixed-height overlay on a phone — every px of leading costs a visible result. */
    line-height: 1.3;
    transition: background 0.1s;
}

.search-modal-result-item:hover {
    background: var(--bg-hover);
    color: var(--accent);
}

.search-modal-empty {
    padding: 10px 12px;
    color: var(--text-tertiary);
    font-size: 13px;
}

/* ============================================================
   Phase C / Task 2.3 — top-nav Status link (no new rules needed;
   uses existing .topnav-links a styles automatically)
   ============================================================ */

/* ============================================================
   Phase C / Task 2.4 — Discord-link quick modal + first-login toast
   ============================================================ */

.discord-toast {
    position: fixed;
    bottom: 88px; /* above the mobile bottom nav */
    left: 50%;
    transform: translateX(-50%);
    background: rgba(14, 16, 24, 0.97);
    border: 1px solid rgba(114, 137, 218, 0.4); /* Discord blurple tint */
    border-radius: 5px;
    padding: 10px 14px;
    display: flex;
    align-items: center;
    gap: 10px;
    font-size: 13px;
    color: var(--text-secondary);
    z-index: 250;
    white-space: nowrap;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
}

.discord-toast-link {
    color: var(--accent);
    font-weight: 600;
    white-space: nowrap;
}

.discord-toast-dismiss {
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 16px;
    padding: 0 2px;
    line-height: 1;
}

.btn-ghost {
    background: none;
    border: 1px solid rgba(255, 255, 255, 0.12);
    color: var(--text-tertiary);
    border-radius: 4px;
    padding: 8px 16px;
    cursor: pointer;
    font-size: 13px;
    transition: border-color 0.12s, color 0.12s;
}

.btn-ghost:hover {
    border-color: rgba(255, 255, 255, 0.25);
    color: var(--text-primary);
}

/* ============================================================
   Phase C / Task 2.5 — First-login welcome card
   ============================================================ */

/* .welcome-card base duplicate removed 2026-06-08 — merged into the canonical
   rule in the onboarding block (max-width/margin/padding folded in). */

.welcome-card h2 {
    font-family: var(--font-display);
    font-size: 2rem;
    color: var(--accent);
    margin-bottom: 6px;
    letter-spacing: 1px;
}

.welcome-sub {
    color: var(--text-secondary);
    font-size: 15px;
    margin-bottom: 20px;
}

.welcome-modes {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 16px;
    margin-top: 16px;
}

@media (max-width: 640px) {
    .welcome-modes { grid-template-columns: 1fr; }
}

@media (max-width: 768px) {
    .welcome-modes { grid-template-columns: repeat(2, 1fr); }
}

.mode-card {
    background: var(--glass-bg);
    border: 1px solid var(--border);
    border-radius: 6px;
    padding: 20px 16px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.mode-card-featured {
    border-color: var(--accent);
    background: rgba(0, 224, 255, 0.04);
}

.mode-card strong {
    font-family: var(--font-display);
    font-size: 15px;
    color: var(--text-primary);
}

.mode-card p {
    color: var(--text-secondary);
    font-size: 13px;
    line-height: 1.5;
    flex: 1;
}

.welcome-dismiss {
    margin-top: 16px;
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 12px;
    cursor: pointer;
    padding: 4px;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.welcome-dismiss:hover { color: var(--text-tertiary); }

/* ============================================================
   Phase C / Task 2.6d — Status page mobile breakpoints
   (also applied as scoped style in Status.razor if needed)
   ============================================================ */

@media (max-width: 640px) {
    .status-grid { grid-template-columns: repeat(2, 1fr) !important; }
}

@media (max-width: 480px) {
    .status-grid { grid-template-columns: 1fr !important; }
}

/* ============================================================
   Phase C / Task 2.6g — Operator community pages mobile guard
   ============================================================ */

@media (max-width: 768px) {
    .tenant-identity-ribbon {
        padding-right: 12px;
    }
}

/* ============================================================
   Phase C / Task 2.6b — Copy IP button on server cards
   ============================================================ */

.btn-copy-ip {
    background: rgba(255, 255, 255, 0.05);
    border: 1px solid rgba(255, 255, 255, 0.1);
    color: var(--text-tertiary);
    border-radius: 4px;
    padding: 6px 10px;
    font-size: 12px;
    cursor: pointer;
    transition: background 0.12s, color 0.12s;
    white-space: nowrap;
}

.btn-copy-ip:hover { background: rgba(255, 255, 255, 0.1); color: var(--text-primary); }

/* ============================================================
   Phase C / Task 2.6e — Explicit notification permission card
   ============================================================ */

.queue-notif-card {
    margin-top: 10px;
    padding: 10px 14px;
    background: rgba(255, 255, 255, 0.03);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 5px;
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

.queue-notif-text {
    flex: 1;
    font-size: 13px;
    color: var(--text-secondary);
    min-width: 160px;
}

.queue-notif-actions {
    display: flex;
    gap: 6px;
    flex-shrink: 0;
}

/* .btn-sm duplicate removed 2026-06-08 — merged into the canonical rule near
   the top of the buttons block (font-size/padding folded in). */

.btn-accent {
    background: var(--accent);
    color: #000;
    border: none;
    cursor: pointer;
    font-weight: 600;
    transition: opacity 0.12s;
}

/* ============================================================
   Phase 5.7 — Responsive cleanup at tablet (768px) + phone (375px)
   ============================================================
   Targeted, page-scoped overrides for the four high-traffic public
   pages (/leaderboard, /laps, /matches, /time-attack). Each block
   is intentionally narrow so it does NOT cross-contaminate other
   pages — desktop widths see no change.

   Audit (2026-05-04): static analysis of the page DOMs at 768px
   and 375px identified four classes of issue:
     1. Wide tables (records "Fastest Times" 9 columns) push the
        page wider than the viewport at 768px — need tablet-class
        column hiding (existing col-hide-sm only fires at 640px).
     2. Server-card footer (Connect + Copy IP buttons) overflows
        at 375px — the two side-by-side buttons exceed the card
        gutter on narrow phones.
     3. Match-filters filter-row already collapses at 480px but
        not at the canonical 375px iPhone-SE breakpoint, so we
        re-pin the rule at 375px for clarity (defensive — wider
        breakpoint already covers it, but a future refactor that
        nudges 480→500 would silently regress 375 unless pinned).
     4. /laps detail header (lap-title + lap-time) at 375px —
        scoped CSS file already handles 640px stacking, but the
        time value (2.4rem) still overruns ~360px viewports.
   ============================================================ */

/* Phase 5.7 — tablet (≤768px) cleanup */
@media (max-width: 768px) {
    /* /leaderboard records "Fastest Times" — hide Car + Date columns at
       tablet so the 9-column table fits without horizontal scroll. The
       existing col-hide-sm class only fires at 640px and below; this
       extends the hide-set up to the tablet breakpoint by reusing the
       same class so a future column-add inherits the behavior. */
    .pub-table .col-hide-sm { display: none; }

    /* /time-attack server-card footer — Connect + Copy IP buttons stack
       vertically so the Copy IP label never wraps awkwardly mid-button.
       The 8px gap matches the existing flex gap on .server-links. */
    .server-card-footer {
        display: flex;
        flex-direction: column;
        gap: 8px;
    }
}

/* Phase 5.7 — phone (≤375px) cleanup, iPhone SE / small Android */
@media (max-width: 375px) {
    /* /matches — collapse filter-row to one-per-row at the canonical
       small-phone width. Existing 480px rule covers this transitively
       but re-pinning at 375px makes the contract explicit. */
    .match-filters .filter-row { flex-direction: column; }
    .filter-select,
    .filter-toggle,
    .filter-search-wrap,
    .filter-search { width: 100%; }

    /* /laps/{id} detail — shrink the giant lap-time-value (2.4rem on
       desktop) to fit alongside the player name on narrow phones.
       The Detail.razor.css scoped sheet stacks the header at 640px;
       this rule additionally shrinks the time digits at 375px so they
       never wrap mid-time (e.g. 2:34.567 across two lines). */
    .lap-time-value { font-size: 1.8rem; }
    .lap-title h1 { font-size: 1.4rem; }

    /* /leaderboard rating tab — reduce horizontal padding on the
       sticky table header so all columns fit inside a 375px viewport.
       The .pub-table 768px rule already drops to 8px/10px; this
       further shrinks at phone width. */
    .pub-table th, .pub-table td { padding: 6px 8px; font-size: 11px; }
}

.btn-accent:hover { opacity: 0.85; }

/* Wave 7 — /coming-soon landing, served by PublicSiteGateMiddleware
   when PublicSiteDisabled flag is on. Minimal-layout: no nav, footer,
   or bottom-nav. */
.minimal-layout {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg);
    padding: 24px;
}
.coming-soon-card {
    max-width: 480px;
    padding: 48px 32px;
    text-align: center;
}
.coming-soon-logo {
    width: 180px;
    height: auto;
    margin-bottom: 24px;
}
.coming-soon-wordmark {
    font-family: 'Rajdhani', sans-serif;
    font-size: 56px;
    letter-spacing: 4px;
    color: var(--accent);
    margin: 0 0 24px 0;
}
.coming-soon-tagline {
    font-size: 16px;
    color: var(--text-secondary);
    margin-bottom: 16px;
}
.coming-soon-status {
    font-size: 14px;
    color: var(--text-muted);
    margin-bottom: 32px;
}
.coming-soon-cta {
    display: inline-block;
    padding: 12px 24px;
}

/* Wave 8 (2026-05-07) — operator-pitch landing page (/operators-pitch).
   Single-scroll marketing page surfacing what KOTT does for prospective
   operators. Reuses the .glass-panel + cyan accent vocabulary from the
   rest of the public site so it doesn't read as a foreign template. */
.operators-pitch-page {
    max-width: 960px;
    margin: 0 auto;
    padding: 0 1rem;
}
.op-pitch-banner {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0 0 1.5rem;
    padding: 12px 16px;
    border-radius: 4px;
    background: rgba(255, 179, 71, 0.08);
    border: 1px solid rgba(255, 179, 71, 0.3);
    color: var(--warning);
    font-size: var(--text-sm);
}
.op-pitch-banner-icon {
    font-size: 18px;
    line-height: 1;
}
.op-pitch-banner-text {
    font-family: var(--font-display);
    font-weight: 600;
    letter-spacing: 0.3px;
}
.op-pitch-hero {
    text-align: center;
    padding: 2.5rem 1rem 2rem;
}
.op-pitch-title {
    font-family: var(--font-display);
    font-size: clamp(28px, 5vw, 44px);
    font-weight: 800;
    letter-spacing: -0.5px;
    margin: 0 0 0.75rem;
    color: var(--text-primary);
}
.op-pitch-tagline {
    font-size: clamp(16px, 2.2vw, 18px);
    color: var(--text-secondary);
    max-width: 640px;
    margin: 0 auto 1.75rem;
    line-height: 1.55;
}
.op-pitch-hero-cta {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    justify-content: center;
}
/* SAME TRAP AS .welcome-btn ABOVE (see the comment there), and it bit again: this is an <a>,
   so `.public-shell a { color: var(--link) }` at (0,1,1) outranks a bare `.op-pitch-cta-primary`
   at (0,1,0) — rendering accent text on an accent background, i.e. an invisible button. It was
   the primary call to action on the operator pitch, so the one control that page exists for was
   unreadable. Prefixing with .public-shell ties specificity and lets the later rule's color win.
   Pinned by PublicFilledButtonContrastGuards so the next one is caught by the build. */
.public-shell .op-pitch-cta-primary {
    display: inline-block;
    padding: 12px 24px;
    border-radius: 4px;
    background: var(--accent);
    color: #000;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 15px;
    text-decoration: none;
    transition: background 120ms ease;
}
.public-shell .op-pitch-cta-primary:hover { background: var(--accent-hover); color: #000; }
.op-pitch-cta-secondary {
    display: inline-block;
    padding: 12px 24px;
    border-radius: 4px;
    background: var(--bg-elevated);
    color: var(--text-primary);
    border: 1px solid var(--border);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 15px;
    text-decoration: none;
    transition: border-color 120ms ease, color 120ms ease;
}
.op-pitch-cta-secondary:hover { border-color: var(--accent); color: var(--accent); }
.op-pitch-section {
    margin: 2.5rem 0;
}
.op-pitch-section-title {
    font-family: var(--font-display);
    font-size: 24px;
    font-weight: 700;
    margin: 0 0 1.25rem;
    color: var(--text-primary);
}
.op-pitch-card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 16px;
}
.op-pitch-card {
    padding: 20px;
    border-radius: 6px;
}
.op-pitch-card-badge {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 999px;
    font-family: var(--font-display);
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.6px;
    text-transform: uppercase;
    margin-bottom: 10px;
}
.op-pitch-card-badge-mm { background: rgba(0, 224, 255, 0.12); color: var(--accent); }
.op-pitch-card-badge-ta { background: rgba(180, 156, 255, 0.12); color: var(--accent-ta, #b49cff); }
.op-pitch-card-badge-ops { background: rgba(255, 255, 255, 0.06); color: var(--text-secondary); }
.op-pitch-card-heading {
    font-family: var(--font-display);
    font-size: 17px;
    font-weight: 700;
    margin: 0 0 0.5rem;
    color: var(--text-primary);
}
.op-pitch-card-body {
    font-size: 14px;
    line-height: 1.55;
    color: var(--text-secondary);
    margin: 0;
}
.op-pitch-steps {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.op-pitch-step {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 14px 16px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: 5px;
}
.op-pitch-step-num {
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--accent);
    color: #000;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 15px;
    display: flex;
    align-items: center;
    justify-content: center;
}
.op-pitch-step-body {
    display: flex;
    flex-direction: column;
    gap: 4px;
    color: var(--text-secondary);
    font-size: 14px;
    line-height: 1.55;
}
.op-pitch-step-body strong {
    color: var(--text-primary);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 15px;
}
.op-pitch-step-body code {
    font-size: 12.5px;
    color: var(--accent);
    background: rgba(0, 224, 255, 0.06);
    padding: 0 4px;
    border-radius: 3px;
}
.op-pitch-requirements {
    list-style: disc;
    padding-left: 1.25rem;
    margin: 0;
    color: var(--text-secondary);
    font-size: 14px;
    line-height: 1.7;
}
.op-pitch-requirements li { margin-bottom: 0.4rem; }
.op-pitch-requirements strong {
    color: var(--text-primary);
    font-family: var(--font-display);
    font-weight: 600;
}
.op-pitch-cta-block {
    text-align: center;
    padding: 2rem 1rem 2.5rem;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: 6px;
}
.op-pitch-cta-text {
    color: var(--text-secondary);
    max-width: 540px;
    margin: 0 auto 1.25rem;
    line-height: 1.55;
}
.op-pitch-cta-row {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    justify-content: center;
    margin-bottom: 1rem;
}
.op-pitch-cta-footnote {
    color: var(--text-muted);
    font-size: 13px;
    margin: 0.5rem 0 0;
}
.op-pitch-cta-footnote a {
    color: var(--accent);
    text-decoration: none;
}
.op-pitch-cta-footnote a:hover { text-decoration: underline; }

/* Communities empty-state two-CTA row (Wave 8 deliverable 1.C). */
.empty-state-cta-row {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    justify-content: center;
    margin-top: 1rem;
}
.empty-state-cta-row .empty-state-cta-primary {
    display: inline-block;
    padding: 10px 20px;
    border-radius: 4px;
    background: var(--accent);
    color: #000;
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 14px;
    text-decoration: none;
}
.empty-state-cta-row .empty-state-cta-primary:hover { background: var(--accent-hover); }
.empty-state-cta-row .empty-state-cta-secondary {
    display: inline-block;
    padding: 10px 20px;
    border-radius: 4px;
    background: var(--bg-elevated);
    color: var(--text-primary);
    border: 1px solid var(--border);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 14px;
    text-decoration: none;
}
.empty-state-cta-row .empty-state-cta-secondary:hover {
    border-color: var(--accent);
    color: var(--accent);
}

/* Home secondary CTA — "Run KOTT for your community" link card placed
   after the marketing-content section, NOT in the hero. Surfaces the
   operator funnel without dominating the player-first hero stack. */
.home-operator-cta {
    margin: 1.5rem auto;
    padding: 16px 20px;
    max-width: 720px;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: 5px;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px 16px;
    justify-content: space-between;
}
.home-operator-cta-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    flex: 1 1 280px;
}
.home-operator-cta-title {
    font-family: var(--font-display);
    font-weight: 700;
    color: var(--text-primary);
    font-size: 15px;
}
.home-operator-cta-sub {
    font-size: 13px;
    color: var(--text-muted);
}
.home-operator-cta-btn {
    display: inline-block;
    padding: 8px 16px;
    border-radius: 4px;
    background: transparent;
    color: var(--accent);
    border: 1px solid var(--accent);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: 14px;
    text-decoration: none;
    transition: background 120ms ease;
}
.home-operator-cta-btn:hover {
    background: var(--accent);
    color: #000;
}

/* ============================================================
   Live per-server page — map stage + in-map roster overlay
   2026-07-14: the roster was a side-by-side <aside> that cost the map ~360px of
   width. It's now an overlay INSIDE the stage, so the canvas owns the full
   content column. The stage is the positioning context; the canvas fills it
   absolutely and server-live-map.js sizes the backing store (DPR-aware) to match.
   ============================================================ */
.server-live-stage {
  position: relative;
  margin-top: 8px;
  width: 100%;
  /* Tall enough to read as the page's subject, never taller than the viewport. The vh term is
     what makes it "full screen" on a laptop; the clamp floor keeps a short window usable and the
     ceiling stops it ballooning on a tall monitor. The subtrahend is topnav + page padding —
     trimmed 210→170 once the server header moved inside the stage and stopped costing height.
     What's left below the fold is deliberate: it reveals the Top 10 board's edge, so the page
     reads as having more content rather than ending at the map. */
  height: clamp(440px, calc(100vh - 170px), 880px);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 8px;
  background: #05080c;
  overflow: hidden;
}
.server-live-map {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block; cursor: grab; touch-action: none;
}
.server-live-map:active { cursor: grabbing; }

/* SSE health chip. Hidden until a connection that WAS up drops, so a normal load never
   flashes it. Top-right — the roster owns the left, the hint owns the bottom. */
.server-live-conn {
  position: absolute; top: 10px; right: 10px;
  font-family: var(--font-display); font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.05em;
  padding: 3px 9px; border-radius: 3px;
  background: rgba(255, 209, 102, 0.14); color: #ffd166;
  border: 1px solid rgba(255, 209, 102, 0.32);
  pointer-events: none;
}
.server-live-conn[hidden] { display: none; }

/* Zoom/pan affordance — the canvas has no visual hint that it's interactive.
   Bottom-right so it never collides with the top-left roster overlay. */
.server-live-maphint {
  position: absolute; right: 10px; bottom: 8px; margin: 0;
  font-size: 10px; letter-spacing: 0.04em; color: #4b5563;
  pointer-events: none; user-select: none;
}

/* The floating server card: identity (name / track / Connect) + the connected-driver roster,
   overlaid on the map (2026-07-14). One card because it's one idea — "this server, and who's
   on it". Frosted so the map reads underneath. It's the scroll container's outer frame; the
   ident block is fixed and only the roster list below it scrolls. */
.server-live-panel {
  position: absolute; top: 10px; left: 10px;
  width: 300px; max-width: calc(100% - 20px);
  max-height: calc(100% - 20px);
  display: flex; flex-direction: column;   /* ident fixed, roster takes the rest + scrolls */
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 7px;
  background: rgba(6, 10, 16, 0.82);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: 0 8px 28px rgba(0,0,0,0.45);
  overflow: hidden;                        /* clip the scrolling list to the rounded corners */
}
.server-live-ident { flex: none; padding: 9px 10px 10px; border-bottom: 1px solid rgba(255,255,255,0.09); }
/* Was the page <h1> at ~28px; card-sized here. Operator names run to ~100 chars, but the name is
   the server's identity — it wraps in FULL rather than truncating: at 13px in the condensed
   display face that's ~3 lines / ~50px, which the card can afford, and a name cut at
   "…Time Attacks & Bat…" tells a visitor less than the whole thing does.
   overflow-wrap: anywhere so an unbroken token (operators like to paste a discord.gg URL into
   the name) breaks instead of pushing the card wider than the map. */
.server-live-name {
  margin: 0; font-family: var(--font-display); font-size: 13px; font-weight: 700;
  line-height: 1.3; color: var(--text-primary); letter-spacing: 0.01em;
  overflow-wrap: anywhere;
}
.server-live-meta { margin: 3px 0 0; font-size: 11px; line-height: 1.35; color: #6b7585; }
/* min-width:0 lets the Connect button shrink instead of forcing the card wider. */
.server-live-panel .server-live-actions { margin-top: 8px; }
.server-live-panel .btn-connect { flex: 1 1 auto; min-width: 0; text-align: center; padding: 5px 10px; font-size: 12px; }
.server-live-panel .btn-copyip { flex: none; padding: 5px 8px; display: inline-flex; align-items: center; }

.server-live-roster { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 2px; }
.server-live-roster-empty { color: #5b6675; padding: 14px 12px; text-align: center; font-size: 12px; }
.server-live-roster-head {
  display: flex; justify-content: space-between;
  color: #8a94a6; font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em;
  line-height: 1.3; padding: 6px 10px 5px; border-bottom: 1px solid rgba(255,255,255,0.07);
  /* Sticky over a scrolling list, so it needs its OWN near-opaque fill: `background: inherit`
     resolved to the panel's own rgba(…,0.82) and rows scrolled visibly through it. */
  position: sticky; top: 0; background: rgba(6, 10, 16, 0.97);
}
/* Row shape mirrors the in-game HUD racer list (kott_hud_surfaces.lua): name + right-aligned
   STATE word on the top line, car + right-aligned PB on the sub-line.

   Density: line-height is pinned to 1.25 HERE because .public-shell sets 1.6 site-wide — prose
   leading, which this dense two-line list inherited and which alone made every row ~12px taller
   than its own text needs. With the row padding + gap trimmed to match, a row is ~40px instead
   of ~58px, so ~7 drivers fit in the space 5 used to take. */
.slr-row {
  display: flex; flex-direction: column;
  padding: 5px 10px; border-bottom: 1px solid rgba(255,255,255,0.04);
}
.slr-row:last-child { border-bottom: 0; }
.slr-line { display: flex; align-items: baseline; gap: 7px; min-width: 0; line-height: 1.25; }
.slr-name {
  color: #e8eaed; font-weight: 600; font-size: 13px; text-decoration: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
a.slr-name:hover { color: #00e0ff; text-decoration: underline; }
/* Crew tag prefixing the name, in the crew's colour — the "[TAG] name" identity the in-game HUD
   renders. flex:none so it never shrinks: the NAME ellipsizes first, since a half-clipped tag
   ("[TE…") would misidentify the crew, whereas a clipped name is still recognisable. The inline
   style carries the crew colour (hex-validated in JS); this is the fallback. */
.slr-crew {
  flex: none; font-family: var(--font-display); font-size: 11px; font-weight: 700;
  color: #00e0ff; letter-spacing: 0.02em;
}
.slr-sub { color: #6b7585; font-size: 11px; }
.slr-car { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
/* Rank + PB travel together, right-aligned on the sub-line: the rank IS that PB's rank. */
.slr-pb { margin-left: auto; flex: none; display: flex; align-items: baseline; gap: 5px; }
.slr-best {
  flex: none; white-space: nowrap;
  font-family: var(--font-display); font-size: 11px; font-variant-numeric: tabular-nums;
  color: rgba(0, 224, 255, 0.85);   /* HUD: fade(theme.cyan, 0.85) on the PB */
}

/* Live driver STATE (2026-07-14) — replaces the live km/h readout, which was a number nobody
   could act on. Deliberately the in-game HUD racer list's treatment: lowercase plain coloured
   word, right-aligned, no chip chrome — colour alone carries it. Palette is the HUD theme
   (kott_hud_kit.lua, itself mirroring KOTT.Shared DesignTokens.Colors), so the same driver
   reads the same word in the same colour in-game and here. An unknown/empty status renders
   NOTHING (see DriverStatus).
   NB "racing" is intentionally absent: a 1v1 touge engagement is `battling`; the word stays
   reserved for a future planned circuit/grid race mode. */
.slr-state {
  margin-left: auto; flex: none; white-space: nowrap;
  font-family: var(--font-display); font-size: 11px; font-weight: 600; letter-spacing: 0.02em;
}
.slr-state-battling    { color: #ffb347; }                 /* HUD theme.amber  */
.slr-state-time_attack { color: #b49cff; }                 /* HUD theme.purple */
.slr-state-cruising    { color: rgba(0, 224, 255, 0.75); } /* HUD fade(theme.cyan, 0.75) */
.slr-state-lining_up   { color: #ffd166; }                 /* HUD theme.gold — LINING UP */
.slr-state-queued      { color: #ffd166; }
.slr-state-spectating  { color: #6b707a; }                 /* HUD theme.dim */
.slr-state-hunting     { color: #ff6b6b; }                 /* cat-and-mouse CAT — red  */
.slr-state-evading     { color: #8aff8a; }                 /* cat-and-mouse MOUSE — green */

@media (max-width: 768px) {
  /* Phone: a floating left column is the wrong shape — at ~340px of stage it covered most
     of the map AND squeezed names to "Takumi Fuj…". Dock the card to the bottom as a full-width
     sheet instead: the map keeps a clean top half, names get the whole width back, and Connect
     lands at thumb height. Taller stage since the sheet now carries the identity block too. */
  .server-live-stage { height: clamp(460px, 78vh, 700px); }
  .server-live-panel {
    top: auto; bottom: 0; left: 0; right: 0;
    width: auto; max-width: none;
    /* 58%, not more: the sheet now carries the identity block as well as the list, and at 62%
       it left the map only ~240px — too little to read a touge line on a phone. */
    max-height: 58%;
    border-radius: 0 0 7px 7px;
    border-left: 0; border-right: 0; border-bottom: 0;
  }
  .server-live-maphint { display: none; }
}

/* ============================================================
   Community Hub (P1 Wave 2a) — Trophy Case (live-computed badges)
   De-ranked: badges derive only from tenant-scoped community stats.
   Rarity drives the chip accent — references tokens, never the
   pinned semantic hexes. Elite borrows the gold tier token.
   ============================================================ */
.trophy-case {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 28px;
}

.badge-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    border-radius: 999px;
    border: 1px solid var(--border);
    background: var(--bg-panel);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    font-family: var(--font-display);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--text-primary);
    transition: transform 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
    cursor: default;
}

.badge-chip:hover {
    transform: translateY(-1px);
    border-color: var(--border-hover);
}

.badge-icon {
    font-size: 16px;
    line-height: 1;
}

.badge-label { white-space: nowrap; }

/* Common — subtle neutral chip. */
.badge-chip.badge-common {
    border-color: var(--border-hover);
}

/* Rare — cyan accent. */
.badge-chip.badge-rare {
    border-color: var(--border-accent-strong);
    background:
        linear-gradient(180deg, var(--accent-dim) 0%, var(--bg-panel) 90%);
    color: var(--accent);
}
.badge-chip.badge-rare:hover {
    border-color: var(--accent);
    box-shadow: 0 0 14px var(--accent-glow);
}

/* Elite — gold tier token, with a restrained glow. */
.badge-chip.badge-elite {
    border-color: rgba(255, 209, 102, 0.4);
    background:
        linear-gradient(180deg, rgba(255, 209, 102, 0.1) 0%, var(--bg-panel) 90%);
    color: var(--tier-gold);
}
.badge-chip.badge-elite:hover {
    border-color: var(--tier-gold);
    box-shadow: 0 0 16px rgba(255, 209, 102, 0.25);
}

/* Official — a KOTT-central badge (badge_definitions.tenant_id IS NULL). Player
   Badges (2026-07-03): pinned cyan border + gold-check corner mark so an operator's
   community cosmetic can never be mistaken for official KOTT recognition. */
.badge-chip.badge-official {
    border-color: var(--accent);
    background: linear-gradient(180deg, var(--accent-dim) 0%, var(--bg-panel) 90%);
}
.badge-chip.badge-official .badge-label { color: var(--accent); }
.badge-chip.badge-official:hover {
    border-color: var(--accent);
    box-shadow: 0 0 14px var(--accent-glow);
}
.badge-official-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--tier-gold);
    font-size: 12px;
    font-weight: 700;
    line-height: 1;
}

/* Inline SVG badge icons (BadgeIcon.razor) sit where the emoji glyph used to. The
   stroke inherits the chip color via currentColor (rare→cyan, elite→gold, official). */
.badge-icon .badge-svg { width: 18px; height: 18px; display: block; }

@media (prefers-reduced-motion: reduce) {
    .badge-chip { transition: none; }
    .badge-chip:hover { transform: none; }
}

/* ===== Live server page — track leaderboard + join (2026-06-15) ===== */
.server-live-actions { display: flex; align-items: center; gap: 8px; }
.btn-copyip.copied { color: var(--accent); border-color: var(--accent); }

/* Rank badge in the connected-driver roster (now overlaid on the map). Sized DOWN 2026-07-14:
   at 11px + 5px padding + a border it measured 21.6px tall — quietly the tallest thing on the
   name line, taller than the 13px name it labels, and setting the whole row's height. It's
   secondary info (the name is the subject), so it now reads as a small quiet tag. */
.slr-rank { display: inline-block; min-width: 20px; padding: 0 4px; margin-right: 6px;
    font-family: var(--font-display); font-size: 10px; font-weight: 700; text-align: center;
    color: var(--accent); border: 1px solid var(--border-hover); border-radius: 3px; }
.slr-line .slr-rank { margin-right: 0; }   /* the flex gap already spaces it */

/* "Top 10" track leaderboard below the map. (The "Currently playing" half of this board was
   dropped 2026-07-14 — it duplicated the in-map roster; the grid is a single cell now.) */
.server-live-board { margin-top: 24px; }
.server-live-board-title { font-family: var(--font-display); font-size: 14px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 1px; color: var(--text-secondary); margin: 0 0 10px; }
.slb-list { display: flex; flex-direction: column; }
/* line-height 1.25: same fix as .slr-line above, and for the same reason — this board renders the
   SAME name+car pair as the roster, so inheriting .public-shell's 1.6 left it ~56px per row while
   the roster right above it sat at ~40px. Two lists of drivers on one page must not disagree. */
.slb-row { display: grid; grid-template-columns: 40px 1fr auto auto; align-items: center; gap: 12px;
    padding: 6px 12px; border-bottom: 1px solid var(--border); font-size: 13px; line-height: 1.25; }
.slb-row:last-child { border-bottom: none; }
.slb-rank { font-family: var(--font-display); font-weight: 700; color: var(--text-tertiary); }
.slb-name { color: var(--text-primary); text-decoration: none;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.slb-name:hover { color: var(--accent); }
.slb-driver { display: flex; flex-direction: column; min-width: 0; gap: 1px; }
.slb-car { color: var(--text-muted); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.slb-time { font-family: var(--font-display); font-weight: 600; color: var(--accent); text-align: right; font-variant-numeric: tabular-nums; }
.slb-gap { font-family: var(--font-display); color: var(--text-muted); text-align: right; min-width: 64px; font-variant-numeric: tabular-nums; }
.slb-empty { padding: 14px 12px; color: var(--text-muted); font-size: 13px; }
.server-live-fulllink { display: inline-block; margin-top: 10px; font-family: var(--font-display);
    font-size: 13px; font-weight: 600; color: var(--accent); text-decoration: none; }
.server-live-fulllink:hover { text-decoration: underline; }

@media (max-width: 640px) {
    .slb-row { grid-template-columns: 32px 1fr auto; gap: 8px; }
    .slb-gap { display: none; }   /* drop gap on narrow screens; rank+name+time stay */
}

/* ── Community Events (2026-06-27) ──────────────────────────────────────────
   Per-community competition cards on /community/{slug}/events: a hero banner
   with an accent wash, a segmented countdown to the deadline, a top-3 podium,
   and a live standings board with a winner-crown reveal the instant the timer
   hits zero. --accent is operator-scoped via TenantBrandedLayout, so cyan picks
   up the community brand. (Distinct from the admin .event-row feed above.) */
.event-card { position: relative; margin-bottom: 22px; border-radius: 5px; overflow: hidden;
    background: var(--bg-panel); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
    border: 1px solid var(--border); }
.event-card.is-live { border-color: var(--border-accent); box-shadow: 0 0 0 1px rgba(0,224,255,0.08), 0 18px 50px -24px rgba(0,224,255,0.30); }

/* Hero banner — centered identity + countdown over a top-radial accent wash */
.event-banner { position: relative; display: flex; flex-direction: column; align-items: center; text-align: center; padding: 24px 28px 26px;
    background:
      radial-gradient(130% 150% at 50% 0%, rgba(0,224,255,0.10), transparent 60%),
      linear-gradient(180deg, rgba(0,224,255,0.05), transparent 64%); }
.event-card.is-ended .event-banner { background:
      radial-gradient(130% 150% at 50% 0%, rgba(138,255,138,0.08), transparent 60%),
      linear-gradient(180deg, rgba(138,255,138,0.04), transparent 64%); }

.event-status { display: inline-flex; align-items: center; gap: 7px; font-family: var(--font-display); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 2px; padding: 4px 11px; border-radius: 4px; border: 1px solid var(--border); }
.event-status.is-live { color: var(--success); border-color: rgba(138,255,138,0.35); background: rgba(138,255,138,0.06); }
.event-status.is-upcoming { color: var(--accent); border-color: var(--border-accent); background: var(--accent-dim); }
.event-status.is-ended { color: var(--text-muted); }
.event-status-dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; opacity: 0.85; }

.event-title { font-family: var(--font-display); font-size: 2.05rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-primary); margin: 13px 0 0; line-height: 1.05; }
.event-meta { display: flex; justify-content: center; align-items: center; gap: 9px; margin-top: 8px; flex-wrap: wrap; }
.event-pass { font-family: var(--font-display); font-size: 1rem; font-weight: 600; color: var(--accent); text-transform: uppercase; letter-spacing: 0.5px; }
.event-meta-sep { color: var(--text-tertiary); }
.event-pass-layout { font-family: var(--font-display); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; color: var(--text-secondary); border: 1px solid var(--border); border-radius: 4px; padding: 2px 8px; }
.event-entrants { font-size: 0.85rem; color: var(--text-muted); }

/* Prize — a centered reward pill */
.event-prize { display: inline-flex; align-items: center; gap: 9px; margin-top: 14px; border: 1px solid var(--border-accent); border-radius: 4px; padding: 8px 15px; background: var(--accent-dim); }
.event-prize-icon { font-size: 1.25rem; line-height: 1; }
.event-prize-value { font-family: var(--font-display); font-size: 1.05rem; font-weight: 700; color: var(--accent); text-transform: uppercase; letter-spacing: 0.5px; }

.event-prose { margin: 14px auto 0; max-width: 62ch; }

/* Countdown — the centered centerpiece (boxless: numbers + colon separators) */
.event-countdown { margin-top: 22px; }
.event-countdown-caption { display: block; font-family: var(--font-display); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 2px; color: var(--text-secondary); margin-bottom: 10px; }
.cd-cells { display: flex; justify-content: center; align-items: center; gap: 4px; }
.cd-cell { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 0 18px; }
.cd-num { font-family: var(--font-display); font-size: 2.6rem; font-weight: 700; line-height: 1; color: var(--accent); font-variant-numeric: tabular-nums; text-shadow: 0 0 22px var(--accent-glow); }
.cd-unit { font-family: var(--font-display); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 1.5px; color: var(--text-muted); }
.cd-sep { font-family: var(--font-display); font-size: 2rem; font-weight: 700; color: var(--accent); opacity: 0.3; line-height: 1; margin-bottom: 16px; }
.event-countdown.is-upcoming .cd-num { color: var(--text-primary); text-shadow: none; }
.event-countdown.is-upcoming .cd-sep { color: var(--text-muted); }

/* Winner banner (ended) — centered fit-content pill */
.event-winner-banner { display: flex; align-items: center; gap: 16px; width: fit-content; max-width: 100%; margin: 22px auto 0; padding: 14px 24px; border-radius: 5px;
    background: linear-gradient(90deg, rgba(138,255,138,0.14), rgba(138,255,138,0.02)); border: 1px solid rgba(138,255,138,0.30); }
.event-winner-banner.is-empty { background: var(--bg-hover); border-color: var(--border); color: var(--text-muted); font-size: 0.95rem; }
.event-crown { font-size: 2rem; line-height: 1; filter: drop-shadow(0 0 9px rgba(255,209,102,0.6)); }
.event-winner-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; text-align: left; }
.event-winner-label { font-family: var(--font-display); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 1.5px; color: var(--success); }
.event-winner-name { font-family: var(--font-display); font-size: 1.5rem; font-weight: 700; color: var(--text-primary); text-decoration: none; }
.event-winner-name:hover { color: var(--accent); }
.event-winner-time { font-family: var(--font-display); font-size: 1.6rem; font-weight: 700; color: var(--success); font-variant-numeric: tabular-nums; }

/* Live winner-crown reveal when the deadline passes while the visitor is on the page */
.event-card.just-ended .event-winner-banner { animation: event-crown-reveal 1s cubic-bezier(0.16,1,0.3,1); }
.event-card.just-ended .event-crown { animation: event-crown-pop 1s cubic-bezier(0.16,1,0.3,1); }
@keyframes event-crown-reveal {
    0% { transform: scale(0.96); opacity: 0; box-shadow: 0 0 0 0 rgba(138,255,138,0.5); }
    60% { box-shadow: 0 0 0 10px rgba(138,255,138,0); }
    100% { transform: scale(1); opacity: 1; box-shadow: 0 0 0 0 rgba(138,255,138,0); }
}
@keyframes event-crown-pop {
    0% { transform: scale(0) rotate(-25deg); opacity: 0; }
    55% { transform: scale(1.35) rotate(8deg); }
    100% { transform: scale(1) rotate(0); opacity: 1; }
}

/* Podium — top 3 as elevated cards, #1 centered + raised with a gold glow */
.event-podium { display: flex; justify-content: center; align-items: stretch; gap: 14px; padding: 26px 28px 18px; }
.podium-slot { position: relative; display: flex; flex: 1 1 0; max-width: 230px; min-width: 0; }
.slot-1 { transform: translateY(-12px); }
.podium-crown { position: absolute; top: -28px; left: 50%; font-size: 1.6rem; filter: drop-shadow(0 0 9px rgba(255,209,102,0.65)); animation: podium-crown-float 3s ease-in-out infinite; z-index: 1; }
.podium-card { display: flex; flex-direction: column; align-items: center; gap: 6px; width: 100%; padding: 18px 14px; border-radius: 5px; background: var(--bg-elevated); border: 1px solid var(--border); }
.slot-1 .podium-card { border-color: rgba(255,209,102,0.40); background: linear-gradient(180deg, rgba(255,209,102,0.10), rgba(255,209,102,0.01)); box-shadow: 0 0 28px rgba(255,209,102,0.14); }
.slot-2 .podium-card { border-color: rgba(192,200,212,0.30); }
.slot-3 .podium-card { border-color: rgba(205,127,50,0.30); }
.podium-rank { font-family: var(--font-display); font-weight: 700; font-size: 1.05rem; width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center; }
.podium-rank.rank-1 { color: var(--tier-gold); border: 2px solid var(--tier-gold); box-shadow: 0 0 14px rgba(255,209,102,0.30); }
.podium-rank.rank-2 { color: var(--tier-silver); border: 2px solid var(--tier-silver); }
.podium-rank.rank-3 { color: var(--tier-bronze); border: 2px solid var(--tier-bronze); }
.podium-name { font-family: var(--font-display); font-weight: 700; font-size: 1rem; color: var(--text-primary); text-decoration: none; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.podium-name:hover { color: var(--accent); }
.podium-car { font-size: 11px; color: var(--text-muted); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.podium-time { font-family: var(--font-display); font-weight: 700; font-size: 1.3rem; color: var(--accent); font-variant-numeric: tabular-nums; margin-top: 2px; }
.slot-1 .podium-time { color: var(--tier-gold); }
.podium-gap { font-size: 11px; color: var(--text-muted); font-variant-numeric: tabular-nums; text-transform: uppercase; letter-spacing: 0.5px; }
@keyframes podium-crown-float { 0%, 100% { transform: translateX(-50%) translateY(0); } 50% { transform: translateX(-50%) translateY(-4px); } }

/* Full standings */
.event-standings-head { display: flex; align-items: center; gap: 10px; margin: 10px 28px 12px; }
.event-standings-title { font-family: var(--font-display); font-size: 1.05rem; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: var(--text-primary); margin: 0; }
.event-standings-live { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-display); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: var(--success); }
.event-card .table-wrap { margin: 0 16px 18px; }
.event-standings .event-row-leader { background: rgba(0,224,255,0.05); }
.event-card.is-ended .event-standings .event-row-leader { background: rgba(138,255,138,0.06); }
.event-leader-crown { margin-left: 6px; font-size: 0.95rem; vertical-align: -1px; filter: drop-shadow(0 0 5px rgba(255,209,102,0.5)); }

/* Standings pager */
.event-pager { display: flex; align-items: center; justify-content: center; gap: 16px; padding: 4px 16px 20px; }
.event-pager-btn { font-family: var(--font-display); font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; color: var(--accent); background: transparent; border: 1px solid var(--border-accent); border-radius: 4px; padding: 7px 14px; cursor: pointer; transition: background 0.15s, border-color 0.15s, color 0.15s; }
.event-pager-btn:hover:not(:disabled) { background: var(--accent-dim); border-color: var(--border-accent-strong); }
.event-pager-btn:disabled { color: var(--text-tertiary); border-color: var(--border); opacity: 0.5; cursor: default; }
.event-pager-info { font-family: var(--font-display); font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }

@media (max-width: 640px) {
    .event-banner { padding: 20px 18px 22px; }
    .event-title { font-size: 1.55rem; }
    .cd-cell { padding: 0 11px; }
    .cd-num { font-size: 1.85rem; }
    .cd-sep { margin-bottom: 13px; }
    .event-podium { padding: 22px 12px 12px; gap: 8px; }
    .podium-card { padding: 14px 8px; gap: 5px; }
    .slot-1 { transform: translateY(-8px); }
    .podium-name { font-size: 0.82rem; }
    .podium-time { font-size: 1.05rem; }
    .event-standings-head { margin: 8px 16px 10px; }
    .event-card .table-wrap { margin: 0 6px 14px; }
    .event-winner-time { font-size: 1.25rem; }
}
@media (prefers-reduced-motion: reduce) {
    .event-card.just-ended .event-winner-banner,
    .event-card.just-ended .event-crown,
    .podium-crown { animation: none; }
}

/* ════════════════════════════════════════════════════════════════════
   ATMOSPHERE PASS (2026-07-08) — ambient depth layer, hover grammar,
   entrance motion, shared empty-state, soft-refresh utility.
   The site read as flat text on #000 because the frosted panels had
   nothing behind them to blur; the fixed ambient layer below gives every
   backdrop-filter site real content to frost (blur radii were capped at
   8px above to pay for it). All accents come from var(--accent) /
   var(--accent-purple) so tenant-branded surfaces inherit their brand
   color — no hardcoded hexes in this section. All motion is gated on
   @media (prefers-reduced-motion: no-preference).
   ════════════════════════════════════════════════════════════════════ */

/* ───── 1. AMBIENT LAYER ─────
   Fixed full-viewport backdrop behind the public shell: two large radial
   accent washes at 3–5% alpha + a tiled data-URI SVG grain. pointer-events
   none, z-index 0; the shell's structural children are lifted to z-index 1
   below so panels (and their backdrop-filters) sit above it.
   color-mix keeps the wash derived from the CSS vars; browsers without
   color-mix drop the declaration and gracefully keep the plain #000. */
.ambient-layer {
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background:
        radial-gradient(58% 46% at 16% 6%,
            color-mix(in srgb, var(--accent) 5%, transparent), transparent 72%),
        radial-gradient(52% 44% at 86% 92%,
            color-mix(in srgb, var(--accent-purple, var(--accent)) 4%, transparent), transparent 72%);
}
.ambient-layer::after {
    content: '';
    position: absolute;
    inset: 0;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23g)'/%3E%3C/svg%3E");
    background-size: 140px 140px;
    opacity: 0.035;
}
/* Lift the shell's structural children above the fixed ambient layer.
   .topnav is already sticky z-100; the banner rule at the top of this
   sheet is position:relative and only needs the z-index. */
.public-content,
.public-footer { position: relative; z-index: 1; }
.announcement-banner { z-index: 1; }

/* ───── 2. HOME HERO BACKDROP ─────
   .hero-backdrop is an absolutely-positioned slot under the hero copy that
   supports a self-hosted screenshot <img> beneath a dark gradient overlay.
   Graceful when the image is absent: the slot still carries a top-anchored
   accent wash (so the hero has atmosphere today), the <img> has alt="" (no
   broken-image chrome), and the inline onerror adds .hero-backdrop-missing
   which hides the img element entirely. */
.home-hero {
    position: relative;
    isolation: isolate; /* keep the z-index:-1 backdrop inside the hero */
    border-radius: 7px;
    overflow: hidden;
}
.hero-backdrop {
    position: absolute;
    inset: 0;
    z-index: -1;
    overflow: hidden;
    border-radius: 7px;
    background: radial-gradient(85% 100% at 50% 0%,
        color-mix(in srgb, var(--accent) 6%, transparent), transparent 72%);
}
.hero-backdrop img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    opacity: 0.28;
    filter: saturate(0.85);
}
.hero-backdrop-missing img { display: none; }
/* Dark gradient overlay — keeps hero type at full contrast over any image. */
.hero-backdrop::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg,
        rgba(0, 0, 0, 0.30) 0%,
        rgba(0, 0, 0, 0.62) 62%,
        var(--bg-primary) 100%);
}

/* ───── 3. HOVER GRAMMAR ─────
   Bounded per-component-class batches (no universal selectors).
   Cards: -2px lift + accent border + glow (uses the existing glow/duration/
   easing tokens from tokens.css). .card-hoverable is the generic opt-in
   utility for sibling pages' interactive cards. .server-card is deliberately
   NOT in the border batch — its border colors are role-meaningful. */
.home-mode-card:hover,
.home-recent-item:hover,
.home-req-chip:hover,
.card-hoverable:hover {
    border-color: var(--border-accent-strong);
    box-shadow: var(--glow-md), var(--shadow-sm);
}
@media (prefers-reduced-motion: no-preference) {
    .home-mode-card,
    .home-recent-item,
    .home-req-chip,
    .card-hoverable {
        transition:
            transform var(--dur-base) var(--ease-out),
            border-color var(--dur-base) var(--ease-out),
            box-shadow var(--dur-base) var(--ease-out),
            background var(--dur-base) var(--ease-out);
    }
    .home-mode-card:hover,
    .home-recent-item:hover,
    .home-req-chip:hover,
    .card-hoverable:hover {
        transform: translateY(-2px);
    }
}

/* Buttons — instant 1px press on :active (masks Blazor circuit latency;
   transition:none makes the press land the same frame as the click, the
   release then eases back through each class's own transition). Instant
   positional feedback, not animation, so it stays outside the motion gate. */
.btn:active:not(:disabled),
.btn-sm:active,
.btn-xs:active,
.track-btn:active,
.lb-tab-btn:active,
.auth-btn:active,
.home-hero-cta:active,
.home-status-cta:active,
.home-anon-cta-btn:active,
.queue-join-btn:active:not(:disabled),
.replay-btn:active,
.event-pager-btn:active:not(:disabled),
.mobile-search-btn:active,
.topnav-dropdown-trigger:active,
.empty-state .cta:active,
.error-state .retry-btn:active {
    transform: translateY(1px);
    transition: none;
}

/* Table rows — inset accent left edge on hover (pairs with the existing
   var(--bg-hover) row tint declared at the top of this sheet). */
.pub-table tbody tr:hover td:first-child {
    box-shadow: inset 2px 0 0 var(--accent);
}

/* ───── 4. ENTRANCE MOTION ─────
   One-shot ~200ms fade + 4px rise on the main content container, plus an
   nth-child staggered entrance on the Home card grids. `backwards` fill
   keeps the delayed cards invisible until their turn. Server-browser grids
   are deliberately excluded — they re-render on the 10s live refresh and
   would replay the entrance. */
@keyframes kott-enter {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: no-preference) {
    .public-content { animation: kott-enter 0.2s var(--ease-out) both; }

    .home-mode-cards .home-mode-card,
    .home-mode-cards .home-mode-card:nth-child(2),
    .home-req-list li:nth-child(2) { animation-delay: 0.05s; }
    .home-mode-cards .home-mode-card:nth-child(3),
    .home-req-list li:nth-child(3) { animation-delay: 0.1s; }
    .home-req-list li:nth-child(4) { animation-delay: 0.15s; }
}

/* ───── 6. SOFT-REFRESH UTILITY ─────
   Data-region dimming while a section re-fetches (applied by the
   soft-loading pass): dim + input-block, with a thin sweeping accent
   progress bar along the region's top edge (motion-gated). */
.is-refreshing {
    opacity: 0.45;
    pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
    .is-refreshing { position: relative; transition: opacity var(--dur-slow) var(--ease-standard); }
    .is-refreshing::before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        height: 2px;
        background: linear-gradient(90deg, transparent, var(--accent), transparent);
        background-size: 40% 100%;
        background-repeat: no-repeat;
        animation: kott-refresh-sweep 1.1s var(--ease-in-out) infinite;
    }
}
@keyframes kott-refresh-sweep {
    0%   { background-position: -40% 0; }
    100% { background-position: 140% 0; }
}


/* === Sharp refinement (2026-07-12): cyan top-accent + tabular numerals ============ */
.server-card, .live-widget, .rating-chart, .match-card, .live-match-card {
  border-top: 2px solid var(--accent);
}
.pub-table, .lb, .rating-chart, [class*="time"], [class*="lap"], [class*="sr-"] {
  font-variant-numeric: tabular-nums;
}

/* ── Circuit (grid-race) surfaces — 2026-07-15 review pass ─────────────────
   The three Circuit tables + the outcome/status chips the pages were already
   emitting class hooks for (they rendered unstyled). Density convention:
   data rows pin their own line-height; chips are capped under the cell's
   text strut (the .tier-badge rule) so they never set the row height. */
.circuit-standings td, .circuit-rounds td, .grid-classification td { line-height: 1.3; }
.grid-outcome {
  display: inline-block; font-family: var(--font-display);
  padding: 2px 8px; border-radius: 4px; border: 1px solid;
  font-size: 11px; font-weight: 700; letter-spacing: 0.5px;
  line-height: 1; vertical-align: middle;
}
.grid-outcome-finished { color: var(--accent); border-color: rgba(0, 224, 255, 0.35); background: rgba(0, 224, 255, 0.08); }
.grid-outcome-dnf { color: var(--warning); border-color: rgba(255, 179, 71, 0.35); background: rgba(255, 179, 71, 0.08); }
.grid-outcome-dsq { color: var(--danger); border-color: rgba(255, 107, 107, 0.35); background: rgba(255, 107, 107, 0.08); }
.status-chip {
  display: inline-block; padding: 2px 8px; border-radius: 4px;
  border: 1px solid var(--danger-border, rgba(255, 107, 107, 0.35));
  color: var(--danger); background: var(--danger-dim, rgba(255, 107, 107, 0.08));
  font-size: 11px; font-weight: 700; letter-spacing: 0.5px; line-height: 1;
  vertical-align: middle; text-transform: uppercase;
}
.circuit-back-link { margin-top: 16px; }

/* ═══════════════════════════════════════════════════════════════════════
   Doc pages — /docs/operators, /docs/install (2026-08-02 platform pivot)

   Long-form operator documentation, previously readable only inside a private
   repo. These are PROSE surfaces, so they deliberately keep the .public-shell
   1.6 leading rather than the ~1.25 used by dense data components — the house
   density rule exempts guides for exactly this reason. Measure is capped near
   70ch because unbroken 1200px-wide paragraphs are what make documentation
   feel like a chore.
   ═══════════════════════════════════════════════════════════════════════ */
.doc-page { max-width: 74ch; margin: 0 auto; padding-bottom: 64px; }
.doc-breadcrumb { font-size: 12px; color: var(--text-tertiary); margin-bottom: 18px; display: flex; gap: 8px; align-items: center; }
.doc-breadcrumb a { color: var(--text-secondary); }
.doc-breadcrumb a:hover { color: var(--accent); }

.doc-section { margin-top: 40px; }
.doc-section > h2 {
    font-family: var(--font-display); font-size: 19px; font-weight: 700;
    letter-spacing: -0.01em; margin: 0 0 12px; padding-bottom: 8px;
    border-bottom: 1px solid var(--border-subtle);
}
.doc-section p { color: var(--text-secondary); margin: 0 0 14px; }
.doc-section p:last-child { margin-bottom: 0; }
.doc-section strong { color: var(--text-primary); font-weight: 650; }

.doc-list { margin: 0 0 14px; padding-left: 20px; color: var(--text-secondary); display: flex; flex-direction: column; gap: 10px; }
.doc-steps { margin: 0; padding-left: 22px; color: var(--text-secondary); display: flex; flex-direction: column; gap: 14px; }
.doc-steps > li { padding-left: 4px; }

/* A callout for the thing a reader would otherwise discover the hard way. */
.doc-note {
    border-left: 2px solid var(--accent); padding: 2px 0 2px 14px;
    color: var(--text-secondary); margin: 16px 0 0;
}

.doc-code {
    font-family: var(--font-mono, ui-monospace, Consolas, monospace); font-size: 12.5px;
    background: var(--bg-elevated, rgba(255,255,255,0.04)); border: 1px solid var(--border-subtle);
    border-radius: 4px; padding: 10px 12px; margin: 10px 0; overflow-x: auto; line-height: 1.45;
}

/* Troubleshooting: symptom → cause. A <dl> because that is what it is. */
.doc-dl { margin: 0; color: var(--text-secondary); }
.doc-dl dt { font-weight: 650; color: var(--text-primary); margin-top: 14px; font-size: 13.5px; }
.doc-dl dt:first-child { margin-top: 0; }
.doc-dl dd { margin: 4px 0 0; padding-left: 14px; border-left: 1px solid var(--border-subtle); }

/* ═══════════════════════════════════════════════════════════════════════
   Home "two paths" (2026-08-02 platform pivot)

   Replaces the mode chips + "pick a mode" button + four-step install tutorial.
   KOTT is a plugin provider, so the home page routes two audiences rather than
   onboarding one: race (find a community) or host (run it yourself). Two cards,
   deliberately, because a third would make it a menu again.
   ═══════════════════════════════════════════════════════════════════════ */
.home-paths { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; margin: 26px 0 14px; }
.public-shell .home-path {
    flex: 1 1 260px; max-width: 340px; text-align: left;
    display: flex; flex-direction: column; gap: 5px;
    padding: 16px 18px; border-radius: 6px;
    background: var(--bg-elevated); border: 1px solid var(--border);
    color: var(--text-primary);
    transition: border-color 0.14s ease, transform 0.14s ease;
}
.public-shell .home-path:hover { border-color: var(--accent); transform: translateY(-2px); }
/* The player path is the likelier one from a cold landing, so it carries the accent edge —
   the operator path is a peer, not a footnote, and stays visually equal in every other way. */
.public-shell .home-path-primary { border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.home-path-title { font-family: var(--font-display); font-size: 16px; font-weight: 700; letter-spacing: -0.01em; }
.home-path-sub { font-size: 13px; color: var(--text-secondary); line-height: 1.45; }
.home-paths-note { font-size: 13px; color: var(--text-tertiary); margin: 0; }

@media (prefers-reduced-motion: reduce) {
    .public-shell .home-path { transition: border-color 0.14s ease; }
    .public-shell .home-path:hover { transform: none; }
}
