/* ========================================
   Heat Design System — Industrial Brutalist / CRT Terminal
   ======================================== */

/* --- Design Tokens (stage-16 mobile-first remap) --- */
:root {
    /* Surfaces */
    --background: #0A0A0A;
    --surface-elevated: #141414;
    --surface-2: #1C1C1C;
    --foreground: #F5F5F5;
    --muted-foreground: #9A9A9A;
    --tx-3: #5A5A5A;
    --border: #333333;
    --border-subtle: rgba(255, 255, 255, 0.06);
    --border-default: rgba(255, 255, 255, 0.12);
    --border-strong: rgba(255, 255, 255, 0.22);

    /* Primary = Ice (focal / CTA / selected / active tab) */
    --primary: #E6F8FC;
    --primary-foreground: #000000;
    --primary-soft: rgba(230, 248, 252, 0.06);

    /* Danger = LIVE / losses / destructive */
    --danger: #EF4444;
    --danger-foreground: #FFFFFF;

    /* Success = wins / plus */
    --active: #22C55E;

    /* Warning */
    --warning: #EAB308;

    /* Legacy aliases (backward compat with older components) */
    --ring: var(--primary);
    --accent: var(--primary);
    --accent-foreground: var(--primary-foreground);
    --destructive: var(--danger);
    --destructive-foreground: var(--danger-foreground);
    --card: #0A0A0A;
    --card-foreground: var(--foreground);
    --popover: #0A0A0A;
    --popover-foreground: var(--foreground);
    --secondary: #141414;
    --secondary-foreground: var(--foreground);
    --muted: #141414;
    --input: #141414;
    --radius: 0;

    /* 4pt spacing grid */
    --sp-1: 4px;
    --sp-2: 8px;
    --sp-3: 12px;
    --sp-4: 16px;
    --sp-5: 24px;
    --sp-6: 32px;

    /* Touch targets (WCAG 2.5.5) */
    --touch-target: 44px;

    /* Mobile header / bottom nav sizing */
    --appbar-h: 56px;
    --botnav-h: 70px;

    --font-display: 'Archivo Black', sans-serif;
    --font-sans: 'Inter', sans-serif;
    --font-mono: 'JetBrains Mono', monospace;

    /* Design-system formal aliases */
    --bg-0: var(--background);
    --bg-1: var(--surface-elevated);
    --bg-2: var(--surface-2);
    --bd-1: var(--border-subtle);
    --bd-2: var(--border-default);
    --bd-3: var(--border-strong);
    --tx-1: var(--foreground);
    --tx-2: var(--muted-foreground);
}

/* --- Reset & Base --- */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

html, body {
    background-color: var(--background);
    color: var(--foreground);
    font-family: var(--font-sans);
    font-size: 16px;
    line-height: 1.5;
    /* Use dvh, not vh: on iOS Safari `100vh` resolves to the LARGE
       viewport (toolbar collapsed), so when the toolbar is visible the body
       is taller than the visible area — that's the "scroll past content"
       bug, with hundreds of dead pixels below the fixed bottom-nav. `100dvh`
       matches the current visible viewport, so a short page (e.g. Home with
       2 hub cards) doesn't grow beyond what's on screen. */
    min-height: 100dvh;
    /* Safety net — if any element accidentally overflows horizontally
       (e.g. native iOS pickers, long unbreakable text), don't expose
       horizontal page scroll to the user. */
    overflow-x: hidden;
    /* Prevent iOS rubber-band overscroll dragging body up and showing the
       page background behind a fixed bottom-nav. */
    overscroll-behavior-y: none;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

@supports not (min-height: 100dvh) {
    html, body { min-height: 100vh; }
}

::selection {
    background: var(--primary);
    color: var(--primary-foreground);
}

a {
    color: inherit;
    text-decoration: none;
}

/* --- Scrollbar --- */
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: var(--background); }
::-webkit-scrollbar-thumb { background: var(--border); }
::-webkit-scrollbar-thumb:hover { background: #444444; }

/* --- CRT Scanline Overlay --- */
.crt-overlay {
    position: fixed;
    inset: 0;
    z-index: 9999;
    pointer-events: none;
    background: repeating-linear-gradient(
        0deg,
        rgba(0, 0, 0, 0.15) 0px,
        rgba(0, 0, 0, 0.15) 1px,
        transparent 1px,
        transparent 2px
    );
}

/* --- Noise Grain Overlay --- */
.noise-overlay {
    position: fixed;
    inset: 0;
    z-index: 9998;
    pointer-events: none;
    opacity: 0.03;
    background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E");
}

/* --- Glow Effects --- */
.glow-active {
    box-shadow: 0 0 8px var(--active), 0 0 16px rgba(34, 197, 94, 0.3);
}

.glow-red {
    box-shadow: 0 0 8px var(--danger), 0 0 16px rgba(239, 68, 68, 0.3);
}

.glow-ice {
    box-shadow: 0 0 8px var(--primary), 0 0 16px rgba(230, 248, 252, 0.18);
}

/* --- Animations --- */
@keyframes flicker {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.8; }
}

.flicker {
    animation: flicker 2s infinite;
}

@keyframes pulse-glow {
    0%, 100% { box-shadow: 0 0 8px var(--active); }
    50% { box-shadow: 0 0 16px var(--active), 0 0 24px rgba(34, 197, 94, 0.5); }
}

.pulse-active {
    animation: pulse-glow 2s infinite;
}

@keyframes pulse-glow-red {
    0%, 100% { box-shadow: 0 0 8px var(--danger); }
    50% { box-shadow: 0 0 16px var(--danger), 0 0 24px rgba(239, 68, 68, 0.5); }
}

@keyframes pulse-dot {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0.3; }
}

@keyframes fade-slide-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes stagger-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes scan-shimmer {
    0%   { background-position: 0% 0%; }
    100% { background-position: 0% 100%; }
}

@keyframes cursor-blink {
    0%, 100% { opacity: 1; }
    50%      { opacity: 0; }
}

@keyframes fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes value-flash {
    0%   { color: var(--active); }
    100% { color: var(--foreground); }
}

/* A3 — scanline sweep on focal card */
@keyframes scan-sweep {
    0%   { transform: translateY(0); opacity: 0; }
    8%   { opacity: 0.18; }
    50%  { opacity: 0.18; }
    92%  { opacity: 0.18; }
    100% { transform: translateY(200px); opacity: 0; }
}

.card.focal {
    position: relative;
    overflow: hidden;
}

.card.focal::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    height: 2px;
    background: var(--primary);
    opacity: 0;
    pointer-events: none;
    animation: scan-sweep 6s ease-in-out infinite;
    will-change: transform, opacity;
}

/* A5 — glitch text on error */
@keyframes text-glitch {
    0%   { transform: translateX(0); text-shadow: none; }
    20%  { transform: translateX(-1px); text-shadow: 2px 0 var(--danger), -2px 0 var(--active); }
    40%  { transform: translateX(1px); text-shadow: -2px 0 var(--danger), 2px 0 var(--active); }
    60%  { transform: translateX(-1px); text-shadow: 1px 0 var(--danger), -1px 0 var(--active); }
    100% { transform: translateX(0); text-shadow: none; }
}

.alert-error-glitch {
    animation: text-glitch 300ms steps(8) 1;
}

/* A4 — status dot flash */
@keyframes dot-flash {
    0%   { opacity: 0.6; transform: scale(1); }
    30%  { opacity: 1; transform: scale(1.3); }
    100% { opacity: 0.6; transform: scale(1); }
}

.status-dot.flash {
    animation: dot-flash 250ms ease-out 1;
}

/* A2 — digit roll cell */
.digit-roll-cell {
    display: inline-block;
    font-variant-numeric: tabular-nums;
}

/* --- Bracket Notation --- */
.bracket::before { content: '[ '; }
.bracket::after { content: ' ]'; }
.angle-bracket::before { content: '< '; }
.angle-bracket::after { content: ' >'; }
.arrow-right::before { content: '>>> '; }
.slash-prefix::before { content: '/// '; }

/* --- Typography --- */
.text-hero {
    font-family: var(--font-display);
    font-size: clamp(4rem, 12vw, 14rem);
    font-weight: 400;
    letter-spacing: -0.04em;
    line-height: 0.9;
    text-transform: uppercase;
    z-index: 2;
    position: relative;
}

.text-page-title {
    font-family: var(--font-display);
    font-size: clamp(2rem, 5vw, 4rem);
    font-weight: 400;
    letter-spacing: -0.04em;
    line-height: 0.9;
    text-transform: uppercase;
}

.text-section-title {
    font-family: var(--font-display);
    font-size: 1.5rem;
    font-weight: 400;
    letter-spacing: -0.02em;
    line-height: 0.9;
    text-transform: uppercase;
}

.text-card-title {
    font-family: var(--font-display);
    font-size: 1.125rem;
    font-weight: 400;
    letter-spacing: -0.02em;
    text-transform: uppercase;
}

.text-large-number {
    font-family: var(--font-mono);
    font-size: clamp(3rem, 8vw, 6rem);
    font-weight: 400;
    line-height: 1;
    text-transform: uppercase;
    white-space: nowrap;
}

.text-medium-number {
    font-family: var(--font-mono);
    font-size: 1.5rem;
    font-weight: 400;
    line-height: 1;
    text-transform: uppercase;
    white-space: nowrap;
}

.text-button {
    font-family: var(--font-mono);
    font-size: 13px;
    font-weight: 400;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.text-body-label {
    font-family: var(--font-mono);
    font-size: 11px;
    font-weight: 400;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted-foreground);
}

.text-micro-label {
    font-family: var(--font-mono);
    font-size: 9px;
    font-weight: 400;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted-foreground);
}

.text-card-label {
    font-family: var(--font-display);
    font-size: 1rem;
    font-weight: 400;
    letter-spacing: -0.02em;
    text-transform: uppercase;
}

.text-button-strong {
    font-family: var(--font-mono);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.text-page-label {
    font-family: var(--font-display);
    font-size: 32px;
    font-weight: 400;
    letter-spacing: -0.04em;
    line-height: 0.9;
    text-transform: uppercase;
}

/* --- Buttons --- */
.btn-primary {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    width: 100%;
    min-height: var(--touch-target);
    background-color: var(--primary);
    color: var(--primary-foreground);
    padding: 0 var(--sp-4);
    font-family: var(--font-mono);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    text-align: center;
    border: 1px solid var(--primary);
    border-radius: 0;
    cursor: pointer;
    transition: opacity 0.15s, transform 0.1s;
}

.btn-primary:hover {
    opacity: 0.92;
}

.btn-secondary {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    width: 100%;
    min-height: var(--touch-target);
    background-color: transparent;
    color: var(--foreground);
    padding: 0 var(--sp-4);
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    text-align: center;
    border: 1px solid var(--border-default);
    border-radius: 0;
    cursor: pointer;
    transition: color 0.15s, border-color 0.15s, transform 0.1s;
}

.btn-secondary:hover {
    border-color: var(--muted-foreground);
    color: var(--foreground);
}

.btn-danger {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    width: 100%;
    min-height: var(--touch-target);
    background-color: transparent;
    color: var(--danger);
    padding: 0 var(--sp-4);
    font-family: var(--font-mono);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    text-align: center;
    border: 1px solid var(--danger);
    border-radius: 0;
    cursor: pointer;
    transition: background-color 0.2s, color 0.2s, transform 0.1s;
}

.btn-danger:hover {
    background-color: var(--danger);
    color: var(--danger-foreground);
}

/* "Active/engaged" state button — mirrors .btn-danger but in success green.
   Used to communicate "you're already connected" (FOLLOWING, JOINED, etc.)
   so the user can distinguish a state badge from a CTA at a glance. */
.btn-active {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-2);
    width: 100%;
    min-height: var(--touch-target);
    background-color: transparent;
    color: var(--active);
    padding: 0 var(--sp-4);
    font-family: var(--font-mono);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    text-align: center;
    border: 1px solid var(--active);
    border-radius: 0;
    cursor: pointer;
    transition: background-color 0.2s, color 0.2s, transform 0.1s;
}

