/* ══════════════════════════════════════════════════════════════════════
   TAMIJI UI — Design System
   ----------------------------------------------------------------------
   Hand-written, build-free. Load AFTER /public/style.css:

       <link rel="stylesheet" href="/public/style.css">
       <link rel="stylesheet" href="/public/ui.css">

   Every class is prefixed `ui-` so it never collides with Tailwind
   utilities or the legacy classes in style.css.

   Rules of the road:
     1. Never hard-code a colour in a page. Use a token.
     2. Never invent a radius or font-size. Use the scale.
     3. Markup declares INTENT (surface, muted text, tone). The theme decides
        the pixels. No `!important` colour overrides. Ever.

   THEMING CONTRACT
   ----------------
   One switch for the whole product: `data-ui-theme` on <html>.

       <html data-ui-theme="dark">   → dark tokens
       <html data-ui-theme="light">  → light tokens (also the default)

   Every v2 page must set it BEFORE first paint with a blocking head script,
   otherwise the page flashes the wrong theme:

       <script>
         (function () {
           var d = 'light';                    // this page's default
           var m = document.cookie.match(/(?:^|;\s*)tamiji_theme_preference=([^;]*)/);
           var t = (m && decodeURIComponent(m[1]))
                || localStorage.getItem('theme-preference') || d;
           document.documentElement.dataset.uiTheme = t === 'dark' ? 'dark' : 'light';
         })();
       </script>

   Portals default to 'light'; the arena and games pages default to 'dark'.
   `TamijiTheme.apply()` keeps the attribute in sync when the user toggles.

   Body must also carry `data-ui="v2"` — that's what tells
   portal-components.js to skip the legacy dark-mode override stylesheet.
   ══════════════════════════════════════════════════════════════════════ */


/* ─── 1. TOKENS ─────────────────────────────────────────────────────── */

/* Mode-independent: scales, motion, spacing. Never themed. */
:root {
    /* Radius scale — five steps, no exceptions */
    --ui-r-sm: 8px;
    --ui-r-md: 12px;
    --ui-r-lg: 16px;
    --ui-r-xl: 22px;
    --ui-r-2xl: 28px;
    --ui-r-full: 999px;

    /* Spacing rhythm (4px base) */
    --ui-s-1: 4px;
    --ui-s-2: 8px;
    --ui-s-3: 12px;
    --ui-s-4: 16px;
    --ui-s-5: 20px;
    --ui-s-6: 24px;
    --ui-s-8: 32px;
    --ui-s-10: 40px;
    --ui-s-12: 48px;
    --ui-s-16: 64px;

    /* Motion */
    --ui-ease: cubic-bezier(0.4, 0, 0.2, 1);
    --ui-fast: 140ms;
    --ui-base: 220ms;

    /* Fixed hues — these mean the same thing in both modes */
    --ui-on-accent: #ffffff;
    --ui-success: #10b981;
    --ui-warning: #f59e0b;
    --ui-danger: #ef4444;
}

/* ── LIGHT (default) ── */
:root,
html[data-ui-theme="light"] {
    color-scheme: light;

    /* Surfaces — 0 is the page, higher numbers sit closer to the viewer */
    --ui-surface-0: #f7f8fc;
    --ui-surface-1: #ffffff;
    --ui-surface-2: #ffffff;
    --ui-surface-3: rgba(15, 23, 42, 0.04);
    --ui-surface-inset: #f1f5f9;

    --ui-border: rgba(15, 23, 42, 0.10);
    --ui-border-strong: rgba(15, 23, 42, 0.18);

    --ui-text: #0f172a;
    --ui-text-secondary: #475569;
    --ui-text-muted: #64748b;
    --ui-text-faint: #94a3b8;

    --ui-accent: #4f46e5;
    --ui-accent-hover: #4338ca;
    --ui-accent-text: #4338ca;
    --ui-accent-soft: rgba(79, 70, 229, 0.09);
    --ui-accent-line: rgba(79, 70, 229, 0.22);

    --ui-success-text: #047857;
    --ui-success-soft: rgba(16, 185, 129, 0.11);
    --ui-warning-text: #b45309;
    --ui-warning-soft: rgba(245, 158, 11, 0.14);
    --ui-danger-text: #b91c1c;
    --ui-danger-soft: rgba(239, 68, 68, 0.08);
    --ui-danger-line: rgba(239, 68, 68, 0.22);

    --ui-shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.05);
    --ui-shadow-md: 0 2px 8px rgba(15, 23, 42, 0.05), 0 8px 24px rgba(15, 23, 42, 0.04);
    --ui-shadow-lg: 0 8px 24px rgba(15, 23, 42, 0.07), 0 24px 56px rgba(15, 23, 42, 0.07);
    --ui-shadow-accent: 0 4px 14px rgba(79, 70, 229, 0.20);

    /* Ink surfaces — deliberately dark panels that stay dark in BOTH modes
       (hero, spotlight). Their own text tokens travel with them. */
    --ui-ink: #111827;
    --ui-ink-2: rgba(255, 255, 255, 0.08);
    --ui-ink-text: #f8fafc;
    --ui-ink-muted: #cbd5e1;
    --ui-ink-border: rgba(255, 255, 255, 0.12);
}

/* ── DARK ── */
html[data-ui-theme="dark"] {
    color-scheme: dark;

    --ui-surface-0: #0b1120;
    --ui-surface-1: #151d2e;
    --ui-surface-2: #1b2436;
    --ui-surface-3: rgba(255, 255, 255, 0.06);
    --ui-surface-inset: #0d1424;

    --ui-border: rgba(255, 255, 255, 0.09);
    --ui-border-strong: rgba(255, 255, 255, 0.18);

    --ui-text: #f1f5f9;
    --ui-text-secondary: #cbd5e1;
    --ui-text-muted: #94a3b8;
    --ui-text-faint: #64748b;

    --ui-accent: #6366f1;
    --ui-accent-hover: #818cf8;
    --ui-accent-text: #a5b4fc;
    --ui-accent-soft: rgba(99, 102, 241, 0.16);
    --ui-accent-line: rgba(99, 102, 241, 0.34);

    --ui-success-text: #6ee7b7;
    --ui-success-soft: rgba(16, 185, 129, 0.15);
    --ui-warning-text: #fcd34d;
    --ui-warning-soft: rgba(245, 158, 11, 0.15);
    --ui-danger-text: #fca5a5;
    --ui-danger-soft: rgba(239, 68, 68, 0.13);
    --ui-danger-line: rgba(239, 68, 68, 0.28);

    --ui-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.40);
    --ui-shadow-md: 0 2px 8px rgba(0, 0, 0, 0.35), 0 8px 24px rgba(0, 0, 0, 0.30);
    --ui-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.45), 0 24px 56px rgba(0, 0, 0, 0.40);
    --ui-shadow-accent: 0 4px 14px rgba(99, 102, 241, 0.30);

    /* In dark mode the ink surface lifts slightly so it still separates
       from the page behind it. */
    --ui-ink: #1b2436;
    --ui-ink-2: rgba(255, 255, 255, 0.06);
    --ui-ink-text: #f1f5f9;
    --ui-ink-muted: #cbd5e1;
    --ui-ink-border: rgba(255, 255, 255, 0.10);
}

/* Respect the OS when the page hasn't resolved a preference yet. */
@media (prefers-color-scheme: dark) {
    html:not([data-ui-theme]) body[data-ui-theme-auto] {
        color-scheme: dark;
    }
}


/* ─── 1b. ACCENT ────────────────────────────────────────────────────── */
/* One accent for the whole product. There is no per-portal colour any more:
   Family, Couple, Junior and Student are the same product wearing the same
   clothes, and the only visual switch is light vs dark.

   The `ui-tone-*` class names survive across the codebase but are deliberately
   inert — every one of them resolves to the single accent below. Keeping them
   inert rather than deleting them from ~40 files means no element can end up
   unstyled because a class was missed, and re-introducing accent variation
   later is a change in this one block. */

:root {
    --ui-tone: var(--ui-accent);
    --ui-tone-text: var(--ui-accent-text);
    --ui-tone-soft: var(--ui-accent-soft);
    --ui-tone-line: var(--ui-accent-line);
}

[class*="ui-tone-"] {
    --ui-tone: var(--ui-accent);
    --ui-tone-text: var(--ui-accent-text);
    --ui-tone-soft: var(--ui-accent-soft);
    --ui-tone-line: var(--ui-accent-line);
}


/* ─── 1c. PAGE BASE ─────────────────────────────────────────────────── */
/* v2 pages own their own base styling so they don't depend on whatever
   legacy body rules a given page happens to inherit. */

body[data-ui="v2"] {
    margin: 0;
    min-height: 100vh;
    background: var(--ui-surface-0);
    color: var(--ui-text);
    font-family: 'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    overflow-x: hidden;
    transition: background-color var(--ui-base) var(--ui-ease),
                color var(--ui-base) var(--ui-ease);
}

/* Junior keeps Nunito — the one place a rounder voice earns its keep. */
body[data-ui="v2"][data-portal="junior"] {
    font-family: 'Nunito', ui-rounded, ui-sans-serif, system-ui, sans-serif;
}

body[data-ui="v2"] img { max-width: 100%; }

@media (prefers-reduced-motion: reduce) {
    body[data-ui="v2"] * {
        animation-duration: 0.01ms !important;
        transition-duration: 0.01ms !important;
    }
}


/* ─── 2. TYPOGRAPHY ─────────────────────────────────────────────────── */
/* Two weights carry the whole system: 700 for headings, 500 for body.
   The old design used font-black on everything, which flattened hierarchy. */

.ui-display,
.ui-h1, .ui-h2, .ui-h3, .ui-h4 {
    color: var(--ui-text);
    letter-spacing: -0.02em;
    margin: 0;
    text-wrap: balance;
}

.ui-display { font-size: clamp(2rem, 1.4rem + 2.6vw, 3rem); line-height: 1.06; font-weight: 800; letter-spacing: -0.035em; }
.ui-h1      { font-size: clamp(1.6rem, 1.25rem + 1.4vw, 2.125rem); line-height: 1.15; font-weight: 800; }
.ui-h2      { font-size: 1.375rem; line-height: 1.25; font-weight: 700; }
.ui-h3      { font-size: 1.0625rem; line-height: 1.35; font-weight: 700; }
.ui-h4      { font-size: 0.9375rem; line-height: 1.4; font-weight: 700; }