@media (hover: hover) {
    /* Subtle hover: only intensify the border + text, no large filled BG.
       Important for auto-width pill buttons where a tinted background looked
       like an unintended banner instead of an interactive cue. */
    .btn-active:hover {
        background-color: rgba(34, 197, 94, .04);
        border-color: var(--active);
        filter: brightness(1.15);
    }
}

.btn-primary:active,
.btn-secondary:active,
.btn-danger:active,
.btn-active:active {
    transform: scale(0.97);
}

.btn-disabled {
    background-color: var(--surface-elevated);
    color: var(--border);
    cursor: not-allowed;
    pointer-events: none;
}

.btn-sm {
    display: inline-block;
    padding: 0.3rem 0.8rem;
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    text-align: center;
    border-radius: 0;
    cursor: pointer;
    width: auto;
}

.btn-sm.btn-secondary {
    padding: 0.3rem 0.8rem;
    font-size: 11px;
}

.btn-sm.btn-danger {
    padding: 0.3rem 0.8rem;
    font-size: 11px;
}

/* Inline кнопка (auto-width версія будь-якого варіанту) */
.btn-inline {
    display: inline-block;
    width: auto;
    padding: 0.5rem 1rem;
}

.btn-row {
    display: flex;
    gap: 0.75rem;
}

.btn-row > * {
    flex: 1;
}

.action-section {
    margin-top: 1.5rem;
}

/* --- Inputs --- */
.input-field {
    display: block;
    width: 100%;
    max-width: 100%;
    /* min-width: 0 lets flex children shrink below their intrinsic content size.
       Without it, iOS Safari sizes datetime-local inputs to fit the locale-formatted
       value (e.g. "9 ТРАВ. 2026 Р., 08:45") and overflows narrow viewports. */
    min-width: 0;
    box-sizing: border-box;
    background-color: var(--background);
    color: var(--foreground);
    border: 1px solid var(--border);
    border-radius: 0;
    padding: 0.75rem 1rem;
    font-family: var(--font-mono);
    font-size: 13px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    outline: none;
    transition: border-color 0.15s;
}

/* iOS Safari (and some Android browsers) render native pickers for these input
   types with their own internal min-width based on the locale-formatted value.
   That intrinsic width can exceed the parent and overflow the viewport on
   narrow screens with verbose locales (e.g. uk-UA). Stripping the native
   appearance switches them to plain text-box sizing while keeping the
   browser's native picker UI for selection. */
input[type="datetime-local"].input-field,
input[type="date"].input-field,
input[type="time"].input-field,
input[type="month"].input-field {
    -webkit-appearance: none;
    appearance: none;
    text-align: left;
}

.input-field:focus {
    border-color: var(--muted-foreground);
}

.input-field::placeholder {
    color: var(--border);
}

.input-label {
    display: block;
    margin-bottom: 0.5rem;
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted-foreground);
}

/* --- Status Tags --- */
.status-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.25rem 0.5rem;
    border: 1px solid;
    font-family: var(--font-mono);
    font-size: 9px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    line-height: 1;
    align-items: center;
    justify-content: center;
    white-space: nowrap;
}

.status-tag.live {
    color: var(--danger);
    border-color: var(--danger);
    animation: pulse-glow-red 2s infinite;
}

.status-tag.pending {
    color: var(--muted-foreground);
    border-color: var(--muted-foreground);
}

.status-tag.completed {
    color: var(--active);
    border-color: var(--active);
}

.status-tag.champion {
    color: var(--primary);
    border-color: var(--primary);
}

/* --- Modal ---
   Owned by ModalHost (mounted at MainLayout root, OUTSIDE any animated/
   transformed ancestor). Anything position:fixed inside a transformed
   element is relative to that element, not the viewport — so the host MUST
   stay out of `.page-container.animate-page`. See IModalService for the API.

   Body scroll-lock applied via .modal-open class while the modal is open. */
body.modal-open { overflow: hidden; }

.modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    background: rgba(10, 10, 10, 0.85);
    display: flex;
    padding: 1rem;
}

.modal-overlay.placement-center {
    align-items: center;
    justify-content: center;
}

.modal-overlay.placement-bottomsheet {
    align-items: flex-end;
    justify-content: center;
    padding: 0;
}

.modal-panel {
    background: var(--surface, var(--background));
    border: 1px solid var(--border);
    width: 100%;
    max-width: 700px;
    /* vh on iOS Safari is the LARGE viewport (toolbars hidden), so a vh-sized panel is taller
       than what is visible and gets clipped top and bottom. dvh tracks the visible viewport;
       100% keeps it inside the overlay's padding. The vh line is the fallback for old engines. */
    max-height: 80vh;
    max-height: min(80dvh, 100%);
    display: flex;
    flex-direction: column;
}

.modal-panel-sheet {
    max-width: 100%;
    max-height: 85vh;
    max-height: min(85dvh, 100%);
    border-bottom: 0;
}

.modal-header {
    padding: 1rem 1.5rem;
    border-bottom: 1px solid var(--border);
    flex-shrink: 0;
}

.modal-body {
    padding: 1.5rem;
    overflow-y: auto;
    flex: 1 1 auto;
    min-height: 0;
}

.modal-footer {
    display: flex;
    justify-content: flex-end;
    gap: 0.75rem;
    padding: 1rem 1.5rem;
    border-top: 1px solid var(--border);
    flex-shrink: 0;
}

@media (max-width: 640px) {
    .modal-overlay {
        padding: 0.5rem;
    }

    .modal-panel {
        max-width: 100%;
        max-height: 90vh;
        max-height: min(90dvh, 100%);
    }

    .modal-header {
        padding: 0.75rem 1rem;
    }

    .modal-body {
        padding: 1rem;
    }

    .modal-footer {
        flex-direction: column-reverse;
        padding: 0.75rem 1rem;
    }
}

/* --- Cards --- */
.card {
    border: 1px solid var(--border);
    padding: 1rem;
    background-color: var(--background);
    transition: border-color 0.15s, transform 0.15s;
}

.card:hover {
    border-color: var(--muted-foreground);
    transform: translateY(-2px);
}

.card.selected {
    border-color: var(--primary);
}

.card.champion {
    border-width: 2px;
    border-color: var(--primary);
}

.card.live {
    border-color: var(--danger);
}

/* --- Stats Bar --- */
.stats-bar {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
}

.stats-bar > * {
    text-align: center;
    padding: 1rem;
}

.stats-bar > *:not(:last-child) {
    border-right: 1px solid var(--border);
}

/* --- Grid Borders --- */
.grid-borders {
    background-color: var(--border);
    gap: 1px;
}

.grid-borders > * {
    background-color: var(--background);
}

/* --- Data Rows --- */
.data-row {
    padding: 1rem;
    transition: background-color 0.15s;
}

.data-row:hover {
    background-color: var(--surface-elevated);
}

/* --- Layout Utilities --- */
.page-container {
    padding: 1rem;
}

@media (min-width: 1024px) {
    .page-container {
        padding: 2rem;
    }
}

.split-screen {
    display: grid;
    grid-template-columns: 1fr;
}

/* ≥1024px: 60/40 split. Left column owns the workout description and
   video grid; right column has the timer, entry fee, judges and the
   primary action button. minmax(0, …) lets each track shrink correctly
   so child grids/videos don't overflow. */
@media (min-width: 1024px) {
    .split-screen {
        grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
    }
}

.vs-layout {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: start;
    gap: 1rem;
}

.vs-layout > .vs-mid {
    /* Avatars are 56px; vertically center VS with avatar mid-line.
       align-items:start keeps both columns top-aligned regardless of
       how many lines the names wrap to. */
    padding-top: 22px;
}

/* --- Selection Grid --- */
.opponent-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 1rem;
}

.opponent-grid > * {
    min-width: 0;
    overflow: hidden;
}

/* --- Tabs --- */
.tab-bar {
    display: flex;
    border-bottom: 1px solid var(--border);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
}

.tab-bar::-webkit-scrollbar {
    display: none;
}

.tab-item {
    flex-shrink: 0;
    padding: 1rem 1.5rem;
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted-foreground);
    background: none;
    border: none;
    cursor: pointer;
    transition: color 0.15s;
}

@media (max-width: 479px) {
    .tab-item {
        padding: 0.75rem 1rem;
    }
}

.tab-item:hover {
    color: var(--foreground);
}

.tab-item.active {
    color: var(--foreground);
    background-color: var(--surface-elevated);
    border-bottom: 2px solid var(--primary);
}

/* --- Filter Tags --- */
.filter-tag {
    display: inline-block;
    padding: 0.25rem 0.75rem;
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted-foreground);
    background: none;
    border: none;
    cursor: pointer;
    transition: color 0.15s;
}

.filter-tag:hover {
    color: var(--foreground);
}

.filter-tag.active {
    color: var(--foreground);
    background-color: var(--surface-elevated);
    border: 1px solid var(--border);
}

/* --- Utility --- */
.text-primary { color: var(--primary); }
.text-active { color: var(--active); }
.alert-error { color: var(--danger); }
.timer-critical { color: var(--danger); animation: pulse-dot 1.6s infinite; }
.text-muted { color: var(--muted-foreground); }
.text-foreground { color: var(--foreground); }
.text-border { color: var(--border); }
.bg-elevated { background-color: var(--surface-elevated); }
.border-b { border-bottom: 1px solid var(--border); }
.border-t { border-top: 1px solid var(--border); }
.text-center { text-align: center; }
.text-right { text-align: right; }
.w-full { width: 100%; }
.cursor-pointer { cursor: pointer; }


/* --- Amount Input --- */
.input-amount {
    display: flex;
    align-items: center;
    border: 1px solid var(--border);
}

.input-amount-prefix {
    padding: 0 1rem;
    font-family: var(--font-mono);
    color: var(--muted-foreground);
}

.input-amount input {
    flex: 1;
    background: transparent;
    padding: 1rem;
    font-family: var(--font-mono);
    font-size: 1.5rem;
    color: var(--foreground);
    border: none;
    outline: none;
    text-transform: uppercase;
}

.input-amount input::placeholder {
    color: var(--border);
}

/* --- Score Input --- */
.input-score {
    width: 100%;
    background-color: var(--surface-elevated);
    border: 1px solid var(--border);
    padding: 0.5rem 0.75rem;
    font-family: var(--font-mono);
    font-size: 1rem;
    text-align: center;
    color: var(--foreground);
    outline: none;
    transition: border-color 0.15s;
}

.input-score:focus {
    border-color: var(--muted-foreground);
}

/* --- Progress Bar --- */
.progress-track {
    height: 0.5rem;
    background-color: var(--surface-elevated);
    position: relative;
}

.progress-fill {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    background-color: var(--foreground);
}

/* --- Info Bar --- */
.info-bar {
    padding: 1rem;
    background-color: var(--surface-elevated);
    border: 1px solid var(--border);
    font-family: var(--font-mono);
    font-size: 9px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted-foreground);
}

/* --- Timeline --- */
.timeline-line {
    position: absolute;
    left: 7px;
    top: 0;
    bottom: 0;
    width: 1px;
    background-color: var(--border);
}

.timeline-dot {
    position: relative;
    z-index: 10;
    width: 1rem;
    height: 1rem;
    border: 2px solid var(--border);
    background-color: var(--background);
}

.timeline-dot-win {
    border-color: var(--active);
}

.timeline-dot-loss {
    border-color: var(--primary);
}

/* --- Additional Utilities --- */
.border-r { border-right: 1px solid var(--border); }
.border-l { border-left: 1px solid var(--border); }
.divide-y > * + * { border-top: 1px solid var(--border); }
.divide-x > * + * { border-left: 1px solid var(--border); }
.pb-mobile-nav { padding-bottom: 5rem; }
.aspect-video { aspect-ratio: 16 / 9; }
.text-sm-number {
    font-family: var(--font-mono);
    font-size: 1.25rem;
    font-weight: 400;
    line-height: 1;
    text-transform: uppercase;
}

/* --- Flex Utilities --- */
.flex             { display: flex; }
.flex-col         { display: flex; flex-direction: column; }
.flex-wrap        { flex-wrap: wrap; }
.flex-1           { flex: 1; }
.items-center     { align-items: center; }
.items-start      { align-items: flex-start; }
.justify-between  { justify-content: space-between; }
.justify-center   { justify-content: center; }
.ml-auto          { margin-left: auto; }
.gap-xs  { gap: 0.25rem; }
.gap-sm  { gap: 0.5rem; }
.gap-md  { gap: 1rem; }
.gap-lg  { gap: 1.5rem; }

/* --- Spacing Utilities --- */
.mt-xs { margin-top: 0.25rem; }
.mt-sm { margin-top: 0.5rem; }
.mt-md { margin-top: 1rem; }
.mt-lg { margin-top: 1.5rem; }
.mt-xl { margin-top: 2rem; }
.mb-xs { margin-bottom: 0.25rem; }
.mb-sm { margin-bottom: 0.5rem; }
.mb-md { margin-bottom: 1rem; }
.mb-lg { margin-bottom: 1.5rem; }
.pb-sm { padding-bottom: 0.5rem; }
.pb-md { padding-bottom: 1rem; }
.pb-lg { padding-bottom: 1.5rem; }
.pt-sm { padding-top: 0.5rem; }
.pt-md { padding-top: 1rem; }
.pt-lg { padding-top: 1.5rem; }
.px-sm { padding-left: 0.5rem; padding-right: 0.5rem; }
.px-md { padding-left: 1rem; padding-right: 1rem; }
.pl-md { padding-left: 1rem; }
.pl-lg { padding-left: 1.5rem; }
.pr-md { padding-right: 1rem; }
.pr-lg { padding-right: 1.5rem; }

/* --- Width Utilities --- */
.w-auto      { width: auto; }
.w-auto-min  { width: auto; min-width: 120px; }
.max-w-sm    { max-width: 480px; }
.max-w-md    { max-width: 560px; }
.max-w-input { max-width: 200px; }

/* --- Additional Spacing --- */
.ml-sm { margin-left: 0.5rem; }
.mb-xl { margin-bottom: 2rem; }

/* --- Section Block --- */
/* Стандартний патерн: border-top + padding-top + margin-top */
.section-block {
    margin-top: 1.5rem;
    border-top: 1px solid var(--border);
    padding-top: 1rem;
}

/* --- Page Header --- */
.page-header {
    padding-bottom: 1.5rem;
    margin-bottom: 1.5rem;
    border-bottom: 1px solid var(--border);
}

/* --- Identity Grid (responsive 2col→1col) --- */
.identity-grid {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 0.75rem 2rem;
    max-width: 420px;
    align-items: center;
}

@media (max-width: 479px) {
    .identity-grid {
        grid-template-columns: 1fr;
        gap: 0.5rem;
    }
}

/* --- Metrics Grid (responsive 1→2 col) --- */
.metrics-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.5rem;
}

@media (min-width: 480px) {
    .metrics-grid {
        grid-template-columns: 1fr 1fr;
        gap: 0.5rem 2rem;
    }
}

/* --- Animation Utilities --- */
/* fill-mode: backwards — apply the FROM state before the animation runs (clean
   start) but DON'T retain the TO state after it ends. The TO state includes
   `transform: translateY(0)`, and any non-`none` transform on an ancestor
   turns descendant `position: fixed` overlays into locally-contained ones,
   breaking modal overlays on every animated page (settings logout, etc). */
.animate-page { animation: fade-slide-in 250ms ease-out backwards; }

.animate-stagger > * {
    animation: stagger-in 200ms ease-out backwards;
}
.animate-stagger > *:nth-child(1)  { animation-delay: 0ms; }
.animate-stagger > *:nth-child(2)  { animation-delay: 40ms; }
.animate-stagger > *:nth-child(3)  { animation-delay: 80ms; }
.animate-stagger > *:nth-child(4)  { animation-delay: 120ms; }
.animate-stagger > *:nth-child(5)  { animation-delay: 160ms; }
.animate-stagger > *:nth-child(6)  { animation-delay: 200ms; }
.animate-stagger > *:nth-child(7)  { animation-delay: 240ms; }
.animate-stagger > *:nth-child(8)  { animation-delay: 280ms; }
.animate-stagger > *:nth-child(9)  { animation-delay: 320ms; }
.animate-stagger > *:nth-child(10) { animation-delay: 360ms; }
.animate-stagger > *:nth-child(11) { animation-delay: 400ms; }
.animate-stagger > *:nth-child(12) { animation-delay: 440ms; }
.animate-stagger > *:nth-child(13) { animation-delay: 480ms; }
.animate-stagger > *:nth-child(14) { animation-delay: 520ms; }
.animate-stagger > *:nth-child(15) { animation-delay: 560ms; }
.animate-stagger > *:nth-child(16) { animation-delay: 600ms; }
.animate-stagger > *:nth-child(17) { animation-delay: 640ms; }
.animate-stagger > *:nth-child(18) { animation-delay: 680ms; }
.animate-stagger > *:nth-child(19) { animation-delay: 720ms; }
.animate-stagger > *:nth-child(20) { animation-delay: 760ms; }

.skeleton {
    background: linear-gradient(180deg, var(--surface-elevated) 0%, var(--border) 50%, var(--surface-elevated) 100%);
    background-size: 100% 200%;
    animation: scan-shimmer 1.5s linear infinite;
}

.cursor-blink::after {
    content: '_';
    animation: cursor-blink 1s step-end infinite;
}

.animate-fade { animation: fade-in 150ms ease-out both; }

.animate-value { animation: value-flash 600ms ease-out both; }

/* ── Busy button modifier ──
   Visible loading state for any .btn-* triggered async action.
   Append a blinking underscore after the label without disturbing layout;
   still rely on `disabled` binding to block actual activation, this is the
   visible feedback layer only. */
.btn-primary.is-busy,
.btn-secondary.is-busy,
.btn-danger.is-busy,
.btn-inline.is-busy {
    position: relative;
    pointer-events: none;
    opacity: 0.75;
}

.btn-primary.is-busy::after,
.btn-secondary.is-busy::after,
.btn-danger.is-busy::after,
.btn-inline.is-busy::after {
    content: '_';
    margin-left: 4px;
    animation: cursor-blink 1s step-end infinite;
    display: inline-block;
}

@media (prefers-reduced-motion: reduce) {
    .btn-primary.is-busy::after,
    .btn-secondary.is-busy::after,
    .btn-danger.is-busy::after,
    .btn-inline.is-busy::after {
        animation: none;
    }
}

.progress-fill-animated {
    transition: width 1s cubic-bezier(0.25, 0.46, 0.45, 0.94);
    overflow: hidden;
}

.progress-fill-animated::after {
    content: '';
    position: absolute;
    top: 0;
    left: -100%;
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.15), transparent);
    animation: shimmer-sweep 2s ease-in-out infinite;
}

@keyframes shimmer-sweep {
    0%   { left: -100%; }
    100% { left: 100%; }
}

.progress-tier-low {
    background-color: var(--foreground);
}

.progress-tier-mid {
    background-color: var(--primary);
}

.progress-tier-high {
    background-color: #FFD700;
}

.progress-tier-elite {
    background-color: var(--danger);
}

/* ========================================
   Stage-16 Mobile-first primitives
   ======================================== */

/* --- Icon helpers (used with <svg class="ico"><use href="#i-..."/></svg>) --- */
.ico {
    width: 22px;
    height: 22px;
    display: inline-block;
    flex-shrink: 0;
    vertical-align: middle;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linecap: square;
    stroke-linejoin: miter;
}
.ico-sm { width: 18px; height: 18px; }
.ico-lg { width: 26px; height: 26px; }

/* --- Mobile App Bar --- */
.appbar {
    position: sticky;
    top: 0;
    z-index: 40;
    height: var(--appbar-h);
    padding: 0 var(--sp-4);
    border-bottom: 1px solid var(--border-subtle);
    display: flex;
    align-items: center;
    gap: var(--sp-3);
    background: var(--background);
    flex-shrink: 0;
}

.appbar-stack {
    display: flex;
    flex-direction: column;
    gap: 0;
    line-height: 1.1;
}

.appbar .brand {
    font-family: var(--font-mono);
    font-weight: 800;
    letter-spacing: 0.02em;
    font-size: 15px;
    line-height: 1.1;
}

.appbar .sub {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--tx-3);
    margin-top: 1px;
}

.appbar .grow {
    flex: 1;
}

/* --- Icon button (44×44) --- */
.icon-btn {
    width: var(--touch-target);
    height: var(--touch-target);
    min-width: var(--touch-target);
    min-height: var(--touch-target);
    background: transparent;
    border: 1px solid var(--border-default);
    color: var(--foreground);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    position: relative;
    cursor: pointer;
    transition: border-color 0.15s;
}

.icon-btn:hover {
    border-color: var(--muted-foreground);
}

.icon-btn .badge {
    position: absolute;
    top: -1px;
    right: -1px;
    background: var(--primary);
    color: var(--primary-foreground);
    min-width: 16px;
    height: 16px;
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 4px;
    line-height: 1;
}

/* --- Balance chip ---
   No border on purpose: bell/gear are 44px bordered action buttons; the
   balance is informational text+icon. A bordered chip at 36px alongside
   44px buttons reads as misaligned. Keeping it borderless preserves the
   visual hierarchy (info vs. action) and removes the height mismatch. */
.chip-balance {
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 600;
    color: var(--foreground);
    padding: 0 var(--sp-2);
    height: var(--touch-target);
    display: inline-flex;
    gap: 6px;
    align-items: center;
    cursor: pointer;
    transition: color 0.15s;
    text-decoration: none;
}

.chip-balance:hover {
    color: var(--primary);
}

/* --- Generic chip --- */
.chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    font-weight: 600;
    padding: 5px 8px;
    background: transparent;
    border: 1px solid var(--border-default);
    color: var(--muted-foreground);
    min-height: 24px;
    line-height: 1;
}

.chip.success {
    border-color: var(--active);
    color: var(--active);
}

.chip.danger {
    border-color: var(--danger);
    color: var(--danger);
}

.chip.ice,
.chip.accent {
    border-color: var(--primary);
    color: var(--primary);
}

.chip.dim {
    color: var(--tx-3);
}

.chip .sq {
    width: 8px;
    height: 8px;
    background: currentColor;
}

.chip .pulse {
    width: 8px;
    height: 8px;
    background: currentColor;
    animation: pulse-dot 1.6s infinite;
}

/* --- Avatar --- */
.avatar {
    width: 44px;
    height: 44px;
    background: var(--surface-2);
    border: 1px solid var(--border-default);
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-mono);
    font-weight: 700;
    font-size: 14px;
    color: var(--foreground);
    flex-shrink: 0;
}

.avatar.sm {
    width: 36px;
    height: 36px;
    font-size: 12px;
}

.avatar.lg {
    width: 72px;
    height: 72px;
    font-size: 22px;
}

/* --- Bottom navigation (mobile, replaces legacy .mobile-nav) --- */
.botnav {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    height: var(--botnav-h);
    border-top: 1px solid var(--border-default);
    background: var(--background);
    display: grid;
    grid-template-columns: 1fr 1fr 68px 1fr 1fr;
    z-index: 50;
}

@media (min-width: 768px) {
    .botnav {
        display: none;
    }
}

.botnav-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 4px;
    color: var(--tx-3);
    position: relative;
    border: 0;
    background: transparent;
    min-width: 44px;
    min-height: 44px;
    cursor: pointer;
    text-decoration: none;
    transition: color 0.15s;
}

.botnav-item .lbl {
    font-family: var(--font-mono);
    font-size: 9px;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    font-weight: 600;
}

.botnav-item.active {
    color: var(--foreground);
}

.botnav-item.active::before {
    content: '';
    position: absolute;
    top: 0;
    left: 22%;
    right: 22%;
    height: 2px;
    background: var(--primary);
}

.botnav-item .badge {
    position: absolute;
    top: 8px;
    right: 22%;
    background: var(--primary);
    color: var(--primary-foreground);
    min-width: 14px;
    height: 14px;
    font-family: var(--font-mono);
    font-size: 9px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 3px;
    line-height: 1;
}