.ui-lead { font-size: 1rem;     line-height: 1.65; font-weight: 400; color: var(--ui-text-secondary); margin: 0; max-width: 60ch; }
.ui-body { font-size: 0.9375rem; line-height: 1.65; font-weight: 400; color: var(--ui-text-secondary); margin: 0; }
.ui-text-sm  { font-size: 0.875rem;  line-height: 1.55; color: var(--ui-text-secondary); }
.ui-text-xs  { font-size: 0.8125rem; line-height: 1.5;  color: var(--ui-text-muted); }
.ui-muted    { color: var(--ui-text-muted); }
.ui-faint    { color: var(--ui-text-faint); }
.ui-strong   { color: var(--ui-text); font-weight: 600; }

/* Micro-label above a heading. Replaces the old text-[9px] font-black soup. */
.ui-eyebrow {
    display: block;
    font-size: 0.6875rem;
    font-weight: 700;
    line-height: 1.4;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ui-text-muted);
    margin: 0;
}

.ui-numeric { font-variant-numeric: tabular-nums; }


/* ─── 3. LAYOUT PRIMITIVES ──────────────────────────────────────────── */

.ui-page {
    width: 100%;
    max-width: 1280px;
    margin-inline: auto;
    padding-inline: var(--ui-s-4);
    padding-block: var(--ui-s-6) var(--ui-s-16);
}

@media (min-width: 640px)  { .ui-page { padding-inline: var(--ui-s-6); } }
@media (min-width: 1024px) { .ui-page { padding-inline: var(--ui-s-8); } }

.ui-page--narrow { max-width: 720px; }

/* Vertical rhythm without a wrapper div per gap */
.ui-stack > :where(:not(.hidden):not([hidden])) ~ :where(:not(.hidden):not([hidden])) {
    margin-top: var(--ui-s-4);
}
.ui-stack-sm > :where(:not(.hidden):not([hidden])) ~ :where(:not(.hidden):not([hidden])) {
    margin-top: var(--ui-s-2);
}
.ui-stack-lg > :where(:not(.hidden):not([hidden])) ~ :where(:not(.hidden):not([hidden])) {
    margin-top: var(--ui-s-6);
}
.ui-stack-xl > :where(:not(.hidden):not([hidden])) ~ :where(:not(.hidden):not([hidden])) {
    margin-top: var(--ui-s-10);
}

.ui-row {
    display: flex;
    align-items: center;
    gap: var(--ui-s-3);
}
.ui-row--between { justify-content: space-between; }
.ui-row--wrap    { flex-wrap: wrap; }
.ui-spacer       { flex: 1 1 auto; }

.ui-grid { display: grid; gap: var(--ui-s-4); }
.ui-grid--2 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }

/* Always exactly two columns above 560px. Use this for an even number of
   equally-important tiles — auto-fit would leave a 3+1 orphan row. */
.ui-grid--pair { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 560px) {
    .ui-grid--pair { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.ui-grid--3 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.ui-grid--4 { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }

/* Main content + sidebar. Collapses to one column under 1024px. */
.ui-shell {
    display: grid;
    gap: var(--ui-s-6);
    align-items: start;
}
@media (min-width: 1024px) {
    .ui-shell { grid-template-columns: minmax(0, 1fr) 340px; }
    .ui-shell--wide-aside { grid-template-columns: minmax(0, 1fr) 380px; }

    /* Collapse the sidebar column entirely when the aside is hidden, so a
       logged-out visitor doesn't stare at 340px of dead space. */
    .ui-shell:has(> [data-aside].hidden),
    .ui-shell:has(> [data-aside].ui-hidden) {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Centred single-purpose panel — sign-in, empty account, confirmation */
.ui-panel-center {
    max-width: 480px;
    margin-inline: auto;
    margin-block: clamp(var(--ui-s-8), 6vw, var(--ui-s-16));
}

.ui-signin__lead {
    margin-inline: auto;
}

.ui-signin__actions {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--ui-s-3);
    margin-top: var(--ui-s-6);
}

.ui-divider {
    height: 1px;
    background: var(--ui-border);
    border: 0;
    margin-block: var(--ui-s-4);
}


/* ─── 4. APP HEADER ─────────────────────────────────────────────────── */

.ui-appbar {
    position: sticky;
    top: 0;
    z-index: 60;
    background: color-mix(in srgb, var(--ui-surface-0) 82%, transparent);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--ui-border);
}

.ui-appbar__inner {
    max-width: 1280px;
    margin-inline: auto;
    padding: var(--ui-s-3) var(--ui-s-4);
    display: flex;
    align-items: center;
    gap: var(--ui-s-4);
}
@media (min-width: 640px)  { .ui-appbar__inner { padding-inline: var(--ui-s-6); } }
@media (min-width: 1024px) { .ui-appbar__inner { padding-inline: var(--ui-s-8); } }

.ui-brand {
    display: inline-flex;
    align-items: center;
    gap: var(--ui-s-3);
    text-decoration: none;
    color: inherit;
    border-radius: var(--ui-r-md);
}

/* The brand is the wordmark. The coloured tile and tagline that used to sit
   here were decoration, not identity. */
.ui-brand__mark, .ui-brand__tag { display: none; }

.ui-brand__name {
    font-size: 1.0625rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--ui-text);
    line-height: 1.1;
}


/* Small square control — theme toggle, close, overflow menu */
.ui-iconbtn {
    width: 38px;
    height: 38px;
    flex: none;
    display: inline-grid;
    place-items: center;
    border-radius: var(--ui-r-md);
    border: 1px solid var(--ui-border);
    background: var(--ui-surface-3);
    color: var(--ui-text-secondary);
    font-size: 0.9375rem;
    cursor: pointer;
    transition: background var(--ui-fast) var(--ui-ease),
                border-color var(--ui-fast) var(--ui-ease),
                color var(--ui-fast) var(--ui-ease);
}
.ui-iconbtn:hover {
    background: var(--ui-accent-soft);
    border-color: var(--ui-accent-line);
    color: var(--ui-text);
}


/* ─── 5. SURFACES ───────────────────────────────────────────────────── */

.ui-card {
    background: var(--ui-surface-1);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-r-xl);
    box-shadow: var(--ui-shadow-md);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    padding: var(--ui-s-5);
    color: var(--ui-text-secondary);
}

@media (min-width: 640px) { .ui-card { padding: var(--ui-s-6); } }

.ui-card--flush   { padding: 0; overflow: hidden; }
.ui-card--tight   { padding: var(--ui-s-4); }
.ui-card--flat    { box-shadow: none; }
.ui-card--full    { height: 100%; display: flex; flex-direction: column; }
/* Gives a scrolling card a sensible floor without a magic fixed height */
.ui-card--minh    { min-height: 320px; }

/* Card header: title on the left, meta/actions on the right */
.ui-card__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ui-s-3);
    padding-bottom: var(--ui-s-3);
    margin-bottom: var(--ui-s-4);
    border-bottom: 1px solid var(--ui-border);
}
.ui-card__title {
    font-size: 0.875rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--ui-text);
    margin: 0;
}

/* Clickable card — used for the game picker */
.ui-card-select {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--ui-s-3);
    width: 100%;
    text-align: left;
    padding: var(--ui-s-5);
    background: var(--ui-surface-1);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-r-xl);
    box-shadow: var(--ui-shadow-sm);
    cursor: pointer;
    overflow: hidden;
    isolation: isolate;
    transition: border-color var(--ui-base) var(--ui-ease),
                transform var(--ui-base) var(--ui-ease),
                box-shadow var(--ui-base) var(--ui-ease);
}

/* Accent wash that grows on hover — replaces the old absolutely-positioned blob */
.ui-card-select::before {
    content: "";
    position: absolute;
    inset: auto -30% -60% auto;
    width: 220px;
    height: 220px;
    border-radius: 50%;
    background: var(--ui-tone-soft);
    opacity: 0;
    transform: scale(0.6);
    transition: opacity var(--ui-base) var(--ui-ease), transform var(--ui-base) var(--ui-ease);
    z-index: -1;
}

.ui-card-select:hover {
    border-color: color-mix(in srgb, var(--ui-tone) 45%, transparent);
    transform: translateY(-3px);
    box-shadow: var(--ui-shadow-lg);
}
.ui-card-select:hover::before { opacity: 1; transform: scale(1); }
.ui-card-select:active { transform: translateY(-1px); }

.ui-card-select__icon {
    width: 46px;
    height: 46px;
    display: grid;
    place-items: center;
    font-size: 1.5rem;
    line-height: 1;
    border-radius: var(--ui-r-md);
    background: var(--ui-tone-soft);
    border: 1px solid color-mix(in srgb, var(--ui-tone) 28%, transparent);
}

.ui-card-select__cta {
    margin-top: auto;
    padding-top: var(--ui-s-2);
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--ui-tone-text);
}
.ui-card-select__cta::after {
    content: "→";
    transition: transform var(--ui-base) var(--ui-ease);
}
.ui-card-select:hover .ui-card-select__cta::after { transform: translateX(4px); }


/* ─── 6. BUTTONS ────────────────────────────────────────────────────── */

.ui-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--ui-s-2);
    padding: 10px 18px;
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: -0.005em;
    border-radius: var(--ui-r-md);
    border: 1px solid transparent;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background var(--ui-fast) var(--ui-ease),
                border-color var(--ui-fast) var(--ui-ease),
                color var(--ui-fast) var(--ui-ease),
                box-shadow var(--ui-fast) var(--ui-ease),
                transform var(--ui-fast) var(--ui-ease);
}
.ui-btn:active { transform: translateY(1px); }

.ui-btn:disabled,
.ui-btn[aria-disabled="true"] {
    opacity: 0.45;
    cursor: not-allowed;
    transform: none;
}

.ui-btn--primary {
    background: var(--ui-accent);
    color: var(--ui-on-accent);
    box-shadow: var(--ui-shadow-accent);
}
.ui-btn--primary:hover:not(:disabled) { background: var(--ui-accent-hover); }

.ui-btn--secondary {
    background: var(--ui-surface-3);
    border-color: var(--ui-border);
    color: var(--ui-text);
}
.ui-btn--secondary:hover:not(:disabled) {
    background: var(--ui-accent-soft);
    border-color: var(--ui-accent-line);
}

.ui-btn--ghost {
    background: transparent;
    color: var(--ui-text-muted);
}
.ui-btn--ghost:hover:not(:disabled) {
    background: var(--ui-surface-3);
    color: var(--ui-text);
}

.ui-btn--danger {
    background: var(--ui-danger-soft);
    border-color: var(--ui-danger-line);
    color: var(--ui-danger-text);
}
.ui-btn--danger:hover:not(:disabled) {
    background: color-mix(in srgb, var(--ui-danger) 22%, transparent);
}

.ui-btn--sm    { padding: 7px 13px; font-size: 0.8125rem; border-radius: var(--ui-r-sm); }
.ui-btn--lg    { padding: 13px 26px; font-size: 0.9375rem; border-radius: var(--ui-r-lg); }
.ui-btn--block { width: 100%; }