/* --- FAB (floating action button) in bottom nav center --- */
.fab {
    align-self: stretch;
    background: var(--primary);
    color: var(--primary-foreground);
    border: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-mono);
    font-weight: 700;
    cursor: pointer;
    text-decoration: none;
    transition: opacity 0.15s;
}

.fab:hover {
    opacity: 0.9;
}

/* --- VS block (1fr auto 1fr) --- */
.vs-block {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: var(--sp-3);
}

.vs-player {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--sp-2);
}

.vs-mid {
    font-family: var(--font-mono);
    font-weight: 700;
    font-size: 14px;
    color: var(--tx-3);
    letter-spacing: 0.12em;
}

/* --- Mobile-first layout --- */
.app-layout {
    display: flex;
    flex-direction: column;
    min-height: 100dvh;
}

.app-layout.has-botnav {
    padding-bottom: var(--botnav-h);
}

@media (min-width: 768px) {
    .app-layout.has-botnav {
        padding-bottom: 0;
    }
}

/* Hide appbar on desktop */
@media (min-width: 768px) {
    .appbar {
        display: none;
    }
}

/* Mobile display-heading compression (~40%) */
@media (max-width: 767px) {
    .text-page-title {
        font-size: clamp(1.75rem, 7vw, 2.25rem);
    }
    .text-hero {
        font-size: clamp(3rem, 14vw, 5rem);
    }
}

/* Mobile touch targets */
@media (max-width: 767px) {
    .tab-item,
    .filter-tag {
        min-height: var(--touch-target);
        display: inline-flex;
        align-items: center;
    }
}

/* --- Reduced Motion --- */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
    /* Stage 25 — scan-surface, focal, glitch, caret */
    .scan-surface .ss-mesh,
    .scan-surface .ss-grid,
    .scan-surface .ss-bar,
    .scan-surface .ss-px,
    .card.focal::before,
    .card.focal::after,
    .login-art::after,
    .login-art .text-hero::before,
    .login-art .text-hero::after,
    .login-art .glitch-slice,
    .caret-v { animation: none !important; }
}

/* ==========================================================================
   DESIGN SYSTEM v2 (Stage 25) — Heat Web Responsive bundle
   New primitives: scan-surface, glitch HEAT, badge-grid, feed-tile, tourn,
   notif, msg, score-grid, set-row, toggle, onb-dot, spark, crosshair
   ========================================================================== */

/* SCAN SURFACE */
.scan-surface {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 0;
}
.scan-surface .ss-mesh {
    position: absolute;
    inset: 0;
    background:
        radial-gradient(ellipse at 20% 30%, rgba(230, 248, 252, .18) 0%, transparent 45%),
        radial-gradient(ellipse at 80% 70%, rgba(34, 197, 94, .10) 0%, transparent 50%),
        radial-gradient(ellipse at 50% 90%, rgba(239, 68, 68, .06) 0%, transparent 55%),
        linear-gradient(180deg, #0a0a0a 0%, #141414 100%);
    animation: ssMeshDrift 14s ease-in-out infinite;
}
@keyframes ssMeshDrift {
    0%, 100% { filter: hue-rotate(0deg) saturate(1); }
    50%       { filter: hue-rotate(-15deg) saturate(1.2); }
}
.scan-surface .ss-grid {
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(0deg, rgba(230, 248, 252, .04) 1px, transparent 1px),
        linear-gradient(90deg, rgba(230, 248, 252, .04) 1px, transparent 1px);
    background-size: 32px 32px;
    mask-image: radial-gradient(ellipse at center, #000 0%, transparent 75%);
    animation: ssGridScroll 30s linear infinite;
}
@keyframes ssGridScroll {
    from { background-position: 0 0; }
    to   { background-position: 32px 32px; }
}
.scan-surface .ss-bar {
    position: absolute;
    left: 0;
    right: 0;
    top: -15%;
    height: 80px;
    background: linear-gradient(180deg, transparent 0%, rgba(230, 248, 252, .06) 50%, transparent 100%);
    animation: ssScan 8s linear infinite;
    mix-blend-mode: screen;
}
@keyframes ssScan {
    0%   { top: -15%; }
    100% { top: 115%; }
}
.scan-surface .ss-lines {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: repeating-linear-gradient(0deg, rgba(0, 0, 0, .18) 0, rgba(0, 0, 0, .18) 1px, transparent 1px, transparent 2px);
}
.scan-surface .ss-px {
    position: absolute;
    width: 2px;
    height: 2px;
    background: var(--primary);
    box-shadow: 0 0 4px var(--primary);
}
.scan-surface .ss-px.p1 { top: 20%; left: 15%; animation: ssPxFloat 8s ease-in-out infinite; }
.scan-surface .ss-px.p2 { top: 60%; left: 85%; animation: ssPxFloat 11s ease-in-out infinite reverse; background: var(--active); box-shadow: 0 0 4px var(--active); }
.scan-surface .ss-px.p3 { top: 35%; left: 75%; animation: ssPxFloat 9s ease-in-out 1s infinite; }
.scan-surface .ss-px.p4 { top: 75%; left: 25%; animation: ssPxFloat 12s ease-in-out 2s infinite; }
.scan-surface .ss-px.p5 { top: 15%; left: 55%; animation: ssPxFloat 10s ease-in-out infinite reverse; }
@keyframes ssPxFloat {
    0%, 100% { transform: translate(0, 0); opacity: .4; }
    50%       { transform: translate(20px, -15px); opacity: 1; }
}
.scan-surface.is-tight .ss-grid {
    background-size: 18px 18px;
    mask-image: radial-gradient(ellipse at center, #000 30%, transparent 90%);
}
.scan-surface.is-tight .ss-px { display: none; }
.scan-surface.is-minimal .ss-mesh { background: linear-gradient(180deg, #0a0a0a 0%, #0f0f0f 100%); }
.scan-surface.is-minimal .ss-px { display: none; }
.scan-surface.is-quiet .ss-bar { animation-duration: 14s; opacity: .6; }
body.glow-off .scan-surface .ss-mesh,
body.glow-off .scan-surface .ss-bar,
body.glow-off .scan-surface .ss-px { animation: none; }
body.glow-off .scan-surface .ss-bar { opacity: .3; }
body.glow-off .scan-surface .ss-px { opacity: .5; }

/* FOCAL CARD AUTO SCAN SURFACE */
.card.focal {
    border-color: var(--primary);
    position: relative;
    overflow: hidden;
}

/* "subtle" variant — used by detail-page hero cards (BattleDetail header) where
   the bright cyan border competes with the content inside. Keeps the decorative
   inner scan/grid effects, just tones down the frame. */
.card.focal.focal-subtle {
    border-color: var(--border);
}
.card.focal::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    background-image:
        radial-gradient(ellipse at 20% 30%, rgba(230, 248, 252, .14) 0%, transparent 50%),
        radial-gradient(ellipse at 85% 75%, rgba(34, 197, 94, .06) 0%, transparent 55%),
        linear-gradient(0deg, rgba(230, 248, 252, .04) 1px, transparent 1px),
        linear-gradient(90deg, rgba(230, 248, 252, .04) 1px, transparent 1px);
    background-size: 100% 100%, 100% 100%, 24px 24px, 24px 24px;
    mask-image: radial-gradient(ellipse at center, #000 30%, transparent 95%);
    animation: focalDrift 14s ease-in-out infinite;
}
@keyframes focalDrift {
    0%, 100% { filter: hue-rotate(0deg) saturate(1); }
    50%       { filter: hue-rotate(-12deg) saturate(1.15); }
}
.card.focal::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: -15%;
    height: 60px;
    background: linear-gradient(180deg, transparent 0%, rgba(230, 248, 252, .08) 50%, transparent 100%);
    animation: focalScan 8s linear infinite;
    mix-blend-mode: screen;
    pointer-events: none;
    z-index: 1;
}
@keyframes focalScan {
    0%   { top: -15%; }
    100% { top: 115%; }
}
.card.focal > * { position: relative; z-index: 2; }
.card.focal:has(> .scan-surface)::before,
.card.focal:has(> .scan-surface)::after { display: none; }
body.glow-off .card.focal::before,
body.glow-off .card.focal::after { animation: none; }
body.glow-off .card.focal::after { opacity: .3; }

/* GLITCH HEAT */
.login-art {
    position: relative;
    height: 160px;
    border: 1px solid var(--border-default);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    margin-bottom: 24px;
}
.login-art .text-hero {
    font-family: var(--font-display);
    font-size: 96px;
    letter-spacing: -.04em;
    line-height: .85;
    text-transform: uppercase;
    color: var(--foreground);
    position: relative;
    z-index: 2;
    animation: gJitter 5s steps(1) infinite;
}
.login-art .text-hero::before,
.login-art .text-hero::after {
    content: attr(data-text);
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
}
.login-art .text-hero::before {
    color: #FF003C;
    mix-blend-mode: screen;
    animation: gRGBr 3.2s steps(1) infinite;
}
.login-art .text-hero::after {
    color: #00E5FF;
    mix-blend-mode: screen;
    animation: gRGBb 3.2s steps(1) infinite;
}
.login-art .glitch-slice {
    position: absolute;
    left: 0;
    width: 100%;
    height: 8px;
    background: var(--background);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--primary);
    font-family: var(--font-display);
    font-size: 96px;
    letter-spacing: -.04em;
    line-height: .85;
    text-transform: uppercase;
    z-index: 2;
    pointer-events: none;
}
.login-art .gs1 { top: 32%; animation: gSlice1 6s steps(1) infinite; }
.login-art .gs2 { top: 58%; animation: gSlice2 6s steps(1) infinite; }
.login-art .gs3 { top: 18%; height: 3px; animation: gSlice3 6s steps(1) infinite; }
@keyframes gJitter {
    0%, 7%, 9%, 17%, 40%, 100% { transform: translate(0, 0); }
    8%  { transform: translate(-2px, 1px); }
    16% { transform: translate(2px, -1px); }
    41% { transform: translate(-1px, 0); }
    72%, 73% { transform: translate(1px, 2px); }
}
@keyframes gRGBr {
    0%, 8%, 12%, 40%, 42%, 100% { transform: translate(0, 0); opacity: 0; }
    9%  { transform: translate(-3px, 1px); opacity: .85; }
    11% { transform: translate(2px, -1px); opacity: .7; }
    41% { transform: translate(-2px, 0); opacity: .6; }
    73% { transform: translate(3px, 1px); opacity: .8; }
}
@keyframes gRGBb {
    0%, 8%, 12%, 40%, 42%, 100% { transform: translate(0, 0); opacity: 0; }
    9%  { transform: translate(3px, -1px); opacity: .85; }
    11% { transform: translate(-2px, 1px); opacity: .7; }
    41% { transform: translate(2px, 0); opacity: .6; }
    73% { transform: translate(-3px, -1px); opacity: .8; }
}
@keyframes gSlice1 {
    0%, 12%, 15%, 55%, 57%, 100% { transform: translateX(0); opacity: 0; }
    13% { transform: translateX(8px); opacity: 1; }
    56% { transform: translateX(-12px); opacity: 1; }
}
@keyframes gSlice2 {
    0%, 30%, 32%, 80%, 82%, 100% { transform: translateX(0); opacity: 0; }
    31% { transform: translateX(-6px); opacity: 1; }
    81% { transform: translateX(10px); opacity: 1; }
}
@keyframes gSlice3 {
    0%, 22%, 23%, 67%, 68%, 100% { opacity: 0; }
    22.5% { opacity: 1; transform: translateX(4px); }
    67.5% { opacity: 1; transform: translateX(-8px); }
}
body.glow-off .login-art::after,
body.glow-off .login-art .text-hero::before,
body.glow-off .login-art .text-hero::after,
body.glow-off .login-art .glitch-slice { animation: none; opacity: 0; }

/* CARET-V */
.caret-v {
    display: inline-block;
    width: 4px;
    /* cap height, so the caret lines up with uppercase text instead of rising above it */
    height: .72em;
    height: 1cap;
    background: var(--primary);
    vertical-align: baseline;
    margin-left: 6px;
    animation: caretVBlink 1s steps(1) infinite;
}
@keyframes caretVBlink {
    0%, 49% { opacity: 1; }
    50%, 100% { opacity: 0; }
}

/* ONBOARDING DOTS */
.onb-dots {
    display: flex;
    gap: 6px;
    margin-top: auto;
    padding: 16px;
}
.onb-dot {
    width: 24px;
    height: 3px;
    background: var(--border);
}
.onb-dot.active {
    background: var(--primary);
}

/* BADGE GRID */
.badge-grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 8px;
}
.badge-grid .badge {
    aspect-ratio: 1;
    border: 1px solid var(--border-default);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 8px;
    text-align: center;
    position: relative;
    overflow: hidden;
}
.badge-grid .badge:not(.locked)::before {
    content: '';
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(0deg, rgba(230, 248, 252, .04) 1px, transparent 1px),
        linear-gradient(90deg, rgba(230, 248, 252, .04) 1px, transparent 1px);
    background-size: 14px 14px;
    mask-image: radial-gradient(ellipse at center, #000 20%, transparent 85%);
    pointer-events: none;
    z-index: 0;
}
.badge-grid .badge > * { position: relative; z-index: 2; }
.badge-grid .badge.locked { opacity: .4; }
.badge-grid .badge .lbl {
    font-family: var(--font-mono);
    font-size: 8px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--muted-foreground);
    line-height: 1.1;
}
.badge-grid .badge.gold {
    border-color: #FFD700;
    color: #FFD700;
    box-shadow: 0 0 8px rgba(255, 215, 0, .3);
}
.badge-grid .badge.gold .lbl { color: #FFD700; }

/* Bigger icon than the default 22px ico size — badges are 1:1 squares
   ~110px tall on mobile, the icon should carry visual weight. Default badges
   inherit the muted-foreground stroke colour; gold ones override below. */
.badge-grid .badge .badge-ico {
    width: 40px;
    height: 40px;
    stroke-width: 1.4;
    color: var(--foreground);
    margin-bottom: 2px;
}
.badge-grid .badge.locked {
    /* Override the global .locked opacity (.4) to a slightly less dim value —
       the lock overlay handles the "earn me" affordance, the icon should still
       be readable as an outline silhouette. */
    opacity: 1;
}
.badge-grid .badge.locked .badge-ico {
    color: var(--muted-foreground);
    opacity: 0.4;
}
.badge-grid .badge.locked .lbl {
    opacity: 0.6;
}
.badge-grid .badge.gold .badge-ico {
    color: #FFD700;
    filter: drop-shadow(0 0 4px rgba(255, 215, 0, .35));
}

/* Lock overlay — small padlock pinned to the top-right corner of locked badges. */
.badge-grid .badge .badge-lock {
    position: absolute;
    top: 6px;
    right: 6px;
    width: 14px;
    height: 14px;
    color: var(--muted-foreground);
    stroke-width: 1.5;
    z-index: 3;
    opacity: 0.85;
}

/* Progress bar — anchored to the bottom edge of locked tiles when partial progress
   data is available. Thin track + foreground fill, no rounded corners to match
   the rest of the cyber/terminal aesthetic. */
.badge-grid .badge .badge-progress {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 14px;
    background: var(--surface-2);
    overflow: hidden;
    z-index: 3;
    display: flex;
    align-items: center;
    justify-content: center;
}
.badge-grid .badge .badge-progress-bar {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    background: var(--primary);
    opacity: 0.25;
    transition: width 240ms ease-out;
}
.badge-grid .badge .badge-progress-label {
    position: relative;
    z-index: 4;
    font-family: var(--font-mono);
    font-size: 8px;
    letter-spacing: 0.06em;
    color: var(--foreground);
    line-height: 1;
}

/* FEED TILE */
.feed-tile {
    position: relative;
    aspect-ratio: 9/16;
    border: 1px solid var(--border-default);
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding: 10px;
    background: linear-gradient(180deg, #1a1a1a 0%, #0a0a0a 100%);
    overflow: hidden;
}
.feed-tile::before {
    content: '';
    position: absolute;
    inset: 0;
    background: repeating-linear-gradient(45deg, transparent 0, transparent 8px, rgba(255, 255, 255, .02) 8px, rgba(255, 255, 255, .02) 9px);
}
.feed-tile .play {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 40px;
    height: 40px;
    border: 1px solid var(--primary);
    background: var(--primary-soft);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--primary);
}
.feed-tile .meta {
    position: relative;
    z-index: 2;
    font-family: var(--font-mono);
    font-size: 9px;
    letter-spacing: .08em;
    text-transform: uppercase;
}

/* TOURNAMENT BANNER */
.tourn {
    border: 1px solid var(--primary);
    padding: 14px;
    background: var(--primary-soft);
    position: relative;
    overflow: hidden;
}
.tourn::before {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    width: 60%;
    height: 100%;
    background: linear-gradient(135deg, transparent 50%, rgba(230, 248, 252, .04) 100%);
    pointer-events: none;
}
.tourn .h {
    font-family: var(--font-display);
    font-size: 22px;
    letter-spacing: -.02em;
    line-height: 1;
    text-transform: uppercase;
    color: var(--primary);
}

/* NOTIFICATION ITEM */
.notif {
    padding: 14px 0;
    display: flex;
    gap: 12px;
    border-bottom: 1px solid var(--border-default);
    align-items: flex-start;
}
.notif .icobx {
    width: 32px;
    height: 32px;
    border: 1px solid var(--border-default);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.notif .icobx.r { border-color: var(--danger); color: var(--danger); }
.notif .icobx.g { border-color: var(--active); color: var(--active); }
.notif .icobx.i { border-color: var(--primary); color: var(--primary); }
.notif .body { flex: 1; min-width: 0; }
.notif .body .ttl {
    font-family: var(--font-sans);
    font-weight: 600;
    font-size: 13px;
    line-height: 1.35;
}
.notif .body .meta {
    font-family: var(--font-mono);
    font-size: 9px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--tx-3);
    margin-top: 4px;
}
.notif.unread {
    position: relative;
    padding-left: 8px;
}
.notif.unread::before {
    content: '';
    position: absolute;
    left: 0;
    top: 18px;
    width: 2px;
    height: 24px;
    background: var(--primary);
}

/* CHAT MESSAGE */
.msg {
    display: flex;
    gap: 8px;
    margin-bottom: 14px;
    /* flex-start so the bubble's top sits level with the avatar's top —
       the standard pattern in Slack/Discord/Telegram. With flex-end the
       bubble bottom aligned with the avatar, making the bubble appear to
       float below the icon. */
    align-items: flex-start;
}
.msg.me { flex-direction: row-reverse; }

/* Body column — sized so the bubble lands flush against its side of the row.
   `flex: 1 1 auto` lets it grow into available space (so .me can push to the
   right edge) while `min-width: 0` keeps long words from overflowing. */
.msg-body {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    flex: 1 1 auto;
    min-width: 0;
    max-width: calc(100% - 44px);
}
.msg.me .msg-body { align-items: flex-end; }

.msg-time {
    font-family: var(--font-mono);
    font-size: 9px;
    letter-spacing: 0.08em;
    color: var(--tx-3);
    margin-top: 4px;
}

.msg .avx {
    width: 28px;
    height: 28px;
    background: var(--surface-2);
    border: 1px solid var(--border-default);
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-mono);
    font-size: 10px;
    font-weight: 700;
    flex-shrink: 0;
}
.msg .bub {
    padding: 8px 12px;
    border: 1px solid var(--border-default);
    background: var(--surface-2);
    font-family: var(--font-sans);
    font-size: 13px;
    line-height: 1.4;
    word-break: break-word;
    max-width: 100%;
}
.msg.me .bub {
    border-color: var(--primary);
    background: var(--primary-soft);
    color: var(--primary);
}
.msg .who {
    font-family: var(--font-mono);
    font-size: 9px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--tx-3);
    margin-bottom: 2px;
}

/* SCORE GRID */
.score-grid {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 8px;
}
.score-cell {
    display: flex;
    flex-direction: column;
    gap: 6px;
}
.score-input {
    width: 100%;
    background: var(--surface-elevated);
    border: 1px solid var(--border);
    padding: 10px;
    font-family: var(--font-mono);
    font-size: 18px;
    text-align: center;
    color: var(--foreground);
    outline: none;
}
.score-input:focus { border-color: var(--primary); }

/* SETTINGS ROWS + TOGGLE */
.set-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 0;
    border-bottom: 1px solid var(--border-default);
    cursor: pointer;
}
.set-row .icoBx {
    width: 32px;
    height: 32px;
    border: 1px solid var(--border-default);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--foreground);
}
.set-row .lbl-set {
    flex: 1;
    font-family: var(--font-sans);
    font-size: 14px;
    font-weight: 500;
}
.set-row .val {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--muted-foreground);
}
.toggle {
    width: 38px;
    height: 22px;
    background: var(--surface-2);
    border: 1px solid var(--border-default);
    position: relative;
    cursor: pointer;
}
.toggle::after {
    content: '';
    position: absolute;
    left: 1px;
    top: 1px;
    width: 18px;
    height: 18px;
    background: var(--muted-foreground);
    transition: .15s;
}
.toggle.on {
    border-color: var(--primary);
    background: var(--primary-soft);
}
.toggle.on::after {
    left: 17px;
    background: var(--primary);
}

/* SPARKLINE */
.spark {
    height: 60px;
    display: flex;
    align-items: flex-end;
    gap: 2px;
    margin: 12px 0;
}
.spark .b {
    flex: 1;
    background: var(--primary);
    min-height: 2px;
    opacity: .7;
}
.spark .b:last-child {
    opacity: 1;
    box-shadow: 0 0 8px var(--primary), 0 0 16px rgba(230, 248, 252, .18);
}

/* CROSSHAIR */
.crosshair {
    position: absolute;
    color: var(--primary);
    font-family: var(--font-mono);
    font-size: 14px;
}

/* ==========================================================================
   RESPONSIVE WEB SHELL (Stage 27) — desktop ≥1024px
   AuthLayout uses its own root (.auth-layout) so sidebar/rail rules
   scoped to .device never fire on auth routes — no extra toggles needed.
   ========================================================================== */

/* --- device grid container ---
   Mobile: body-level scroll. `.device` is at least the visible viewport
   (`min-height: 100dvh`), can grow taller when content needs to scroll.
   `dvh` (dynamic viewport height) tracks iOS Safari URL-bar collapse so
   the device matches the *currently visible* viewport — using plain `vh`
   would compute against the largest viewport (toolbar collapsed) and on
   the first paint with toolbar visible, the device would already overflow
   the screen, leaving an extra ~70px of dead scroll past content.
   Desktop (≥1024px) overrides to a fixed-height grid with internal scroll. */
.device {
    width: 100%;
    min-height: 100dvh;
    background: var(--bg-0);
    position: relative;
    display: flex;
    flex-direction: column;
}

@supports not (min-height: 100dvh) {
    .device { min-height: 100vh; }
}

/* column within the device that holds appbar + content + botnav */
.device-main {
    display: flex;
    flex-direction: column;
    flex: 1;
    min-width: 0;
}

/* On mobile this just reserves space below the fixed bottom-nav; the body
   itself is the scroll container so sticky `.appbar` works naturally and
   page-level content (FEED tabs, profile hero, etc.) doesn't need to fight
   a flex parent for an internal scroll context. */
.app-content {
    flex: 1;
    padding-bottom: var(--botnav-h);
}

/* sidebar and rail hidden by default (mobile-first) */
.desktop-side,
.desktop-rail {
    display: none;
}

/* --- Mobile app shell: internal scroll ---
   Below the desktop breakpoint the content column is the scroll container and
   the document itself never scrolls. This keeps the app bar and bottom nav
   pinned like a native app: iOS Safari rubber-bands the *document* on every
   page end (ignoring overscroll-behavior on the root) and drags fixed elements
   along with it, which read as "the whole screen scrolls". Auth pages have no
   .device and keep body-level scroll. Mirrors the desktop rules below. */