/* Quiet inline link-button, e.g. "Back to games" */
.ui-btn-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--ui-accent-text);
    cursor: pointer;
    transition: color var(--ui-fast) var(--ui-ease);
}
.ui-btn-link:hover { color: var(--ui-text); }


/* ─── 7. FORMS ──────────────────────────────────────────────────────── */

.ui-field { display: block; }

.ui-label {
    display: block;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--ui-text-secondary);
    margin-bottom: 6px;
}

.ui-input,
.ui-select,
.ui-textarea {
    width: 100%;
    padding: 10px 14px;
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 500;
    line-height: 1.45;
    color: var(--ui-text);
    background: var(--ui-surface-inset);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-r-md);
    outline: none;
    transition: border-color var(--ui-fast) var(--ui-ease), box-shadow var(--ui-fast) var(--ui-ease);
}

.ui-input::placeholder,
.ui-textarea::placeholder { color: var(--ui-text-faint); }

.ui-input:focus,
.ui-select:focus,
.ui-textarea:focus {
    border-color: var(--ui-accent);
    box-shadow: 0 0 0 3px var(--ui-accent-soft);
}

.ui-hint { font-size: 0.75rem; color: var(--ui-text-muted); margin-top: 6px; }

/* One visible focus style for the whole app */
:where(.ui-btn, .ui-btn-link, .ui-iconbtn, .ui-card-select, .ui-brand):focus-visible {
    outline: 2px solid var(--ui-accent);
    outline-offset: 2px;
}


/* ─── 8. BADGES, CHIPS, STATUS ──────────────────────────────────────── */

.ui-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    font-size: 0.6875rem;
    font-weight: 600;
    line-height: 1.5;
    letter-spacing: 0.03em;
    border-radius: var(--ui-r-full);
    background: var(--ui-surface-3);
    border: 1px solid var(--ui-border);
    color: var(--ui-text-secondary);
    white-space: nowrap;
}

.ui-badge--accent  { background: var(--ui-accent-soft);  border-color: var(--ui-accent-line);  color: var(--ui-accent-text); }
.ui-badge--tone    { background: var(--ui-tone-soft);    border-color: color-mix(in srgb, var(--ui-tone) 30%, transparent); color: var(--ui-tone-text); }
.ui-badge--success { background: var(--ui-success-soft);  border-color: color-mix(in srgb, var(--ui-success) 30%, transparent); color: var(--ui-success-text); }
.ui-badge--warning { background: var(--ui-warning-soft);  border-color: color-mix(in srgb, var(--ui-warning) 30%, transparent); color: var(--ui-warning-text); }
.ui-badge--danger  { background: var(--ui-danger-soft);   border-color: var(--ui-danger-line); color: var(--ui-danger-text); }

.ui-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--ui-success);
    flex: none;
}
.ui-dot--live { animation: ui-pulse 2s var(--ui-ease) infinite; }

@keyframes ui-pulse {
    0%, 100% { opacity: 1;   transform: scale(1); }
    50%      { opacity: 0.45; transform: scale(1.35); }
}


/* ─── 9. LISTS & AVATARS ────────────────────────────────────────────── */

.ui-list { display: flex; flex-direction: column; gap: 6px; }

.ui-list-row {
    display: flex;
    align-items: center;
    gap: var(--ui-s-3);
    padding: 8px 10px;
    border-radius: var(--ui-r-md);
    background: var(--ui-surface-3);
    border: 1px solid var(--ui-border);
    transition: background var(--ui-fast) var(--ui-ease), border-color var(--ui-fast) var(--ui-ease);
}
.ui-list-row:hover { background: var(--ui-accent-soft); border-color: var(--ui-accent-line); }

.ui-list-row__body { flex: 1 1 auto; min-width: 0; }
.ui-list-row__name {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--ui-text);
    margin: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ui-list-row__meta { font-size: 0.6875rem; color: var(--ui-text-muted); margin: 1px 0 0; }

.ui-avatar {
    width: 34px;
    height: 34px;
    flex: none;
    border-radius: var(--ui-r-sm);
    overflow: hidden;
    display: grid;
    place-items: center;
    background: var(--ui-surface-2);
    border: 1px solid var(--ui-border);
    font-size: 0.9375rem;
}
.ui-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ui-avatar--sm { width: 26px; height: 26px; font-size: 0.8125rem; }
.ui-avatar--lg { width: 56px; height: 56px; border-radius: var(--ui-r-md); font-size: 1.5rem; }

/* Numbered explainer list — replaces "1." typed into a <strong> tag */
.ui-steps {
    list-style: none;
    counter-reset: ui-step;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: var(--ui-s-4);
}
.ui-steps > li {
    position: relative;
    padding-left: 32px;
    font-size: 0.8125rem;
    line-height: 1.6;
    color: var(--ui-text-secondary);
}
.ui-steps > li::before {
    counter-increment: ui-step;
    content: counter(ui-step);
    position: absolute;
    left: 0;
    top: 1px;
    width: 22px;
    height: 22px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--ui-accent-soft);
    border: 1px solid var(--ui-accent-line);
    color: var(--ui-accent-text);
    font-size: 0.6875rem;
    font-weight: 700;
}
.ui-steps > li > strong { display: block; margin-bottom: 1px; }

/* Section label inside a scrolling list */
.ui-list-label {
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ui-text-faint);
    margin: var(--ui-s-3) 0 var(--ui-s-2);
}
.ui-list-label:first-child { margin-top: 0; }


/* ─── 10. EMPTY STATES & SCROLL AREAS ───────────────────────────────── */

.ui-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    text-align: center;
    padding: var(--ui-s-8) var(--ui-s-4);
    color: var(--ui-text-muted);
    min-height: 120px;
}
.ui-empty__icon  { font-size: 1.75rem; line-height: 1; opacity: 0.65; }
.ui-empty__title { font-size: 0.875rem; font-weight: 600; color: var(--ui-text-secondary); margin: 0; }
.ui-empty__text  { font-size: 0.8125rem; color: var(--ui-text-muted); margin: 0; max-width: 34ch; line-height: 1.55; }

/* Flexible scroll region: fills its card instead of using a magic pixel height */
.ui-scroll {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: var(--ui-border-strong) transparent;
    padding-right: 4px;
}
.ui-scroll::-webkit-scrollbar { width: 6px; }
.ui-scroll::-webkit-scrollbar-track { background: transparent; }
.ui-scroll::-webkit-scrollbar-thumb { background: var(--ui-border-strong); border-radius: var(--ui-r-full); }
.ui-scroll::-webkit-scrollbar-thumb:hover { background: var(--ui-text-faint); }

.ui-scroll--sm { max-height: 200px; }
.ui-scroll--md { max-height: 300px; }

/* On phones, a scrollable list inside a scrollable page makes a swipe feel
   trapped: the list takes the gesture, then its containment prevents the
   page from continuing. Let ordinary lists grow with the page instead.
   Purpose-built scrolling surfaces such as chat and modals stay independent. */
@media (max-width: 639px) {
    .ui-scroll:not(.ui-chatwin__body):not(.ui-modal .ui-scroll) {
        overflow-y: visible;
        overscroll-behavior: auto;
        max-height: none;
        padding-right: 0;
    }
}


/* ─── 11. MODALS ────────────────────────────────────────────────────── */

.ui-modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: 300;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--ui-s-4);
    background: rgba(15, 23, 42, 0.45);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.ui-modal-backdrop.hidden { display: none; }

html[data-ui-theme="dark"] .ui-modal-backdrop { background: rgba(2, 6, 23, 0.76); }

.ui-modal {
    position: relative;
    width: 100%;
    max-width: 420px;
    max-height: calc(100vh - var(--ui-s-8));
    overflow-y: auto;
    padding: var(--ui-s-6);
    background: var(--ui-surface-2);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-r-2xl);
    box-shadow: var(--ui-shadow-lg);
    animation: ui-modal-in var(--ui-base) var(--ui-ease);
}
.ui-modal--sm { max-width: 340px; }
.ui-modal--lg { max-width: 640px; }
.ui-modal--xl { max-width: 760px; }

@keyframes ui-modal-in {
    from { opacity: 0; transform: translateY(12px) scale(0.98); }
    to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
    .ui-modal { animation: none; }
    .ui-card-select, .ui-btn, .ui-iconbtn { transition: none; }
    .ui-dot--live { animation: none; }
}

.ui-modal__close {
    position: absolute;
    top: var(--ui-s-4);
    right: var(--ui-s-4);
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    border-radius: var(--ui-r-full);
    border: 1px solid var(--ui-border);
    background: var(--ui-surface-3);
    color: var(--ui-text-muted);
    font-size: 0.8125rem;
    cursor: pointer;
    transition: color var(--ui-fast) var(--ui-ease), background var(--ui-fast) var(--ui-ease);
}
.ui-modal__close:hover { color: var(--ui-text); background: var(--ui-accent-soft); }

.ui-modal__actions {
    display: flex;
    flex-direction: column;
    gap: var(--ui-s-2);
    margin-top: var(--ui-s-6);
}

.ui-modal__icon {
    font-size: 2.5rem;
    line-height: 1;
}

/* Profile chooser grid — auto-fits so 2 kids don't look lost in a 4-col grid */
.ui-profile-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: var(--ui-s-3);
    max-height: 340px;
    overflow-y: auto;
}

.ui-profile-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--ui-s-2);
    padding: var(--ui-s-4);
    background: var(--ui-surface-3);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-r-lg);
    cursor: pointer;
    transition: border-color var(--ui-fast) var(--ui-ease),
                background var(--ui-fast) var(--ui-ease),
                transform var(--ui-fast) var(--ui-ease);
}
.ui-profile-card:hover {
    background: var(--ui-accent-soft);
    border-color: var(--ui-accent-line);
    transform: translateY(-2px);
}
.ui-profile-card:focus-visible { outline: 2px solid var(--ui-accent); outline-offset: 2px; }
.ui-profile-card__name { display: block; font-size: 0.875rem; font-weight: 600; color: var(--ui-text); margin: 0; }
.ui-profile-card__role {
    display: block;
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ui-accent-text);
    margin: 2px 0 0;
}

.ui-spinner {
    width: 34px;
    height: 34px;
    margin-inline: auto;
    border: 3px solid var(--ui-accent-soft);
    border-top-color: var(--ui-accent);
    border-radius: 50%;
    animation: ui-spin 700ms linear infinite;
}
@keyframes ui-spin { to { transform: rotate(360deg); } }


/* ─── 12. BANNERS ───────────────────────────────────────────────────── */

.ui-banner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ui-s-4);
    padding: var(--ui-s-4) var(--ui-s-5);
    border-radius: var(--ui-r-lg);
    background: var(--ui-accent-soft);
    border: 1px solid var(--ui-accent-line);
    color: var(--ui-text-secondary);
}
.ui-banner__body { flex: 1 1 240px; min-width: 0; }
.ui-banner__title { font-size: 0.875rem; font-weight: 700; color: var(--ui-text); margin: 0; }
.ui-banner__text  { font-size: 0.8125rem; margin: 2px 0 0; color: var(--ui-text-secondary); }
.ui-banner--success { background: var(--ui-success-soft); border-color: color-mix(in srgb, var(--ui-success) 32%, transparent); }
.ui-banner--warning { background: var(--ui-warning-soft); border-color: color-mix(in srgb, var(--ui-warning) 32%, transparent); }


/* ─── 13. FLOATING CHAT ─────────────────────────────────────────────── */

.ui-fab {
    position: fixed;
    right: var(--ui-s-6);
    bottom: var(--ui-s-6);
    z-index: 200;
    width: 52px;
    height: 52px;
    display: grid;
    place-items: center;
    border-radius: var(--ui-r-full);
    border: 1px solid var(--ui-border-strong);
    background: var(--ui-accent);
    color: #fff;
    font-size: 1.25rem;
    cursor: pointer;
    box-shadow: var(--ui-shadow-lg);
    transition: transform var(--ui-fast) var(--ui-ease), background var(--ui-fast) var(--ui-ease);
}
.ui-fab:hover { background: var(--ui-accent-hover); transform: translateY(-2px); }

.ui-fab__badge {
    position: absolute;
    top: -3px;
    right: -3px;
    min-width: 19px;
    height: 19px;
    padding: 0 5px;
    display: grid;
    place-items: center;
    border-radius: var(--ui-r-full);
    background: var(--ui-danger);
    color: #fff;
    font-size: 0.625rem;
    font-weight: 700;
}

.ui-chatwin {
    position: fixed;
    right: var(--ui-s-6);
    bottom: 88px;
    z-index: 200;
    width: min(340px, calc(100vw - var(--ui-s-8)));
    height: min(440px, calc(100vh - 160px));
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--ui-surface-2);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-r-xl);
    box-shadow: var(--ui-shadow-lg);
    transform-origin: bottom right;
    transition: opacity var(--ui-base) var(--ui-ease), transform var(--ui-base) var(--ui-ease);
}
.ui-chatwin.hidden { display: none; }
.ui-chatwin.is-closed { opacity: 0; transform: scale(0.94) translateY(8px); }

.ui-chatwin__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ui-s-3);
    padding: var(--ui-s-3) var(--ui-s-4);
    border-bottom: 1px solid var(--ui-border);
    background: var(--ui-surface-3);
}
.ui-chatwin__body {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding: var(--ui-s-4);
    display: flex;
    flex-direction: column;
    gap: var(--ui-s-3);
}
.ui-msg {
    display: flex;
    align-items: flex-start;
    gap: var(--ui-s-2);
}
.ui-msg__bubble {
    flex: 1 1 auto;
    min-width: 0;
    padding: 8px 11px;
    border-radius: var(--ui-r-md);
    background: var(--ui-surface-3);
    border: 1px solid var(--ui-border);
}
.ui-msg--me .ui-msg__bubble {
    background: var(--ui-accent-soft);
    border-color: var(--ui-accent-line);
}
.ui-msg__meta {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--ui-s-2);
    margin-bottom: 3px;
}
.ui-msg__sender { font-size: 0.75rem; font-weight: 600; color: var(--ui-text); }
.ui-msg__time   { font-size: 0.625rem; color: var(--ui-text-faint); flex: none; }
.ui-msg__text   { font-size: 0.8125rem; line-height: 1.5; color: var(--ui-text-secondary); margin: 0; overflow-wrap: anywhere; }

.ui-chatwin__foot {
    display: flex;
    align-items: center;
    gap: var(--ui-s-2);
    padding: var(--ui-s-3);
    border-top: 1px solid var(--ui-border);
    background: var(--ui-surface-3);
}


/* ─── 14. UTILITIES ─────────────────────────────────────────────────── */

/* ── Visibility ──
   Tailwind's `.hidden` lives in the `utilities` layer. Our component classes
   are unlayered, so anything that sets `display` (.ui-shell, .ui-chatwin,
   .ui-fab__badge …) would silently out-rank it and show while "hidden".
   The whole app toggles visibility with .hidden, so it wins outright. */
.hidden         { display: none !important; }
.ui-hidden      { display: none !important; }

.ui-center      { text-align: center; }
.ui-truncate    { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ui-mt-auto     { margin-top: auto; }
.ui-full        { width: 100%; }
.ui-grow        { flex: 1 1 0%; }

.ui-mt-1 { margin-top: var(--ui-s-1); }
.ui-mt-2 { margin-top: var(--ui-s-2); }
.ui-mt-3 { margin-top: var(--ui-s-3); }
.ui-mt-4 { margin-top: var(--ui-s-4); }
.ui-mb-4 { margin-bottom: var(--ui-s-4); }

/* Screen-reader-only text — for icon-only buttons */
.ui-sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}


/* ══════════════════════════════════════════════════════════════════════
   15. PORTAL SHELL
   ----------------------------------------------------------------------
   Everything below is shared by family / couple / junior. The only thing
   that differs between the three portals is one `ui-tone-*` class on
   <body>. Nothing here hard-codes a portal colour.
   ══════════════════════════════════════════════════════════════════════ */

/* ─── Navigation ────────────────────────────────────────────────────── */

.ui-nav {
    position: sticky;
    top: 0;
    z-index: 80;
    background: color-mix(in srgb, var(--ui-surface-0) 86%, transparent);
    backdrop-filter: blur(16px) saturate(1.4);
    -webkit-backdrop-filter: blur(16px) saturate(1.4);
    border-bottom: 1px solid var(--ui-border);
}

.ui-nav__inner {
    max-width: 1200px;
    margin-inline: auto;
    padding: 0 var(--ui-s-4);
    height: 64px;
    display: flex;
    align-items: center;
    gap: var(--ui-s-4);
}
@media (min-width: 640px)  { .ui-nav__inner { padding-inline: var(--ui-s-6); } }
@media (min-width: 1024px) { .ui-nav__inner { padding-inline: var(--ui-s-8); } }

.ui-nav__brand {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    text-decoration: none;
    color: inherit;
    border-radius: var(--ui-r-md);
    flex: none;
}

/* The logo is the wordmark. It previously sat in a coloured rounded tile with
   an emoji inside, which competed with the page for attention and read as
   decoration rather than identity. */
.ui-nav__logo { display: none; }

.ui-nav__word {
    font-size: 1.125rem;
    font-weight: 700;
    letter-spacing: -0.025em;
    color: var(--ui-text);
    white-space: nowrap;
}
.ui-nav__word b { font-weight: 700; color: var(--ui-tone-text); }

/* Desktop links */
.ui-nav__links {
    display: none;
    align-items: center;
    gap: 2px;
    margin-inline: auto;
}
@media (min-width: 900px) { .ui-nav__links { display: flex; } }

.ui-nav__link {
    position: relative;
    padding: 8px 14px;
    border-radius: var(--ui-r-md);
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--ui-text-muted);
    text-decoration: none;
    white-space: nowrap;
    transition: color var(--ui-fast) var(--ui-ease), background var(--ui-fast) var(--ui-ease);
}
.ui-nav__link:hover { color: var(--ui-text); background: var(--ui-surface-3); }

.ui-nav__link[aria-current="page"] {
    color: var(--ui-tone-text);
    background: var(--ui-tone-soft);
}

.ui-nav__actions {
    display: flex;
    align-items: center;
    gap: var(--ui-s-2);
    margin-left: auto;
}
@media (min-width: 900px) { .ui-nav__actions { margin-left: 0; } }

.ui-nav__burger { display: inline-grid; }
@media (min-width: 900px) { .ui-nav__burger { display: none; } }

/* Mobile drawer */
.ui-nav__drawer {
    display: grid;
    grid-template-rows: 0fr;
    overflow: hidden;
    border-top: 1px solid transparent;
    transition: grid-template-rows var(--ui-base) var(--ui-ease),
                border-color var(--ui-base) var(--ui-ease);
}
.ui-nav__drawer.is-open { grid-template-rows: 1fr; border-top-color: var(--ui-border); }
@media (min-width: 900px) { .ui-nav__drawer { display: none; } }

.ui-nav__drawer > div { min-height: 0; overflow: hidden; }

.ui-nav__drawer-inner {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--ui-s-3) var(--ui-s-4) var(--ui-s-5);
    max-width: 1200px;
    margin-inline: auto;
}

.ui-nav__drawer .ui-nav__link { padding: 12px 14px; font-size: 0.9375rem; }


/* ─── Hero ──────────────────────────────────────────────────────────── */
/* A deliberate ink panel — dark in both themes. No hotlinked photography;
   the texture is generated, so it can never 404 or slow the page down. */

.ui-hero {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    border-radius: var(--ui-r-2xl);
    background: var(--ui-ink);
    color: var(--ui-ink-text);
    padding: var(--ui-s-10) var(--ui-s-6);
}
@media (min-width: 768px) { .ui-hero { padding: var(--ui-s-16) var(--ui-s-12); } }