@media (max-width: 1023.98px) {
    html:has(.device),
    body:has(.device) {
        height: 100dvh;
        min-height: 0;
        overflow: hidden;
    }

    @supports not (height: 100dvh) {
        html:has(.device),
        body:has(.device) {
            height: 100vh;
        }
    }

    .device {
        height: 100%;
        min-height: 0;
    }

    .device-main {
        min-height: 0;
        overflow: hidden;
    }

    .app-content {
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior-y: contain;
        -webkit-overflow-scrolling: touch;
    }

    body.modal-open .app-content {
        overflow: hidden;
    }
}

/* --- Auth layout desktop centering ---
   The wrapper is a passthrough so each auth page (.login-page,
   .register-page, .onb-page) controls its own width/height/centering. */
.auth-layout {
    min-height: 100vh;
    background: var(--bg-0);
}

.auth-content {
    width: 100%;
    min-height: 100vh;
}

@media (min-width: 1024px) {
    /* --- unbox device into 3-column grid --- */
    .device {
        height: 100vh;
        max-height: none;
        border-radius: 0;
        box-shadow: none;
        display: grid;
        grid-template-columns: 240px 1fr 320px;
        overflow: hidden;
    }

    .device-main {
        grid-column: 2;
        grid-row: 1;
        overflow: hidden;
    }

    .app-content {
        padding-bottom: 0;
        overflow-y: auto;
        padding: 28px 32px 60px;
    }

    .app-content::-webkit-scrollbar { width: 6px; display: block; }
    .app-content::-webkit-scrollbar-thumb { background: var(--border); }

    /* --- sidebar (left column) --- */
    .desktop-side {
        grid-column: 1;
        grid-row: 1;
        background: #080808;
        border-right: 1px solid var(--bd-2);
        display: flex;
        flex-direction: column;
        padding: 18px 0;
        z-index: 60;
    }

    .desktop-side .ds-brand {
        padding: 0 20px 18px;
        display: flex;
        align-items: center;
        gap: 10px;
        border-bottom: 1px solid var(--bd-2);
        margin-bottom: 14px;
    }

    .desktop-side .ds-mark {
        width: 32px;
        height: 32px;
        background: var(--primary);
        color: var(--primary-foreground);
        font-family: var(--font-display);
        font-size: 18px;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .desktop-side .ds-h {
        font-family: var(--font-display);
        font-size: 18px;
        letter-spacing: -.02em;
    }

    .desktop-side .ds-s {
        font-family: var(--font-mono);
        font-size: 9px;
        letter-spacing: .16em;
        color: var(--tx-3);
        margin-top: 2px;
    }

    .desktop-side .ds-item {
        display: flex;
        align-items: center;
        gap: 12px;
        padding: 10px 16px;
        margin: 0 8px;
        color: var(--tx-2);
        cursor: pointer;
        font-family: var(--font-mono);
        font-size: 12px;
        letter-spacing: .06em;
        text-transform: uppercase;
        font-weight: 600;
        border-left: 2px solid transparent;
        background: transparent;
        border-top: 0;
        border-right: 0;
        border-bottom: 0;
        width: calc(100% - 16px);
        text-align: left;
        position: relative;
        text-decoration: none;
    }

    .desktop-side .ds-item:hover {
        color: var(--tx-1);
        background: var(--bg-1);
    }

    .desktop-side .ds-item.active {
        color: var(--tx-1);
        background: var(--primary-soft);
        border-left-color: var(--primary);
    }

    .desktop-side .ds-item .ico {
        width: 18px;
        height: 18px;
        flex-shrink: 0;
    }

    .desktop-side .ds-item .badge {
        margin-left: auto;
        background: var(--primary);
        color: var(--primary-foreground);
        font-size: 9px;
        padding: 1px 5px;
        font-weight: 700;
    }

    .desktop-side .ds-item .badge.r {
        background: var(--danger);
        color: #fff;
    }

    .desktop-side .ds-foot {
        margin-top: auto;
        padding: 14px 18px;
        border-top: 1px solid var(--bd-2);
        display: flex;
        align-items: center;
        gap: 10px;
    }

    .desktop-side .ds-sec {
        padding: 8px 12px;
        font-family: var(--font-mono);
        font-size: 9px;
        letter-spacing: .16em;
        text-transform: uppercase;
        color: var(--tx-3);
        margin-top: 8px;
    }

    /* --- right rail (third column) --- */
    .desktop-rail {
        grid-column: 3;
        grid-row: 1;
        background: #080808;
        border-left: 1px solid var(--bd-2);
        overflow-y: auto;
        padding: 20px;
        display: flex;
        flex-direction: column;
        gap: 24px;
        z-index: 60;
    }

    .desktop-rail::-webkit-scrollbar { width: 4px; }
    .desktop-rail::-webkit-scrollbar-thumb { background: var(--border); }

    .desktop-rail .dr-sec {
        display: flex;
        flex-direction: column;
        gap: 10px;
    }

    .desktop-rail .dr-h {
        font-family: var(--font-mono);
        font-size: 10px;
        letter-spacing: .16em;
        text-transform: uppercase;
        color: var(--tx-3);
        display: flex;
        align-items: center;
        justify-content: space-between;
        border-bottom: 1px solid var(--bd-2);
        padding-bottom: 8px;
        gap: 8px;
    }

    .desktop-rail .dr-mini {
        display: flex;
        gap: 10px;
        padding: 8px 0;
        border-bottom: 1px solid var(--bd-1);
        align-items: flex-start;
    }

    .desktop-rail .dr-mini:last-child { border-bottom: 0; }

    .desktop-rail .dr-mini .icobx {
        width: 26px;
        height: 26px;
        border: 1px solid var(--bd-2);
        display: flex;
        align-items: center;
        justify-content: center;
        flex-shrink: 0;
        color: var(--tx-2);
    }

    .desktop-rail .dr-mini .icobx.r { border-color: var(--danger); color: var(--danger); }
    .desktop-rail .dr-mini .icobx.g { border-color: var(--active); color: var(--active); }
    .desktop-rail .dr-mini .icobx.i { border-color: var(--primary); color: var(--primary); }

    .desktop-rail .dr-mini .ttl {
        font-family: var(--font-sans);
        font-weight: 600;
        font-size: 12px;
        line-height: 1.35;
    }

    .desktop-rail .dr-mini .meta {
        font-family: var(--font-mono);
        font-size: 9px;
        letter-spacing: .08em;
        text-transform: uppercase;
        color: var(--tx-3);
        margin-top: 2px;
    }

    .desktop-rail .dr-live-card {
        padding: 12px;
        cursor: pointer;
        display: flex;
        flex-direction: column;
        gap: 10px;
    }

    .desktop-rail .dr-live-head {
        display: flex;
        align-items: center;
        justify-content: space-between;
    }

    .desktop-rail .dr-live-roster {
        display: flex;
        flex-direction: column;
        gap: 6px;
        padding: 8px 0;
        border-top: 1px solid var(--bd-2);
        border-bottom: 1px solid var(--bd-2);
    }

    .desktop-rail .dr-live-athlete {
        display: grid;
        grid-template-columns: 24px 1fr auto;
        align-items: center;
        gap: 8px;
    }

    .desktop-rail .dr-live-athlete-name {
        font-family: var(--font-sans);
        font-weight: 600;
        font-size: 11px;
        letter-spacing: .04em;
        color: var(--tx-1);
        text-transform: uppercase;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .desktop-rail .dr-live-athlete-meta {
        font-family: var(--font-mono);
        font-size: 9px;
        letter-spacing: .08em;
        color: var(--tx-3);
        text-align: right;
    }

    .desktop-rail .dr-live-foot {
        display: flex;
        flex-direction: column;
        gap: 4px;
    }

    .desktop-rail .dr-live-foot-money {
        display: flex;
        align-items: center;
        gap: 6px;
    }

    .desktop-rail .dr-live-sep {
        color: var(--tx-3);
        font-size: 9px;
    }

    /* --- hide mobile bottom nav on desktop --- */
    .botnav { display: none; }

    /* --- appbar collapses to thin sticky topbar --- */
    .appbar {
        margin-top: 0;
        padding: 14px 32px;
        height: auto;
        min-height: 60px;
        background: rgba(10, 10, 10, .92);
        backdrop-filter: blur(8px);
        position: sticky;
        top: 0;
        z-index: 50;
        border-bottom: 1px solid var(--bd-2);
    }

    /* hide duplicate avatar (sidebar shows it) */
    .appbar .avatar:first-child { display: none; }
    .appbar .grow { display: none; }

    /* --- auth layout stays single column --- */
    .auth-content {
        padding: 0;
    }
}

/* 1024–1279px: sidebar only, no rail */
@media (min-width: 1024px) and (max-width: 1279px) {
    .device { grid-template-columns: 200px 1fr; }
    .desktop-rail { display: none; }
}

/* CRT off toggle (global) */
body.crt-off .crt-overlay { display: none; }

/* ==========================================================================
   STAGE 25 EXTENSION — Shorthand utility classes (Heat Web Responsive)
   Aliases / additions for components and pages using compact class names.
   ========================================================================== */

/* --- Glow CSS custom properties (required by shorthand rules below) --- */
:root {
    --glow-ice: 0 0 8px var(--primary), 0 0 16px rgba(230, 248, 252, .18);
    --glow-red: 0 0 8px var(--danger), 0 0 16px rgba(239, 68, 68, .3);
    --glow-grn: 0 0 8px var(--active), 0 0 16px rgba(34, 197, 94, .3);
}

/* --- Color shorthands --- */
.muted { color: var(--muted-foreground); }
.dim   { color: var(--tx-3); }
.ice   { color: var(--primary); }
.red   { color: var(--danger); }
.grn   { color: var(--active); }
.yel   { color: var(--warning); }

/* --- Layout shorthands --- */
.row-between {
    display: flex;
    justify-content: space-between;
    align-items: center;
}
.row-end {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
}
.grow   { flex: 1; }
.center { display: flex; align-items: center; justify-content: center; }
.stack  { display: flex; flex-direction: column; }
.stack-sm { gap: 8px; }
.stack-md { gap: 12px; }
.stack-lg { gap: 16px; }
.stack-xl { gap: 24px; }

/* --- Avatar shorthands --- */
/* .av is used inside .appbar and .vs — define standalone here */
.av {
    width: 44px;
    height: 44px;
    background: var(--surface-2);
    border: 1px solid var(--border-default);
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-mono);
    font-weight: 700;
    font-size: 14px;
    flex-shrink: 0;
}
.av-sm {
    width: 32px;
    height: 32px;
    font-size: 11px;
}
.av-xs {
    width: 24px;
    height: 24px;
    font-size: 10px;
}
.av-lg {
    width: 56px;
    height: 56px;
    background: var(--surface-2);
    border: 1px solid var(--border-default);
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-mono);
    font-weight: 700;
    font-size: 18px;
}

/* --- Appbar child shorthands (brand/sub/icons already on .appbar — standalone aliases) --- */
.brand {
    font-family: var(--font-mono);
    font-weight: 800;
    font-size: 15px;
    letter-spacing: .02em;
}
.sub {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--tx-3);
    margin-top: 1px;
}
.icons {
    display: flex;
    gap: 6px;
    align-items: center;
}
.icons svg { width: 16px; height: 11px; }

/* --- Status dot --- */
.dot {
    width: 8px;
    height: 8px;
    background: var(--active);
    display: inline-block;
    border-radius: 50%;
    flex-shrink: 0;
    animation: pulse-dot 2s infinite;
}
.dot.r { background: var(--danger); }

/* --- Density --- */
body.compact .content    { padding: 10px 12px 80px; }
body.compact .card       { padding: 12px; }
body.compact .row-data   { padding: 10px 12px; }
body.compact .stack-md   { gap: 8px !important; }

/* --- Statsbar (compact alias for .stats-bar) --- */
.statsbar {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    background: var(--border-default);
    gap: 1px;
    margin: 12px 0;
}
.statsbar > * {
    background: var(--background);
    text-align: center;
    padding: 12px;
}
.stat-v {
    font-family: var(--font-mono);
    font-size: 18px;
    line-height: 1;
}
.stat-l {
    font-family: var(--font-mono);
    font-size: 9px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--muted-foreground);
    margin-top: 4px;
}