/* Tone wash + soft grid, both generated */
.ui-hero::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -2;
    background:
        radial-gradient(ellipse 80% 70% at 8% 0%,
            color-mix(in srgb, var(--ui-tone) 55%, transparent) 0%, transparent 62%),
        radial-gradient(ellipse 70% 80% at 100% 100%,
            color-mix(in srgb, var(--ui-accent) 42%, transparent) 0%, transparent 60%);
}
.ui-hero::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background-image:
        linear-gradient(var(--ui-ink-border) 1px, transparent 1px),
        linear-gradient(90deg, var(--ui-ink-border) 1px, transparent 1px);
    background-size: 56px 56px;
    mask-image: radial-gradient(ellipse 70% 90% at 70% 20%, #000 0%, transparent 75%);
    -webkit-mask-image: radial-gradient(ellipse 70% 90% at 70% 20%, #000 0%, transparent 75%);
    opacity: 0.6;
}

.ui-hero__inner { position: relative; max-width: 640px; }
.ui-hero--center .ui-hero__inner { max-width: 720px; margin-inline: auto; text-align: center; }

.ui-hero__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 5px 12px;
    border-radius: var(--ui-r-full);
    background: var(--ui-ink-2);
    border: 1px solid var(--ui-ink-border);
    color: var(--ui-ink-text);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.ui-hero__title {
    margin: var(--ui-s-5) 0 0;
    font-size: clamp(2.125rem, 1.3rem + 3.4vw, 3.75rem);
    line-height: 1.04;
    font-weight: 800;
    letter-spacing: -0.038em;
    color: var(--ui-ink-text);
    text-wrap: balance;
}
.ui-hero__title em {
    font-style: normal;
    color: transparent;
    background: linear-gradient(100deg, var(--ui-tone), color-mix(in srgb, var(--ui-tone) 35%, #fff));
    -webkit-background-clip: text;
    background-clip: text;
}

.ui-hero__text {
    margin: var(--ui-s-5) 0 0;
    font-size: 1.0625rem;
    line-height: 1.65;
    font-weight: 400;
    color: var(--ui-ink-muted);
    max-width: 52ch;
}
.ui-hero--center .ui-hero__text { margin-inline: auto; }

.ui-hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ui-s-3);
    margin-top: var(--ui-s-8);
}
.ui-hero--center .ui-hero__actions { justify-content: center; }

/* Buttons sitting on ink need their own contrast rules */
.ui-hero .ui-btn--primary {
    background: var(--ui-tone);
    color: #fff;
    box-shadow: 0 4px 16px color-mix(in srgb, var(--ui-tone) 40%, transparent);
}
.ui-hero .ui-btn--primary:hover:not(:disabled) {
    background: color-mix(in srgb, var(--ui-tone) 84%, #fff);
}
.ui-hero .ui-btn--secondary {
    background: var(--ui-ink-2);
    border-color: var(--ui-ink-border);
    color: var(--ui-ink-text);
}
.ui-hero .ui-btn--secondary:hover:not(:disabled) {
    background: color-mix(in srgb, #fff 14%, transparent);
    border-color: color-mix(in srgb, #fff 26%, transparent);
}

/* Stat strip under the hero copy */
.ui-hero__stats {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ui-s-8);
    margin-top: var(--ui-s-10);
    padding-top: var(--ui-s-6);
    border-top: 1px solid var(--ui-ink-border);
}
.ui-hero--center .ui-hero__stats { justify-content: center; }
.ui-hero__stat-value {
    display: block;
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--ui-ink-text);
    font-variant-numeric: tabular-nums;
}
.ui-hero__stat-label {
    display: block;
    margin-top: 2px;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--ui-ink-muted);
}


/* ─── Portal switcher ───────────────────────────────────────────────── */

.ui-switcher {
    display: grid;
    gap: var(--ui-s-3);
    grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 720px) { .ui-switcher { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.ui-switch-card {
    display: flex;
    align-items: center;
    gap: var(--ui-s-3);
    padding: var(--ui-s-4);
    border-radius: var(--ui-r-lg);
    background: var(--ui-surface-1);
    border: 1px solid var(--ui-border);
    text-decoration: none;
    transition: border-color var(--ui-fast) var(--ui-ease),
                transform var(--ui-fast) var(--ui-ease),
                box-shadow var(--ui-fast) var(--ui-ease);
}
.ui-switch-card:hover {
    border-color: var(--ui-tone-line);
    transform: translateY(-2px);
    box-shadow: var(--ui-shadow-md);
}
.ui-switch-card[aria-current="page"] {
    border-color: var(--ui-tone);
    background: var(--ui-tone-soft);
}

.ui-switch-card__icon {
    width: 40px;
    height: 40px;
    flex: none;
    display: grid;
    place-items: center;
    border-radius: 11px;
    background: var(--ui-tone-soft);
    border: 1px solid var(--ui-tone-line);
    font-size: 1.25rem;
}
.ui-switch-card__body { min-width: 0; }
.ui-switch-card__name {
    display: block;
    font-size: 0.9375rem;
    font-weight: 700;
    color: var(--ui-text);
    letter-spacing: -0.015em;
}
.ui-switch-card__desc {
    display: block;
    margin-top: 1px;
    font-size: 0.8125rem;
    color: var(--ui-text-muted);
}
.ui-switch-card__here {
    margin-left: auto;
    flex: none;
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ui-tone-text);
}


/* ─── Section headers ───────────────────────────────────────────────── */

.ui-section-head {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--ui-s-4);
    margin-bottom: var(--ui-s-5);
}
.ui-section-head__title {
    margin: 0;
    font-size: 1.25rem;
    font-weight: 700;
    letter-spacing: -0.022em;
    color: var(--ui-text);
}
.ui-section-head__sub {
    margin: 3px 0 0;
    font-size: 0.875rem;
    color: var(--ui-text-muted);
}
.ui-section-head__action { flex: none; }


/* ─── Content cards (challenges) ────────────────────────────────────── */

.ui-tile {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-radius: var(--ui-r-lg);
    background: var(--ui-surface-1);
    border: 1px solid var(--ui-border);
    box-shadow: var(--ui-shadow-sm);
    text-decoration: none;
    transition: border-color var(--ui-base) var(--ui-ease),
                transform var(--ui-base) var(--ui-ease),
                box-shadow var(--ui-base) var(--ui-ease);
}
.ui-tile:hover {
    border-color: var(--ui-tone-line);
    transform: translateY(-3px);
    box-shadow: var(--ui-shadow-lg);
}

.ui-tile__media {
    position: relative;
    display: block;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    background: var(--ui-surface-inset);
}
.ui-tile__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 600ms var(--ui-ease);
}
.ui-tile:hover .ui-tile__media img { transform: scale(1.04); }

/* Fallback when a challenge has no cover image */
.ui-tile__media--empty {
    display: grid;
    place-items: center;
    font-size: 2rem;
    background:
        radial-gradient(circle at 30% 25%, var(--ui-tone-soft) 0%, transparent 60%),
        var(--ui-surface-inset);
}

.ui-tile__tag {
    position: absolute;
    top: 10px;
    left: 10px;
    padding: 4px 10px;
    border-radius: var(--ui-r-full);
    background: color-mix(in srgb, var(--ui-surface-1) 88%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid var(--ui-border);
    color: var(--ui-tone-text);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
}

.ui-tile__body {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    padding: var(--ui-s-4);
    gap: var(--ui-s-2);
}
.ui-tile__title {
    margin: 0;
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.35;
    letter-spacing: -0.015em;
    color: var(--ui-text);
}
.ui-tile__text {
    margin: 0;
    font-size: 0.8125rem;
    line-height: 1.6;
    color: var(--ui-text-muted);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.ui-tile__foot {
    display: flex;
    gap: var(--ui-s-2);
    margin-top: auto;
    padding-top: var(--ui-s-3);
}
.ui-tile__foot > .ui-btn { flex: 1 1 auto; }


/* ─── Poll cards ────────────────────────────────────────────────────── */

.ui-poll {
    display: flex;
    flex-direction: column;
    gap: var(--ui-s-3);
    padding: var(--ui-s-5);
    border-radius: var(--ui-r-lg);
    background: var(--ui-surface-1);
    border: 1px solid var(--ui-border);
    box-shadow: var(--ui-shadow-sm);
}
.ui-poll__media {
    margin: calc(var(--ui-s-5) * -1) calc(var(--ui-s-5) * -1) 0;
    aspect-ratio: 16 / 7;
    overflow: hidden;
    background: var(--ui-surface-inset);
}
.ui-poll__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ui-poll__title {
    margin: 0;
    font-size: 1.0625rem;
    font-weight: 700;
    line-height: 1.35;
    letter-spacing: -0.015em;
    color: var(--ui-text);
}
.ui-poll__text {
    margin: 0;
    font-size: 0.8125rem;
    line-height: 1.6;
    color: var(--ui-text-muted);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.ui-poll__choices { display: flex; flex-direction: column; gap: var(--ui-s-2); }

.ui-choice {
    position: relative;
    overflow: hidden;
    width: 100%;
    padding: 11px 14px;
    text-align: left;
    border-radius: var(--ui-r-md);
    background: var(--ui-surface-3);
    border: 1px solid var(--ui-border);
    cursor: pointer;
    font: inherit;
    transition: border-color var(--ui-fast) var(--ui-ease), background var(--ui-fast) var(--ui-ease);
}
.ui-choice:hover:not(:disabled) { border-color: var(--ui-tone-line); }
.ui-choice:disabled { cursor: default; }
.ui-choice.is-picked { border-color: var(--ui-tone); background: var(--ui-tone-soft); }

/* The result bar. Width animates from 0 via the data-width attribute. */
.ui-choice__bar {
    position: absolute;
    inset: 0 auto 0 0;
    width: 0;
    background: var(--ui-tone-soft);
    transition: width 700ms var(--ui-ease);
}
.ui-choice__row {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ui-s-3);
}
.ui-choice__label { font-size: 0.875rem; font-weight: 600; color: var(--ui-text); }
.ui-choice__pct {
    font-size: 0.8125rem;
    font-weight: 700;
    color: var(--ui-tone-text);
    font-variant-numeric: tabular-nums;
    flex: none;
}


/* ─── Ink panel (spotlight / promo) ─────────────────────────────────── */

.ui-ink-panel {
    position: relative;
    isolation: isolate;
    overflow: hidden;
    padding: var(--ui-s-6);
    border-radius: var(--ui-r-xl);
    background: var(--ui-ink);
    border: 1px solid var(--ui-ink-border);
    color: var(--ui-ink-muted);
}
.ui-ink-panel::before {
    content: "";
    position: absolute;
    inset: -40% -30% auto auto;
    width: 260px;
    height: 260px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--ui-tone) 40%, transparent);
    filter: blur(60px);
    z-index: -1;
}
.ui-ink-panel h2, .ui-ink-panel h3, .ui-ink-panel .ui-card__title { color: var(--ui-ink-text); }
.ui-ink-panel .ui-eyebrow { color: var(--ui-tone-text); }
.ui-ink-panel .ui-card__head { border-bottom-color: var(--ui-ink-border); }


/* ─── Footer ────────────────────────────────────────────────────────── */

.ui-footer {
    margin-top: var(--ui-s-16);
    border-top: 1px solid var(--ui-border);
    background: var(--ui-surface-1);
}
.ui-footer__inner {
    max-width: 1200px;
    margin-inline: auto;
    padding: var(--ui-s-8) var(--ui-s-4);
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ui-s-4);
}
@media (min-width: 640px)  { .ui-footer__inner { padding-inline: var(--ui-s-6); } }
@media (min-width: 1024px) { .ui-footer__inner { padding-inline: var(--ui-s-8); } }

.ui-footer__links { display: flex; flex-wrap: wrap; gap: var(--ui-s-4); margin-left: auto; }
.ui-footer__link {
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--ui-text-muted);
    text-decoration: none;
    transition: color var(--ui-fast) var(--ui-ease);
}
.ui-footer__link:hover { color: var(--ui-text); }
.ui-footer__note { font-size: 0.8125rem; color: var(--ui-text-faint); width: 100%; }


/* ─── Junior tuning ─────────────────────────────────────────────────── */
/* Junior earns its personality from radius, scale and touch targets —
   not from a different layout or a pile of one-off styles. */

body[data-portal="junior"] {
    --ui-r-md: 14px;
    --ui-r-lg: 20px;
    --ui-r-xl: 26px;
    --ui-r-2xl: 32px;
}
body[data-portal="junior"] .ui-btn { padding: 12px 22px; font-weight: 700; }
body[data-portal="junior"] .ui-btn--sm { padding: 9px 15px; }
body[data-portal="junior"] .ui-tile__title,
body[data-portal="junior"] .ui-section-head__title { font-weight: 800; }
body[data-portal="junior"] .ui-nav__link { font-weight: 700; }


/* ─── Profile widget (v2 skin) ──────────────────────────────────────── */
/* portal-components.js renders the widget with these class hooks on v2
   pages so its colours come from tokens and follow the theme toggle,
   instead of being baked in as Tailwind classes at render time. */

body[data-ui="v2"] .ui-chip-shell {
    background: var(--ui-surface-1);
    border-color: var(--ui-border) !important;
    color: var(--ui-text);
    border-radius: var(--ui-r-full);
}
body[data-ui="v2"] .ui-chip-shell a { color: inherit; text-decoration: none; }

body[data-ui="v2"] .ui-chip-muted { color: var(--ui-text-muted); }

body[data-ui="v2"] .ui-chip-btn {
    color: var(--ui-text-muted);
    border-radius: var(--ui-r-full);
    transition: background var(--ui-fast) var(--ui-ease), color var(--ui-fast) var(--ui-ease);
}
body[data-ui="v2"] .ui-chip-btn:hover {
    background: var(--ui-surface-3);
    color: var(--ui-text);
}

/* Tame the widget's inherited micro-typography */
body[data-ui="v2"] .ui-chip-shell p { font-size: 0.75rem; font-weight: 600; letter-spacing: 0; }
body[data-ui="v2"] .ui-chip-shell .ui-chip-muted { font-size: 0.625rem; font-weight: 600; }


/* ══════════════════════════════════════════════════════════════════════
   16. SUBPAGE SHELL
   ----------------------------------------------------------------------
   Pieces the portal pages didn't need: filter tabs, rank rows, generated
   game artwork, notification rows and a data table.
   ══════════════════════════════════════════════════════════════════════ */

/* ─── Page header ───────────────────────────────────────────────────── */

.ui-page-head { margin-bottom: var(--ui-s-8); }
.ui-page-head__title {
    margin: var(--ui-s-2) 0 0;
    font-size: clamp(1.75rem, 1.3rem + 1.8vw, 2.5rem);
    line-height: 1.1;
    font-weight: 800;
    letter-spacing: -0.032em;
    color: var(--ui-text);
}
.ui-page-head__sub {
    margin: var(--ui-s-3) 0 0;
    font-size: 1rem;
    line-height: 1.6;
    color: var(--ui-text-secondary);
    max-width: 58ch;
}


/* ─── Filter tabs ───────────────────────────────────────────────────── */
/* Horizontally scrollable on mobile without a visible scrollbar, but still
   keyboard reachable — the old version hid overflow entirely. */

.ui-tabs {
    display: flex;
    gap: var(--ui-s-2);
    overflow-x: auto;
    padding-bottom: var(--ui-s-3);
    margin-bottom: var(--ui-s-5);
    border-bottom: 1px solid var(--ui-border);
    scrollbar-width: none;
}
.ui-tabs::-webkit-scrollbar { display: none; }

.ui-tab {
    flex: none;
    padding: 8px 16px;
    border-radius: var(--ui-r-full);
    border: 1px solid var(--ui-border);
    background: var(--ui-surface-3);
    color: var(--ui-text-muted);
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    transition: background var(--ui-fast) var(--ui-ease),
                color var(--ui-fast) var(--ui-ease),
                border-color var(--ui-fast) var(--ui-ease);
}
.ui-tab:hover { color: var(--ui-text); border-color: var(--ui-border-strong); }
.ui-tab[aria-selected="true"] {
    background: var(--ui-tone-soft);
    border-color: var(--ui-tone-line);
    color: var(--ui-tone-text);
}


/* ─── Rank rows (leaderboards) ──────────────────────────────────────── */

.ui-rank {
    display: flex;
    align-items: center;
    gap: var(--ui-s-3);
    padding: 9px 11px;
    border-radius: var(--ui-r-md);
    border: 1px solid transparent;
    text-decoration: none;
    transition: background var(--ui-fast) var(--ui-ease);
}
.ui-rank:hover { background: var(--ui-surface-3); }

.ui-rank__pos {
    width: 24px;
    height: 24px;
    flex: none;
    display: grid;
    place-items: center;
    border-radius: var(--ui-r-full);
    background: var(--ui-surface-3);
    border: 1px solid var(--ui-border);
    color: var(--ui-text-muted);
    font-size: 0.6875rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.ui-rank__body { flex: 1 1 auto; min-width: 0; }
.ui-rank__name {
    display: block;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--ui-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ui-rank__meta {
    display: block;
    margin-top: 1px;
    font-size: 0.6875rem;
    color: var(--ui-text-muted);
    font-variant-numeric: tabular-nums;
}

/* Podium: gold / silver / bronze, readable in both themes */
.ui-rank--1 { background: var(--ui-warning-soft); border-color: color-mix(in srgb, var(--ui-warning) 30%, transparent); }
.ui-rank--1 .ui-rank__pos { background: var(--ui-warning); border-color: var(--ui-warning); color: #422006; }
.ui-rank--2 .ui-rank__pos { background: var(--ui-text-faint); border-color: var(--ui-text-faint); color: var(--ui-surface-1); }
.ui-rank--3 .ui-rank__pos { background: #b45309; border-color: #b45309; color: #fff; }

/* "you" highlight */
.ui-rank--self { background: var(--ui-tone-soft); border-color: var(--ui-tone-line); }
.ui-rank--self .ui-rank__name { color: var(--ui-tone-text); }


/* ─── Generated game artwork ────────────────────────────────────────── */
/* The old page hand-wrote 28 divs per Connect-4 thumbnail. These build the
   same idea from a few elements and inherit the card's tone. */

.ui-art {
    position: relative;
    display: grid;
    place-items: center;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: var(--ui-r-md);
    background:
        radial-gradient(circle at 30% 20%, var(--ui-tone-soft) 0%, transparent 65%),
        var(--ui-surface-inset);
    border: 1px solid var(--ui-border);
}

.ui-art__grid {
    display: grid;
    gap: 5px;
    padding: 10px;
    border-radius: 10px;
    background: color-mix(in srgb, var(--ui-tone) 22%, var(--ui-surface-inset));
}
.ui-art__cell {
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--ui-surface-inset) 82%, #000);
}
.ui-art__cell--a { background: #ef4444; }
.ui-art__cell--b { background: #facc15; }

.ui-art__tiles { display: flex; gap: 7px; }
.ui-art__tile {
    width: 34px;
    height: 42px;
    display: grid;
    place-items: center;
    border-radius: 9px;
    background: var(--ui-surface-2);
    border: 1.5px solid var(--ui-tone-line);
    color: var(--ui-tone-text);
    font-size: 1.125rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.ui-art__tile--lit {
    border-color: var(--ui-tone);
    box-shadow: 0 0 0 3px var(--ui-tone-soft);
}

.ui-art__word {
    font-family: ui-monospace, 'Space Mono', monospace;
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.5;
    letter-spacing: 0.35em;
    text-align: center;
    color: var(--ui-text-faint);
}
.ui-art__word mark {
    background: var(--ui-tone-soft);
    color: var(--ui-tone-text);
    border-radius: 4px;
    padding: 0 3px;
}

.ui-art__badge {
    position: absolute;
    top: 9px;
    right: 9px;
    padding: 3px 9px;
    border-radius: var(--ui-r-full);
    background: color-mix(in srgb, var(--ui-surface-1) 88%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid var(--ui-border);
    color: var(--ui-tone-text);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}


/* ─── Notification rows ─────────────────────────────────────────────── */

.ui-note {
    display: flex;
    align-items: flex-start;
    gap: var(--ui-s-3);
    padding: var(--ui-s-4);
    border-radius: var(--ui-r-lg);
    background: var(--ui-surface-1);
    border: 1px solid var(--ui-border);
    text-decoration: none;
    transition: border-color var(--ui-fast) var(--ui-ease), background var(--ui-fast) var(--ui-ease);
}
.ui-note:hover { border-color: var(--ui-tone-line); }

/* Unread carries a tone bar rather than a whole coloured background —
   a full tint makes a long list unreadable. */
.ui-note--unread { border-left: 3px solid var(--ui-tone); }

.ui-note__icon {
    width: 34px;
    height: 34px;
    flex: none;
    display: grid;
    place-items: center;
    border-radius: var(--ui-r-md);
    background: var(--ui-tone-soft);
    border: 1px solid var(--ui-tone-line);
    font-size: 0.9375rem;
}
.ui-note__body { flex: 1 1 auto; min-width: 0; }
.ui-note__title { margin: 0; font-size: 0.875rem; font-weight: 600; color: var(--ui-text); }
.ui-note__text  { margin: 3px 0 0; font-size: 0.8125rem; line-height: 1.55; color: var(--ui-text-muted); }
.ui-note__time  { flex: none; font-size: 0.6875rem; color: var(--ui-text-faint); white-space: nowrap; }


/* ─── Data table ────────────────────────────────────────────────────── */

.ui-table-wrap {
    overflow-x: auto;
    border-radius: var(--ui-r-lg);
    border: 1px solid var(--ui-border);
    background: var(--ui-surface-1);
}
.ui-table { width: 100%; border-collapse: collapse; font-size: 0.875rem; }
.ui-table th {
    position: sticky;
    top: 0;
    text-align: left;
    padding: 11px 14px;
    background: var(--ui-surface-2);
    border-bottom: 1px solid var(--ui-border);
    color: var(--ui-text-muted);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
}
.ui-table td {
    padding: 11px 14px;
    border-bottom: 1px solid var(--ui-border);
    color: var(--ui-text-secondary);
}
.ui-table tr:last-child td { border-bottom: 0; }
.ui-table tbody tr:hover td { background: var(--ui-surface-3); }
.ui-table__num { text-align: right; font-variant-numeric: tabular-nums; }


/* ─── Checkbox / radio row ──────────────────────────────────────────── */

.ui-check {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--ui-s-2);
    padding: 10px 14px;
    border-radius: var(--ui-r-md);
    background: var(--ui-surface-3);
    border: 1px solid var(--ui-border);
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--ui-text-secondary);
    cursor: pointer;
    transition: border-color var(--ui-fast) var(--ui-ease), background var(--ui-fast) var(--ui-ease);
}
.ui-check:hover { border-color: var(--ui-tone-line); }
.ui-check:has(input:checked) {
    background: var(--ui-tone-soft);
    border-color: var(--ui-tone-line);
    color: var(--ui-text);
}
.ui-check:has(input:disabled) { opacity: 0.5; cursor: not-allowed; }

.ui-check input[type="checkbox"],
.ui-check input[type="radio"] {
    width: 16px;
    height: 16px;
    flex: none;
    accent-color: var(--ui-tone);
    cursor: inherit;
}

/* The duel picker's spinner sits inside the modal icon slot */
.ui-modal__icon .ui-spinner { margin: 0 auto; }


/* ─── Stat tiles ────────────────────────────────────────────────────── */

.ui-stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--ui-s-2); }
.ui-stat {
    padding: var(--ui-s-3) var(--ui-s-4);
    border-radius: var(--ui-r-md);
    background: var(--ui-surface-3);
    border: 1px solid var(--ui-border);
}
.ui-stat__label {
    display: block;
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ui-text-muted);
}
.ui-stat__value {
    display: block;
    margin-top: 3px;
    font-size: 1.375rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--ui-tone-text);
    font-variant-numeric: tabular-nums;
}


/* ─── Toast ─────────────────────────────────────────────────────────── */

.ui-toast {
    position: fixed;
    right: var(--ui-s-6);
    bottom: var(--ui-s-6);
    z-index: 400;
    max-width: min(340px, calc(100vw - var(--ui-s-8)));
    padding: 12px 16px;
    border-radius: var(--ui-r-md);
    background: var(--ui-ink);
    border: 1px solid var(--ui-ink-border);
    color: var(--ui-ink-text);
    font-size: 0.8125rem;
    font-weight: 600;
    box-shadow: var(--ui-shadow-lg);
    animation: ui-toast-in var(--ui-base) var(--ui-ease);
}
.ui-toast.hidden { display: none; }
@keyframes ui-toast-in {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: none; }
}