/* --- Filter bar (compact alias; .filter-tag already exists but this adds .filter-bar) --- */
.filter-bar {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    padding-bottom: 4px;
}
.filter-bar::-webkit-scrollbar { display: none; }

/* --- Data row (compact alias for .data-row) --- */
.row-data {
    /* Horizontal padding gives the hover background breathing room so it
       doesn't bleed all the way to the row edges. Negative margin keeps the
       non-hover layout aligned to the surrounding container's content edges. */
    padding: 14px 12px;
    margin: 0 -12px;
    display: flex;
    align-items: center;
    gap: 12px;
    border-bottom: 1px solid var(--border-default);
    transition: background .15s;
    cursor: pointer;
    text-decoration: none;
    color: inherit;
}
@media (hover: hover) {
    .row-data:hover { background: var(--surface-elevated); }
}
.row-data .ord         { color: var(--tx-3); font-family: var(--font-mono); width: 24px; flex-shrink: 0; font-size: 13px; }
.row-data .body        { flex: 1; min-width: 0; }
.row-data .title       { font-family: var(--font-sans); font-weight: 600; font-size: 14px; }
.row-data .meta        { font-family: var(--font-mono); font-size: 9px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted-foreground); margin-top: 2px; }

/* --- VS block (compact alias for .vs-block) --- */
.vs {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    align-items: start;
    gap: 12px;
    margin: 12px 0;
}

.vs > .vs-mid {
    /* See note on .vs-layout > .vs-mid — same reasoning. */
    padding-top: 22px;
}
.vs .player {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    text-align: center;
}
.vs .av-lg {
    width: 56px;
    height: 56px;
    background: var(--surface-2);
    border: 1px solid var(--border-default);
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-mono);
    font-weight: 700;
    font-size: 18px;
}
.vs .vs-mid {
    font-family: var(--font-mono);
    font-weight: 700;
    font-size: 14px;
    color: var(--tx-3);
    letter-spacing: .12em;
}

/* --- Progress (compact alias for .progress-track/.progress-fill) --- */
.prog {
    height: 6px;
    background: var(--surface-elevated);
    position: relative;
    overflow: hidden;
}
.prog-fill {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    background: var(--primary);
    transition: width 1s cubic-bezier(.25, .46, .45, .94);
}

/* --- Search bar --- */
.search-bar {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    border: 1px solid var(--border-default);
    background: var(--surface-elevated);
    color: var(--muted-foreground);
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: .08em;
}

/* --- Notification helper bubble --- */
.helper {
    font-family: var(--font-sans);
    font-size: 13px;
    line-height: 1.5;
    color: var(--muted-foreground);
}

/* --- Input shorthand (.input instead of .input-field) --- */
.input {
    width: 100%;
    background: var(--background);
    color: var(--foreground);
    border: 1px solid var(--border);
    padding: 12px 16px;
    font-family: var(--font-mono);
    font-size: 13px;
    letter-spacing: .08em;
    text-transform: uppercase;
    outline: none;
    transition: border-color .15s;
}
.input:focus       { border-color: var(--muted-foreground); }
.input::placeholder { color: var(--border); }

/* --- Base .btn (generic base, not replacing .btn-primary/.btn-secondary/.btn-danger) --- */
.btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    min-height: 44px;
    padding: 0 16px;
    font-family: var(--font-mono);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    border: 1px solid;
    cursor: pointer;
    background: transparent;
    color: var(--foreground);
    text-decoration: none;
    transition: opacity .15s, transform .1s;
}
.btn:active { transform: scale(.97); }

/* --- Tabs (compact alias for .tab-bar/.tab-item) --- */
.tabs {
    display: flex;
    border-bottom: 1px solid var(--border);
    margin: 0 -16px 16px;
}
.tab {
    flex: 1;
    min-height: var(--touch-target);
    padding: 14px 8px;
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--muted-foreground);
    background: transparent;
    border: 0;
    cursor: pointer;
    border-bottom: 2px solid transparent;
}
.tab.active {
    color: var(--foreground);
    border-bottom-color: var(--primary);
    background: var(--surface-elevated);
}

/* --- Timeline (compact alias for .timeline-*) --- */
.tl {
    position: relative;
    padding-left: 24px;
}
.tl::before {
    content: '';
    position: absolute;
    left: 7px;
    top: 6px;
    bottom: 6px;
    width: 1px;
    background: var(--border);
}
.tl-item {
    position: relative;
    padding: 10px 0;
}
.tl-item::before {
    content: '';
    position: absolute;
    left: -24px;
    top: 14px;
    width: 14px;
    height: 14px;
    border: 2px solid var(--border);
    background: var(--background);
}
.tl-item.win::before  { border-color: var(--active); }
.tl-item.loss::before { border-color: var(--danger); }

/* --- Chip balance shorthand alias --- */
.chip-bal {
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 600;
    padding: 8px 10px;
    border: 1px solid var(--border-default);
    display: inline-flex;
    gap: 6px;
    align-items: center;
    min-height: 36px;
    color: var(--foreground);
    text-decoration: none;
}

/* --- Status tag pulse keyframe (compact alias @keyframes pglow) --- */
@keyframes pglow {
    0%,  100% { box-shadow: 0 0 8px var(--danger); }
    50%        { box-shadow: 0 0 16px var(--danger), 0 0 24px rgba(239, 68, 68, .5); }
}
.status-tag.live { animation: pglow 2s infinite; }

/* --- Desktop type bumps (mirrors HTML mockup @media block) --- */
@media (min-width: 1024px) {
    .text-page-label { font-size: 48px; }
    .text-section-title { font-size: 1.75rem; }
    .statsbar > * { padding: 16px; }
    .stat-v    { font-size: 22px; }
}

/* ==========================================================================
   Stage 34 — Feed grid + tile overlays + fullscreen player
   ========================================================================== */

.feed-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 12px;
    margin-top: 16px;
}

@media (min-width: 768px) {
    .feed-grid {
        grid-template-columns: repeat(4, 1fr);
        gap: 16px;
    }
}

.feed-empty {
    text-align: center;
    padding: 4rem 1rem;
    color: var(--tx-2);
    font-family: var(--font-mono);
    letter-spacing: 0.08em;
    font-size: 0.85rem;
    text-transform: uppercase;
}

/* Real video element fills the tile beneath the overlays */
.feed-tile-vid {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    z-index: 1;
}

/* Meta overlay text rendered above the video */
.feed-tile-meta {
    position: relative;
    z-index: 2;
    font-family: var(--font-mono);
    font-size: 9px;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--tx-1);
    text-shadow: 0 1px 2px rgba(0,0,0,0.7);
}
.feed-tile-name {
    font-family: var(--font-display);
    font-size: 12px;
    letter-spacing: 0;
    color: var(--tx-1);
    margin-bottom: 2px;
}
.feed-tile-exercise {
    color: var(--tx-2);
    margin-bottom: 4px;
}
.feed-tile-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}
.feed-tile-score {
    color: var(--primary);
    font-weight: 600;
}
.feed-tile-chip {
    padding: 2px 6px;
    border: 1px solid var(--bd-2);
    color: var(--tx-2);
}
.feed-tile-chip.win {
    border-color: var(--active);
    color: var(--active);
}

/* Like button on tile */
.feed-like-btn {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 3;
    background: rgba(0, 0, 0, 0.5);
    border: 1px solid var(--bd-2);
    color: var(--tx-1);
    padding: 4px 8px;
    border-radius: 0;
    cursor: pointer;
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.06em;
    transition: background 120ms, border-color 120ms;
}
.feed-like-btn.liked {
    color: var(--active);
    border-color: var(--active);
}
.feed-like-btn:hover {
    background: rgba(0, 0, 0, 0.75);
}

.feed-tile {
    cursor: pointer;
}

/* Fullscreen player modal */
.feed-fs {
    position: fixed;
    inset: 0;
    z-index: 1000;
    background: rgba(0, 0, 0, 0.95);
    display: flex;
    align-items: center;
    justify-content: center;
}
.feed-fs-bg {
    position: absolute;
    inset: 0;
    cursor: pointer;
}
.feed-fs-stage {
    position: relative;
    width: 100%;
    max-width: 480px;
    height: 100%;
    max-height: 90vh;
    max-height: 90dvh; /* visible viewport on iOS Safari; see .modal-panel */
    aspect-ratio: 9/16;
    background: #000;
    overflow: hidden;
    border: 1px solid var(--bd-2);
}
.feed-fs-video {
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: #000;
    cursor: pointer;
    display: block;
}
.feed-fs-top {
    position: absolute;
    top: 12px;
    left: 12px;
    right: 12px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: var(--tx-1);
    z-index: 2;
}
.feed-fs-athlete {
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    background: rgba(0, 0, 0, 0.5);
    padding: 4px 10px;
    border: 1px solid var(--bd-2);
}
.feed-fs-close {
    background: rgba(0, 0, 0, 0.5);
    border: 1px solid var(--bd-2);
    color: var(--tx-1);
    font-size: 18px;
    width: 32px;
    height: 32px;
    cursor: pointer;
    line-height: 1;
}
.feed-fs-close:hover { border-color: var(--primary); color: var(--primary); }
.feed-fs-actions {
    position: absolute;
    right: 12px;
    bottom: 100px;
    display: flex;
    flex-direction: column;
    gap: 12px;
    z-index: 2;
}
.feed-fs-action {
    background: rgba(0, 0, 0, 0.5);
    border: 1px solid var(--bd-2);
    color: var(--tx-1);
    padding: 0;
    width: 44px;
    height: 44px;
    cursor: pointer;
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.04em;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
}
.feed-fs-action span { font-size: 9px; }
.feed-fs-action.liked { color: var(--active); border-color: var(--active); }
.feed-fs-action:hover { border-color: var(--primary); }
.feed-fs-bottom {
    position: absolute;
    bottom: 12px;
    left: 12px;
    right: 12px;
    color: var(--tx-1);
    z-index: 2;
}
.feed-fs-caption {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    margin-bottom: 8px;
    background: rgba(0, 0, 0, 0.5);
    padding: 6px 10px;
    border: 1px solid var(--bd-2);
    display: inline-block;
}
.feed-fs-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: rgba(0, 0, 0, 0.5);
    padding: 8px;
    border: 1px solid var(--bd-2);
}
.feed-fs-nav {
    background: transparent;
    border: 1px solid var(--bd-2);
    color: var(--tx-1);
    padding: 4px 10px;
    cursor: pointer;
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.06em;
}
.feed-fs-nav:hover:not(:disabled) { border-color: var(--primary); color: var(--primary); }
.feed-fs-nav:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}
.feed-fs-counter {
    font-family: var(--font-mono);
    font-size: 10px;
    letter-spacing: 0.05em;
    color: var(--tx-2);
}

/* ──────────────────────────────────────────────────────────
   Exercise picker — search + group accordion (global)
   Used by CreateBattle wizard step 2 and ExercisePreferenceSelector modal.
   ────────────────────────────────────────────────────────── */

.exercise-search {
    display: flex;
    align-items: center;
    gap: 8px;
    border: 1px solid var(--border);
    padding: 10px 12px;
    background: var(--surface-1);
}

.exercise-search > input {
    flex: 1;
    background: transparent;
    border: none;
    color: var(--foreground);
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    outline: none;
}

.exercise-search > input::placeholder {
    color: var(--muted-foreground);
}

.exercise-group {
    border: 1px solid var(--border);
    background: var(--surface-1);
}

.exercise-group + .exercise-group {
    margin-top: -1px;
}

.exercise-group-header {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 14px;
    background: transparent;
    border: none;
    color: var(--foreground);
    font-family: var(--font-mono);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    cursor: pointer;
    text-align: left;
}

.exercise-group-header:hover {
    background: var(--surface-2);
}

.exercise-group-chevron {
    font-family: var(--font-mono);
    font-size: 16px;
    color: var(--muted-foreground);
}

.exercise-group-list {
    display: grid;
    grid-template-columns: 1fr;
    gap: 10px;
    padding: 0 12px 12px;
}

@media (min-width: 768px) {
    .exercise-group-list {
        grid-template-columns: 1fr 1fr;
    }
}