/* ─── Follow-up note (revealed after voting) ────────────────────────── */

.ui-followup {
    margin-top: var(--ui-s-4);
    padding: var(--ui-s-4);
    border-radius: var(--ui-r-md);
    background: var(--ui-tone-soft);
    border: 1px solid var(--ui-tone-line);
    font-size: 0.8125rem;
    line-height: 1.6;
    color: var(--ui-text-secondary);
}
.ui-followup.hidden { display: none; }
.ui-followup > :first-child { margin-top: 0; }
.ui-followup > :last-child { margin-bottom: 0; }


/* ─── Bullet guide list ─────────────────────────────────────────────── */

.ui-guide { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--ui-s-3); }
.ui-guide > li {
    position: relative;
    padding-left: 18px;
    font-size: 0.8125rem;
    line-height: 1.6;
    color: var(--ui-text-secondary);
}
.ui-guide > li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 8px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--ui-tone);
}


/* ══════════════════════════════════════════════════════════════════════
   17. CHALLENGES
   ══════════════════════════════════════════════════════════════════════ */

/* Views are swapped by showView(); .hidden must win over any display rule. */
.view { display: block; }

.ui-select--auto { width: auto; min-width: 150px; }

.ui-row--end { justify-content: flex-end; }

.ui-toolbar {
    margin-top: var(--ui-s-8);
    padding-top: var(--ui-s-6);
    border-top: 1px solid var(--ui-border);
}

/* ─── Preview ───────────────────────────────────────────────────────── */

.ui-preview-hero {
    display: grid;
    place-items: center;
    aspect-ratio: 21 / 6;
    min-height: 160px;
    overflow: hidden;
    font-size: 3.5rem;
    background:
        radial-gradient(ellipse at 30% 20%, var(--ui-tone-soft) 0%, transparent 60%),
        var(--ui-surface-inset);
    border-bottom: 1px solid var(--ui-border);
}
.ui-preview-hero img { width: 100%; height: 100%; object-fit: cover; display: block; }

.ui-preview-body { padding: var(--ui-s-6); }
@media (min-width: 640px) { .ui-preview-body { padding: var(--ui-s-8); } }

/* Rich text coming out of Quill — style the tags, not per-element classes */
.ui-prose { font-size: 0.9375rem; line-height: 1.7; color: var(--ui-text-secondary); }
.ui-prose > :first-child { margin-top: 0; }
.ui-prose > :last-child { margin-bottom: 0; }
.ui-prose p { margin: 0 0 0.75em; }
.ui-prose ul, .ui-prose ol { margin: 0 0 0.75em; padding-left: 1.25em; }
.ui-prose li { margin-bottom: 0.3em; }
.ui-prose strong, .ui-prose b { color: var(--ui-text); font-weight: 600; }
.ui-prose a { color: var(--ui-tone-text); text-decoration: underline; text-underline-offset: 2px; }

/* ─── Task checklist ────────────────────────────────────────────────── */

.ui-tasks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--ui-s-2); }
.ui-tasks > li {
    display: flex;
    align-items: flex-start;
    gap: var(--ui-s-2);
    font-size: 0.875rem;
    line-height: 1.55;
    color: var(--ui-text-secondary);
}
.ui-tasks > li::before {
    content: "";
    flex: none;
    width: 15px;
    height: 15px;
    margin-top: 3px;
    border-radius: 4px;
    border: 1.5px solid var(--ui-tone-line);
    background: var(--ui-tone-soft);
}

/* ─── Progress meter ────────────────────────────────────────────────── */

.ui-meter {
    height: 8px;
    border-radius: var(--ui-r-full);
    background: var(--ui-surface-3);
    border: 1px solid var(--ui-border);
    overflow: hidden;
}
.ui-meter__fill {
    height: 100%;
    background: var(--ui-tone);
    border-radius: inherit;
    transition: width 600ms var(--ui-ease);
}

/* Compact meter used inside challenge cards */
.ui-meter--sm { height: 5px; }

.ui-streak {
    font-size: 2.5rem;
    font-weight: 800;
    letter-spacing: -0.03em;
    color: var(--ui-text);
    margin: var(--ui-s-3) 0;
}

/* ─── Upload dropzone ───────────────────────────────────────────────── */

.ui-dropzone {
    display: block;
    padding: var(--ui-s-8) var(--ui-s-5);
    text-align: center;
    border-radius: var(--ui-r-lg);
    border: 2px dashed var(--ui-border-strong);
    background: var(--ui-surface-3);
    cursor: pointer;
    transition: border-color var(--ui-fast) var(--ui-ease), background var(--ui-fast) var(--ui-ease);
}
.ui-dropzone:hover {
    border-color: var(--ui-tone);
    background: var(--ui-tone-soft);
}
.ui-dropzone__icon { font-size: 1.75rem; line-height: 1; margin-bottom: var(--ui-s-2); }
.ui-dropzone__img { max-height: 220px; margin-inline: auto; border-radius: var(--ui-r-md); object-fit: contain; }

/* ─── Wizard stepper ────────────────────────────────────────────────── */

.ui-step {
    display: flex;
    align-items: center;
    gap: var(--ui-s-3);
    width: 100%;
    padding: 10px 12px;
    text-align: left;
    border-radius: var(--ui-r-md);
    border: 1px solid transparent;
    background: none;
    font: inherit;
    color: var(--ui-text-muted);
    cursor: pointer;
    transition: background var(--ui-fast) var(--ui-ease), color var(--ui-fast) var(--ui-ease);
}
.ui-step:hover { background: var(--ui-surface-3); color: var(--ui-text); }
.ui-step[aria-current="step"] {
    background: var(--ui-tone-soft);
    border-color: var(--ui-tone-line);
    color: var(--ui-tone-text);
}
.ui-step__num {
    width: 24px;
    height: 24px;
    flex: none;
    display: grid;
    place-items: center;
    border-radius: 50%;
    border: 1px solid var(--ui-border);
    background: var(--ui-surface-3);
    font-size: 0.6875rem;
    font-weight: 700;
}
.ui-step[aria-current="step"] .ui-step__num,
.ui-step.is-done .ui-step__num {
    background: var(--ui-tone);
    border-color: var(--ui-tone);
    color: #fff;
}
.ui-step__label { font-size: 0.875rem; font-weight: 600; }

/* ─── Badge chips ───────────────────────────────────────────────────── */

.ui-badge-summary {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
}