@media (min-width: 1024px) {
    .exercise-group-list {
        grid-template-columns: 1fr 1fr 1fr;
    }
}

/* ============================================================
   Reduced motion — applied via `body.motion-reduced` (explicit user
   setting from Settings → REDUCED MOTION → ON) OR via the OS-level
   `prefers-reduced-motion: reduce` query (when user keeps the setting
   on AUTO and their system requests reduced motion). The override
   `data-reduced-motion="off"` would force animations on, but currently
   we just rely on absence of the class for the OFF state.
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
    body:not(.motion-reduced-off) *,
    body:not(.motion-reduced-off) *::before,
    body:not(.motion-reduced-off) *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

body.motion-reduced *,
body.motion-reduced *::before,
body.motion-reduced *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
}

/* ============================================================
   Avatar tile (AvatarTile component)
   Renders either an SVG mark from the IconSprite or two-letter
   initials inside a sized square frame. Used everywhere a user
   appears (profile, vs-block, sidebar, leaderboard, top bar).
   ============================================================ */

.avt {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--surface-2);
    border: 1px solid var(--border-default);
    overflow: hidden;
    flex-shrink: 0;
    box-sizing: border-box;
}

.avt-svg {
    width: 72%;
    height: 72%;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.avt-initials {
    font-family: var(--font-mono);
    font-weight: 700;
    color: var(--tx-1);
    text-transform: uppercase;
    line-height: 1;
}

.avt-xs { width: 24px; height: 24px; }
.avt-xs .avt-initials { font-size: 10px; }
.avt-sm { width: 32px; height: 32px; }
.avt-sm .avt-initials { font-size: 11px; }
.avt-md { width: 44px; height: 44px; }
.avt-md .avt-initials { font-size: 14px; }
.avt-lg { width: 56px; height: 56px; }
.avt-lg .avt-initials { font-size: 18px; }
.avt-xl { width: 80px; height: 80px; }
.avt-xl .avt-initials { font-size: 24px; }

/* ============================================================
   Avatar picker (modal)
   Grid of all avatar marks + 8 colour chips, with live preview.
   ============================================================ */

.av-picker {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.av-picker-panel {
    margin-top: 12px;
    padding: 14px;
    background: var(--surface-2);
    border: 1px solid var(--border);
}

.av-picker-preview {
    display: flex;
    gap: 16px;
    align-items: center;
    padding: 16px;
    background: var(--surface-2);
    border: 1px solid var(--border);
}

.av-picker-grid {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 8px;
}

@media (max-width: 480px) {
    .av-picker-grid { grid-template-columns: repeat(4, 1fr); }
}

.av-picker-item {
    background: transparent;
    border: 1px solid var(--border);
    padding: 6px;
    cursor: pointer;
    transition: border-color 120ms ease, background 120ms ease;
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 1;
    color: inherit;
    font: inherit;
}

@media (hover: hover) {
    .av-picker-item:hover {
        border-color: var(--primary);
    }
}

.av-picker-item.selected {
    border-color: var(--primary);
    background: var(--primary-soft);
}

.av-picker-svg {
    width: 80%;
    height: 80%;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.av-picker-colors {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.av-picker-color {
    width: 32px;
    height: 32px;
    background: var(--c);
    border: 2px solid transparent;
    cursor: pointer;
    padding: 0;
    transition: transform 120ms ease, border-color 120ms ease;
    box-sizing: border-box;
}

@media (hover: hover) {
    .av-picker-color:hover {
        transform: scale(1.1);
    }
}

.av-picker-color.selected {
    border-color: var(--background);
    outline: 2px solid var(--c);
    outline-offset: 0;
}

/* ── PROFILE HERO — social counts + actions ── */
.profile-social-counts {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 24px;
    margin: 16px 0 4px;
}
.profile-social-count {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 2px;
    text-decoration: none;
    color: inherit;
    cursor: pointer;
    padding: 4px 8px;
    border-radius: 4px;
    transition: background 120ms ease;
}
@media (hover: hover) {
    .profile-social-count:hover {
        background: var(--surface-2);
    }
}
.profile-social-divider {
    width: 1px;
    height: 24px;
    background: var(--bd-2);
}

.profile-actions {
    display: flex;
    gap: 10px;
    justify-content: center;
    flex-wrap: wrap;
    margin-top: 18px;
}
/* Override .btn-primary / .btn-active / .btn-secondary defaults (width:100%,
   min-height:44px) — those are designed for full-width form submits, not for
   pill-style action buttons that sit inline within a hero card.

   Auto width keeps the button proportional to its label so a single FOLLOW
   button doesn't span the entire card on desktop (which made the active-state
   green tint feel like a banner instead of a button). */
.profile-action-btn {
    width: auto;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    font-size: 12px;
    padding: 10px 22px;
    min-width: 0;
    min-height: 38px;
}

@media (max-width: 480px) {
    .profile-social-counts { gap: 16px; }
    /* Mobile: let buttons share the row width (still constrained) so
       single-button states (FOLLOW alone) don't sit awkwardly small. */
    .profile-action-btn {
        flex: 1 1 140px;
        max-width: 240px;
        padding: 11px 18px;
    }
}

/* ── VS layout — clickable player block (navigates to athlete profile) ── */
.vs-player-clickable {
    cursor: pointer;
    border-radius: 4px;
    padding: 4px 8px;
    transition: background 120ms ease;
}
@media (hover: hover) {
    .vs-player-clickable:hover {
        background: var(--surface-2);
    }
}

.feed-tile-name-clickable {
    cursor: pointer;
    transition: color 120ms ease;
}
@media (hover: hover) {
    .feed-tile-name-clickable:hover {
        color: var(--primary);
    }
}

/* ── CHAT HUB ROW ── */
.chat-row-body {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}
.chat-row-title {
    font-family: var(--font-mono);
    font-size: 12px;
    letter-spacing: .08em;
    text-transform: uppercase;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.chat-row-time {
    font-family: var(--font-mono);
    font-size: 9px;
    letter-spacing: .08em;
    color: var(--tx-3);
    flex-shrink: 0;
    white-space: nowrap;
}
.chat-row-preview {
    font-family: var(--font-sans);
    font-size: 13px;
    color: var(--muted-foreground);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    line-height: 1.35;
}
.chat-row-preview.unread {
    color: var(--foreground);
    font-weight: 600;
}
.chat-row-prefix {
    color: var(--tx-3);
    margin-right: 4px;
    text-transform: uppercase;
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: .08em;
}
.chat-unread-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--primary);
    box-shadow: 0 0 6px var(--primary);
    flex-shrink: 0;
    align-self: center;
}
.chat-row-unread .chat-row-title {
    color: var(--primary);
}

/* ── DESKTOP RAIL — empty state ──
   Distinct from .dr-h titles: sentence-case Inter (not mono `///` slug),
   smaller, italic, indented — reads as informational copy, not a header. */
.desktop-rail .dr-empty {
    font-family: var(--font-sans);
    font-size: 12px;
    font-style: italic;
    color: var(--tx-3);
    padding: 14px 4px 6px;
    line-height: 1.4;
}

/* ── LOCKED SECTION — placeholder for content gated by status (workout
   detail before live, coaching before completed). Subdued, lock icon left,
   short label + optional hint right. */
.locked-section {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 12px;
    border: 1px dashed var(--border);
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.02);
}

.locked-section .locked-icon {
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--tx-3);
    flex-shrink: 0;
}

.locked-section .locked-icon .ico {
    width: 18px;
    height: 18px;
}

.locked-section .locked-text {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

/* Movement standards collapse trigger inside .workout-detail-card */
.workout-detail-card .standards-toggle {
    background: none;
    border: none;
    padding: 0;
    cursor: pointer;
    color: var(--tx-3);
    display: inline-flex;
    align-items: center;
}

.workout-detail-card .standards-toggle:hover {
    color: var(--primary);
}

/* Smooth height-auto collapse via the grid-rows 0fr→1fr trick. Inner element
   keeps overflow:hidden so the row clip cuts the content. Works in all evergreen
   browsers (Chrome 117+, Safari 17.4+, Firefox 117+). */
.workout-detail-card .standards-collapse {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 300ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

.workout-detail-card .standards-collapse[data-open="true"] {
    grid-template-rows: 1fr;
}

.workout-detail-card .standards-collapse-inner {
    overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
    .workout-detail-card .standards-collapse {
        transition: none;
    }
}

/* ── COACH FEEDBACK card ──
   Distinct accent (primary cyan tint) so AI coaching reads like an in-character
   broadcast, not just another result row. */
.coach-feedback-card {
    border-left: 2px solid var(--primary);
    background: rgba(230, 248, 252, 0.03);
    padding: 16px 18px;
}

/* ── WORKOUT PREVIEW / DETAIL card layout ──
   Header is a 70/30 grid: workout title (primary cyan) on the left, and
   type tag + time cap stacked on the right. Stats / sections sit below.
   Slightly more generous outer padding than the default .card so the
   right-aligned tag/time don't crowd the corner. */
.workout-preview-card,
.workout-detail-card {
    padding: 1.5rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.workout-preview-card .wp-head,
.workout-detail-card .wp-head {
    display: grid;
    grid-template-columns: 70% 30%;
    gap: 12px;
    align-items: start;
}

.workout-preview-card .wp-head-title,
.workout-detail-card .wp-head-title {
    min-width: 0;
    line-height: 1.2;
}

.workout-preview-card .wp-head-meta,
.workout-detail-card .wp-head-meta {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
    text-align: right;
}

.workout-preview-card .wp-stats,
.workout-detail-card .wp-stats {
    display: flex;
    gap: 32px;
    padding: 12px 0;
    border-top: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
}

.workout-preview-card .wp-stat,
.workout-detail-card .wp-stat {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.workout-preview-card .wp-section,
.workout-detail-card .wp-section {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.workout-preview-card .wp-section-label,
.workout-detail-card .wp-section-label {
    margin: 0;
}

.workout-preview-card .wp-chip-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.workout-preview-card .wp-inline-list,
.workout-detail-card .wp-inline-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px 10px;
    align-items: center;
    line-height: 1.5;
}

.workout-preview-card .wp-sep,
.workout-detail-card .wp-sep {
    color: var(--tx-3);
    user-select: none;
    line-height: 1;
}

.workout-detail-card .wp-movement-row {
    padding: 10px 0;
}

.workout-detail-card .wp-movement-name {
    font-size: 13px;
    font-weight: 500;
    text-shadow: 0 0 8px rgba(230, 248, 252, 0.18);
}

/* ── Workout unlock animation ──
   Detail card slides up + fades in on first paint. Since the preview/detail
   are distinct components, the DOM swap on Scheduled→Live transition (or
   on a fresh page load when the battle is already live) auto-triggers this
   entrance. Movement rows stagger in below the card. */
@keyframes workout-unlock-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes workout-movement-in {
    from { opacity: 0; transform: translateX(-4px); }
    to   { opacity: 1; transform: translateX(0); }
}

.workout-detail-card {
    animation: workout-unlock-in 450ms cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

.workout-detail-card .wp-movement-row {
    opacity: 0;
    animation: workout-movement-in 320ms ease-out both;
}

.workout-detail-card .wp-movement-row:nth-child(2)  { animation-delay: 200ms; }
.workout-detail-card .wp-movement-row:nth-child(3)  { animation-delay: 260ms; }
.workout-detail-card .wp-movement-row:nth-child(4)  { animation-delay: 320ms; }
.workout-detail-card .wp-movement-row:nth-child(5)  { animation-delay: 380ms; }
.workout-detail-card .wp-movement-row:nth-child(6)  { animation-delay: 440ms; }
.workout-detail-card .wp-movement-row:nth-child(7)  { animation-delay: 500ms; }
.workout-detail-card .wp-movement-row:nth-child(8)  { animation-delay: 560ms; }
.workout-detail-card .wp-movement-row:nth-child(n+9) { animation-delay: 620ms; }

@media (prefers-reduced-motion: reduce) {
    .workout-detail-card,
    .workout-detail-card .wp-movement-row {
        animation: none;
        opacity: 1;
        transform: none;
    }
}