.ui-badge-tile {
    display: flex;
    align-items: center;
    gap: var(--ui-s-3);
    padding: var(--ui-s-3);
    border-radius: var(--ui-r-md);
    background: var(--ui-surface-3);
    border: 1px solid var(--ui-border);
}
.ui-badge-tile__art {
    width: 38px;
    height: 38px;
    flex: none;
    display: grid;
    place-items: center;
    border-radius: var(--ui-r-md);
    background: var(--ui-tone-soft);
    border: 1px solid var(--ui-tone-line);
    font-size: 1.125rem;
    overflow: hidden;
}
.ui-badge-tile__art img { width: 100%; height: 100%; object-fit: cover; }
.ui-badge-tile__body { min-width: 0; flex: 1 1 auto; }
.ui-badge-tile__name {
    display: block;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--ui-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ui-badge-tile__meta { display: block; margin-top: 1px; font-size: 0.6875rem; color: var(--ui-text-muted); }
.ui-badge-tile__earned {
    flex: none;
    width: 22px;
    height: 22px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: var(--ui-success);
    color: #fff;
    font-size: 0.75rem;
    font-weight: 700;
}

/* ─── Toast visibility ──────────────────────────────────────────────── */
/* The old page animated three Tailwind classes on and off. One state class
   is easier to reason about and can't get half-applied. */
.ui-toast {
    display: flex;
    align-items: center;
    gap: var(--ui-s-2);
    opacity: 0;
    transform: translateY(10px);
    pointer-events: none;
    transition: opacity var(--ui-base) var(--ui-ease), transform var(--ui-base) var(--ui-ease);
}
.ui-toast.is-visible { opacity: 1; transform: none; pointer-events: auto; }

/* Helpers used by converted legacy renderers */
.ui-tone-text-c { color: var(--ui-tone-text); }
.ui-tone-soft-c { background: var(--ui-tone-soft); border-color: var(--ui-tone-line); }
.ui-radius-lg   { border-radius: var(--ui-r-lg); }
.ui-required    { color: var(--ui-danger-text); }
.ui-badge__art  { width: 14px; height: 14px; border-radius: 50%; object-fit: cover; }
.ui-editor      { border: 1px solid var(--ui-border); border-radius: var(--ui-r-md); background: var(--ui-surface-inset); }
.ui-editor .ql-toolbar { border: 0; border-bottom: 1px solid var(--ui-border); }
.ui-editor .ql-container { border: 0; font-family: inherit; font-size: 0.875rem; color: var(--ui-text); }
.ui-editor .ql-editor.ql-blank::before { color: var(--ui-text-faint); font-style: normal; }
/* Transient highlight when a panel is scrolled into view */
.is-flash { outline: 2px solid var(--ui-tone); outline-offset: 3px; transition: outline-color var(--ui-base) var(--ui-ease); }
.ui-mt-6 { margin-top: var(--ui-s-6); }
.ui-mb-3 { margin-bottom: var(--ui-s-3); }
.ui-mb-6 { margin-bottom: var(--ui-s-6); }
/* Comment thread indent + misc used by the single-challenge modules */
.ui-thread { margin-top: var(--ui-s-3); padding-left: var(--ui-s-4); border-left: 2px solid var(--ui-border); display: flex; flex-direction: column; gap: var(--ui-s-3); }
.ui-prewrap { white-space: pre-wrap; }
.ui-danger-link { color: var(--ui-danger-text); }
.ui-mb-2 { margin-bottom: var(--ui-s-2); }


/* ─── Online players list ───────────────────────────────────────────── */
/* Used by the arena, the games lobby and profile. Previously two hardcoded
   Tailwind palettes chosen by an `isMidnight` flag, which every caller set
   to true — so the list stayed dark on light pages. */

.ui-player {
    display: flex;
    align-items: center;
    gap: var(--ui-s-3);
    padding: 8px 10px;
    margin-bottom: 6px;
    border-radius: var(--ui-r-md);
    background: var(--ui-surface-1);
    border: 1px solid var(--ui-border);
    transition: border-color var(--ui-fast) var(--ui-ease), background var(--ui-fast) var(--ui-ease);
}
.ui-player:hover { border-color: var(--ui-border-strong); }

.ui-player--match {
    background: var(--ui-accent-soft);
    border-color: var(--ui-accent-line);
}

/* Your own row — tinted with the page tone so it reads as "this is me"
   without shouting louder than the people you can actually challenge. */
.ui-player--self {
    background: var(--ui-tone-soft);
    border-color: var(--ui-tone-line);
    margin-top: var(--ui-s-2);
    margin-bottom: 0;
}

.ui-player__body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.ui-player__name {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--ui-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.ui-player__you { font-weight: 500; color: var(--ui-tone-text); }

.ui-player__status {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--ui-text-muted);
}
.ui-player__status--free .ui-dot { background: var(--ui-success); }
.ui-player__status--busy .ui-dot { background: var(--ui-danger); }
.ui-player__status--busy { color: var(--ui-danger-text); }

/* Checkbox row without the card chrome — for inline filters */
.ui-check--bare {
    padding: 0;
    background: none;
    border: 0;
    font-size: 0.75rem;
    font-weight: 500;
    color: var(--ui-text-muted);
}
.ui-check--bare:hover { background: none; color: var(--ui-text); }
.ui-check--bare:has(input:checked) { background: none; color: var(--ui-tone-text); }

/* Wizard field extras */
.ui-check--start { align-items: flex-start; justify-content: flex-start; text-align: left; }
.ui-dropzone--slim { padding: var(--ui-s-6) var(--ui-s-4); }
.ui-media-preview {
    display: block;
    width: 100%;
    max-height: 200px;
    object-fit: cover;
    border-radius: var(--ui-r-md);
    border: 1px solid var(--ui-border);
}


/* ══════════════════════════════════════════════════════════════════════
   18. GAME SCREENS
   ----------------------------------------------------------------------
   Setup, lobby and result surfaces shared by Connect 4, Word Search,
   Tic-Tac-Toe and Guess My Number.

   The boards themselves keep each game's own palette — those games ship a
   `theme-midnight` variant already, which the product theme now drives.
   ══════════════════════════════════════════════════════════════════════ */

/* ─── Full-screen setup / result overlay ────────────────────────────── */

.ui-screen {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--ui-s-4);
    overflow-y: auto;
    background: color-mix(in srgb, var(--ui-surface-0) 82%, transparent);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
}
.ui-screen.hidden { display: none; }

.ui-screen__panel {
    width: 100%;
    max-width: 880px;
    max-height: calc(100vh - var(--ui-s-8));
    overflow-y: auto;
    padding: var(--ui-s-6);
    border-radius: var(--ui-r-2xl);
    background: var(--ui-surface-1);
    border: 1px solid var(--ui-border);
    box-shadow: var(--ui-shadow-lg);
}
@media (min-width: 640px) { .ui-screen__panel { padding: var(--ui-s-8); } }

.ui-screen__panel--sm { max-width: 560px; }

/* Account strip at the top of a setup screen */
.ui-screen__account {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--ui-s-3);
    padding-bottom: var(--ui-s-4);
    margin-bottom: var(--ui-s-6);
    border-bottom: 1px solid var(--ui-border);
}

.ui-screen__title {
    margin: 0;
    font-size: clamp(1.5rem, 1.2rem + 1.2vw, 2rem);
    line-height: 1.15;
    font-weight: 800;
    letter-spacing: -0.03em;
    color: var(--ui-text);
}
.ui-screen__sub {
    margin: var(--ui-s-2) 0 0;
    font-size: 0.9375rem;
    line-height: 1.6;
    color: var(--ui-text-secondary);
}

/* Keep targets visible below the sticky navigation after scrollIntoView/hash navigation. */
main [id] { scroll-margin-top: 96px; }

/* ─── Mode picker ───────────────────────────────────────────────────── */
/* Big, obvious choices: play the AI, play locally, play online. */

.ui-modes {
    display: grid;
    gap: var(--ui-s-3);
    grid-template-columns: minmax(0, 1fr);
    margin-top: var(--ui-s-6);
}
@media (min-width: 640px) { .ui-modes { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

.ui-mode {
    display: flex;
    flex-direction: column;
    gap: 6px;
    padding: var(--ui-s-4);
    text-align: left;
    border-radius: var(--ui-r-lg);
    background: var(--ui-surface-2);
    border: 1px solid var(--ui-border);
    cursor: pointer;
    font: inherit;
    transition: border-color var(--ui-fast) var(--ui-ease),
                background var(--ui-fast) var(--ui-ease),
                transform var(--ui-fast) var(--ui-ease);
}
.ui-mode:hover { border-color: var(--ui-tone-line); transform: translateY(-2px); }
.ui-mode[aria-pressed="true"],
.ui-mode.is-active {
    border-color: var(--ui-tone);
    background: var(--ui-tone-soft);
}
.ui-mode__icon { font-size: 1.5rem; line-height: 1; }
.ui-mode__name { font-size: 0.9375rem; font-weight: 700; color: var(--ui-text); }
.ui-mode__desc { font-size: 0.8125rem; line-height: 1.5; color: var(--ui-text-muted); }

/* ─── Room code ─────────────────────────────────────────────────────── */

.ui-roomcode {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--ui-s-3);
    padding: var(--ui-s-4);
    border-radius: var(--ui-r-md);
    background: var(--ui-tone-soft);
    border: 1px dashed var(--ui-tone-line);
}
.ui-roomcode__value {
    font-family: ui-monospace, 'Space Mono', monospace;
    font-size: 1.5rem;
    font-weight: 700;
    letter-spacing: 0.22em;
    color: var(--ui-tone-text);
}

/* ─── In-game status bar ────────────────────────────────────────────── */

.ui-status {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--ui-s-2);
    padding: 12px var(--ui-s-4);
    border-radius: var(--ui-r-lg);
    background: var(--ui-surface-1);
    border: 1px solid var(--ui-border);
    font-size: 0.9375rem;
    font-weight: 700;
    color: var(--ui-text);
    text-align: center;
}

/* Score cards flanking the board */
.ui-score {
    display: flex;
    align-items: center;
    gap: var(--ui-s-3);
    padding: var(--ui-s-3);
    border-radius: var(--ui-r-md);
    background: var(--ui-surface-1);
    border: 1px solid var(--ui-border);
    transition: border-color var(--ui-fast) var(--ui-ease), background var(--ui-fast) var(--ui-ease);
}
.ui-score.is-turn { border-color: var(--ui-tone); background: var(--ui-tone-soft); }
.ui-score__name { font-size: 0.8125rem; font-weight: 600; color: var(--ui-text); }
.ui-score__value {
    margin-left: auto;
    font-size: 1.375rem;
    font-weight: 800;
    color: var(--ui-text);
    font-variant-numeric: tabular-nums;
}

/* ─── Result modal ──────────────────────────────────────────────────── */

.ui-result { text-align: center; }
.ui-result__icon { font-size: 3.5rem; line-height: 1; }
.ui-result__title {
    margin: var(--ui-s-3) 0 0;
    font-size: 1.75rem;
    font-weight: 800;
    letter-spacing: -0.025em;
    color: var(--ui-text);
}
.ui-result__body { margin: var(--ui-s-2) 0 0; font-size: 0.9375rem; line-height: 1.6; color: var(--ui-text-secondary); }

/* Modal open/close animation driven by a state class, so JS toggles one
   thing and the motion stays in CSS with the component. */
.ui-modal--enter, .ui-modal.is-closed { transition: opacity var(--ui-base) var(--ui-ease), transform var(--ui-base) var(--ui-ease); }
.ui-modal.is-closed { opacity: 0; transform: scale(0.94); }

/* Centred, letter-spaced code entry */
.ui-input--code { text-align: center; letter-spacing: 0.3em; text-transform: uppercase; font-family: ui-monospace, monospace; }

/* Scrollable full-screen setup (Word Search has a tall config panel) */
.ui-screen--scroll { align-items: flex-start; padding-block: var(--ui-s-8); }
.ui-screen__panel--split { display: flex; flex-direction: column; gap: var(--ui-s-6); max-width: 900px; }
@media (min-width: 768px) { .ui-screen__panel--split { flex-direction: row; } }
.ui-screen__panel--split > * { flex: 1 1 0; min-width: 0; }

/* Token bridges for converted legacy game markup */
.ui-surface-1-c        { background-color: var(--ui-surface-1); }
.ui-surface-3-c        { background-color: var(--ui-surface-3); }
.ui-border-c           { border-color: var(--ui-border); }
.ui-text-c             { color: var(--ui-text); }
.ui-text-secondary-c   { color: var(--ui-text-secondary); }
.ui-text-muted-c       { color: var(--ui-text-muted); }
.ui-surface-inset-c { background-color: var(--ui-surface-inset); }
