/* Agent Ludum — site stylesheet.
 *
 * One design language for the whole site. The platform tokens in :root below
 * (colors, type, geometry, shadows) are the shared identity every page wears —
 * the chrome (nav, footer, brand, buttons) never varies between games. The
 * structural rules reference var(--x) only, never a literal color or font.
 *
 * A single game tints only its own content by setting content tokens on its
 * <main data-game> region (see GameTheme in app/games/base.py); the chrome sits
 * outside <main> and stays constant. The `.al` scope near the bottom holds the
 * marketing front page's reset plus the shared AL components and the dark
 * `.al-plum` arena surface.
 */
@import url('https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,400;12..96,600;12..96,700;12..96,800&family=Space+Grotesk:wght@400;500;600;700&family=Space+Mono:wght@400;700&display=swap');

/* ============================================================
 * AGENT LUDUM — platform design tokens (the shared design language).
 *
 * One identity for the whole site. The chrome (nav, footer, brand, button
 * shape, type scale) reads these fixed values and never changes between games.
 * A game tints only its own content area by setting content tokens (--surface,
 * --brand, --hoard/--help/--hurt, ...) on its <main data-game> — see GameTheme
 * in app/games/base.py. Chrome lives outside <main>, so it never takes the tint.
 * ============================================================ */
:root {
    /* fonts */
    --al-display: 'Bricolage Grotesque', system-ui, sans-serif;
    --al-body: 'Space Grotesk', system-ui, sans-serif;
    --al-mono: 'Space Mono', ui-monospace, monospace;
    --font-body: var(--al-body);
    --font-head: var(--al-display);
    --font-mono: var(--al-mono);
    --head-transform: none;
    --head-spacing: -0.01em;
    /* geometry */
    --al-radius: 14px;
    --al-radius-lg: 22px;
    --al-maxw: 1200px;
    --radius: 12px;
    --maxw: 1040px;
    /* surfaces + ink (Lilac — the platform reading surface) */
    --bg: #eae5f5;
    --bg-2: #e2dcf1;
    --surface: #f4eefb;
    --surface-2: #e8e1f4;
    --ink: #241c33;
    --ink-soft: #655a7a;
    --line: #d8cfe9;
    --line-bold: #241c33;
    /* brand + accent (orange is the single primary-action color) */
    --brand: #e2640e;
    --brand-2: #5b4fd6;
    --on-brand: #fff6ec;
    --accent: #e2640e;
    --accent-ink: #fff6ec;
    --accent-hover: #c4540b;
    /* semantic move trio (always paired with a text label, never color-only) */
    --hoard: #b07e0d;
    --help: #1f8a5b;
    --hurt: #c1452f;
    /* error / danger */
    --bad: #c1452f;
    --bad-bg: #fbe9e4;
    --bad-line: #f0c8bd;
    /* code */
    --code-bg: #241c33;
    --code-ink: #f3edf9;
    /* shadows */
    --al-shadow: 3px 3px 0 var(--line-bold);
    --al-shadow-soft: 0 20px 44px -26px rgba(36, 28, 51, 0.5);
    --shadow: var(--al-shadow-soft);
}

/* ============================================================
 * STRUCTURE — references variables only, never literal colors
 * ============================================================ */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    font-family: var(--font-body);
    font-size: 16px;
    line-height: 1.5;
    color: var(--ink);
    background: var(--bg);
}

/* Shell — the chrome (.al-nav / .al-footer) is the shared Agent Ludum frame
 * defined in the AL component section below. `.shell` is the centered content
 * column every interior + lobby page uses; `.bleed` lets the marketing page run
 * full-width sections. Per-game tint is applied on <main data-game>, inside the
 * chrome, so the nav and footer never take a game's color. */
main.shell { max-width: var(--maxw); margin: 2rem auto; padding: 0 1.25rem; }
main.bleed { max-width: none; margin: 0; padding: 0; }

/* Typography */
h1, h2, h3 {
    font-family: var(--font-head);
    text-transform: var(--head-transform);
    letter-spacing: var(--head-spacing);
}
h1 { font-size: 1.6rem; margin: 0 0 1rem; }
h2 { font-size: 1.2rem; margin: 2rem 0 0.75rem; }
h3 { font-size: 1rem; margin: 1.25rem 0 0.5rem; }
a { color: var(--accent); }
small, .hint { color: var(--ink-soft); font-size: 0.85rem; }
.hint { display: block; margin: 0.25rem 0 0; }
.field-label {
    font-size: 0.8rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin-bottom: 0.35rem;
}

.warning-box {
    background: var(--bad-bg);
    border: 1px solid var(--bad-line);
    border-radius: var(--radius);
    color: var(--bad);
    padding: 0.75rem 1rem;
    margin: 1rem 0;
    font-size: 0.9rem;
}
.warning-box code { color: inherit; }

/* Cards */
.card, .game-card {
    background: var(--surface);
    border: 2px solid var(--line);
    border-radius: var(--al-radius);
    padding: 1.1rem 1.25rem;
    margin-bottom: 1rem;
}
.game-card { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.game-card h3 { margin: 0 0 0.2rem; }
.game-card .meta { color: var(--ink-soft); font-size: 0.88rem; }

/* Forms */
.form label { display: block; font-weight: 600; font-size: 0.9rem; margin-bottom: 1rem; }
.form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1rem; }
input[type="text"], input[type="number"], input[type="datetime-local"], input[type="date"],
input[type="email"], textarea, select {
    display: block;
    width: 100%;
    margin-top: 0.3rem;
    padding: 0.6rem 0.75rem;
    font: inherit;
    color: var(--ink);
    background: var(--surface);
    border: 1.5px solid var(--line);
    border-radius: var(--radius);
}
input:focus, textarea:focus, select:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
textarea { min-height: 8rem; resize: vertical; font-weight: 400; font-family: var(--font-mono); }

/* Default controls share the platform's pill shape so a button reads the same
 * on every page. The marketing page + lobby + nav use the bolder `.btn` (2px
 * outline + offset shadow) for primary moments; this is the lighter everyday
 * control for forms and dense pages. */
button, .cta {
    display: inline-block;
    padding: 0.55rem 1.2rem;
    font: inherit;
    font-weight: 700;
    color: var(--accent-ink);
    background: var(--accent);
    border: none;
    border-radius: 999px;
    cursor: pointer;
    text-decoration: none;
}
button:hover, .cta:hover { background: var(--accent-hover); }
button.secondary, .cta.secondary { background: transparent; color: var(--accent); border: 1.5px solid var(--line-bold); }

.save-confirm { color: #16a34a; font-weight: 600; margin-bottom: 0.75rem; }
.agent-setup-card { max-width: 42rem; padding: 1rem 1.1rem 1.15rem; }
.agent-setup-form { display: grid; gap: 0.8rem; }
.agent-setup-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.8rem; }
.agent-setup-form label { display: grid; gap: 0.35rem; margin-bottom: 0; }
.agent-setup-form input,
.agent-setup-form select,
.agent-setup-form textarea {
    padding: 0.5rem 0.7rem;
}
.agent-setup-form textarea { min-height: 7rem; }
.agent-setup-form .form-actions { margin-top: 0.15rem; justify-content: flex-end; }
.preset-picker { display: flex; flex-wrap: wrap; gap: 0.35rem; margin-bottom: 0.35rem; }
.preset-btn { background: transparent; color: var(--ink); border: 1px solid var(--line); font-weight: 500; padding: 0.28rem 0.65rem; border-radius: 999px; font-size: 0.88rem; }
.preset-btn:hover { border-color: var(--accent); color: var(--accent); background: transparent; }
.preset-btn.active { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.base-prompt-preview { white-space: pre-wrap; overflow-wrap: anywhere; }

/* Connection controls — the Pause/Rotate/Delete row that lives inside the
 * status card. A hairline divides it from the status text above. */
.connection-controls {
    display: flex;
    gap: 0.6rem;
    flex-wrap: wrap;
    margin-top: 0.9rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--line);
}
.connection-controls form { margin: 0; }

/* Provider toggles — one row per AI provider. The switch is the real control
 * (on = run this provider on this machine); the state text to its right is a
 * separate "is the CLI installed?" read-out. */
.provider-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--line);
}
.provider-row:last-of-type { border-bottom: none; }
.provider-toggle-form { display: flex; align-items: center; gap: 0.7rem; margin: 0; }
.provider-name { font-weight: 700; }
.provider-state { font-size: 0.85rem; color: var(--ink-soft); text-align: right; }
.provider-detected { color: var(--help); font-weight: 700; }
.provider-missing { color: var(--hoard); font-weight: 700; }

.provider-install-hint {
    margin: 0 0 0.4rem;
    padding: 0.55rem 0.75rem;
    font-size: 0.85rem;
    color: var(--ink-soft);
    background: var(--surface-2);
    border-left: 3px solid var(--hoard);
    border-radius: 0 var(--radius) var(--radius) 0;
}
.provider-install-hint code {
    font-family: var(--font-mono);
    background: var(--code-bg);
    color: var(--code-ink);
    padding: 0.05rem 0.35rem;
    border-radius: 5px;
    font-size: 0.82em;
}
.provider-strand-warning {
    margin-bottom: 0.75rem;
    padding: 0.75rem 0.9rem;
    background: var(--bad-bg);
    border: 1.5px solid var(--bad-line);
    border-radius: var(--radius);
}
.provider-strand-warning .meta { color: var(--bad); margin-top: 0; }

/* The switch itself: a hidden checkbox driving a sliding pill. */
.toggle-switch { display: inline-flex; align-items: center; cursor: pointer; flex: none; }
.toggle-switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.toggle-track {
    position: relative;
    display: inline-block;
    width: 42px;
    height: 24px;
    background: var(--line);
    border-radius: 999px;
    transition: background 0.15s ease;
}
.toggle-thumb {
    position: absolute;
    top: 3px;
    left: 3px;
    width: 18px;
    height: 18px;
    background: var(--surface);
    border-radius: 50%;
    box-shadow: 0 1px 2px rgba(36, 28, 51, 0.4);
    transition: transform 0.15s ease;
}
.toggle-switch input:checked + .toggle-track { background: var(--accent); }
.toggle-switch input:checked + .toggle-track .toggle-thumb { transform: translateX(18px); }
.toggle-switch input:focus-visible + .toggle-track {
    outline: none;
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 30%, transparent);
}

@media (max-width: 720px) {
    .agent-setup-grid { grid-template-columns: 1fr; }
    .agent-setup-card { padding: 0.9rem 0.9rem 1rem; }
}

/* Messages */
.error {
    color: var(--bad);
    background: var(--bad-bg);
    border: 1px solid var(--bad-line);
    border-radius: 8px;
    padding: 0.6rem 0.8rem;
    margin: 0.5rem 0;
}

/* Tables */
table {
    width: 100%;
    border-collapse: collapse;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    overflow: hidden;
    font-size: 0.92rem;
    margin-bottom: 1rem;
}
th, td { text-align: left; padding: 0.55rem 0.75rem; border-bottom: 1px solid var(--line); }
th { background: var(--surface-2); font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-soft); }
tr:last-child td { border-bottom: none; }

/* Game viewer */
.layout { display: grid; grid-template-columns: 290px 1fr; gap: 1.5rem; align-items: start; }
@media (max-width: 720px) { .layout { grid-template-columns: 1fr; } }
.turn-block {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    padding: 0.85rem 0.95rem;
    margin-bottom: 0.85rem;
}
.turn-head { margin: 0 0 0.6rem; font-size: 0.8rem; color: var(--ink-soft); font-weight: 700; }
.turn-block .moves { list-style: none; margin: 0; padding: 0; }
.turn-block .move-row {
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    padding: 0.65rem 0.75rem;
    margin-bottom: 0.55rem;
}
.turn-block .move-row:last-child { margin-bottom: 0; }
.move-line { display: flex; align-items: center; flex-wrap: wrap; gap: 0.35rem; }
.who-name { font-weight: 700; }
.said { margin-top: 0.45rem; color: var(--ink); }
.said.no-message { color: var(--ink-soft); font-style: italic; }
.turn-block .effect { font-size: 0.85rem; margin-top: 0.3rem; }
.turn-block .effect .who { color: var(--ink-soft); }
.turn-block .effect .sep { color: var(--ink-soft); margin: 0 0.2rem; }
.turn-block .turn-empty { color: var(--ink-soft); list-style: none; }
.action-card.help { border-color: color-mix(in srgb, var(--help) 28%, var(--line)); background: color-mix(in srgb, var(--help) 7%, var(--surface)); }
.action-card.hoard { border-color: color-mix(in srgb, var(--hoard) 24%, var(--line)); }
.action-card.hurt, .action-card.is-betrayal { border-color: var(--bad-line); background: var(--bad-bg); }
.action-line .delta { font-weight: 850; margin-left: 0; }
.mutual-note { color: var(--ink-soft); font-weight: 750; font-size: 0.82rem; }

/* The private "thinking", paired directly with each move. Shown by default,
   clamped to two lines, expandable. */
.thought {
    margin-top: 0.4rem;
    padding: 0.4rem 0.6rem;
    border-left: 2px solid var(--line);
    background: var(--surface-2);
    border-radius: 0 6px 6px 0;
    font-size: 0.85rem;
}
.thought-label {
    display: inline-block;
    font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.07em;
    font-weight: 700; color: var(--ink-soft); margin-bottom: 0.15rem;
}
.thought-text { font-style: italic; color: var(--ink-soft); }
/* Thinking is shown on demand (opt-in), so it is never clamped once revealed. */
.thought-wrap { margin-top: 0.4rem; }
.thinking-toggle {
    padding: 0.1rem 0.45rem; background: none; cursor: pointer;
    border: 1px solid var(--line); border-radius: 999px;
    color: var(--ink-soft); font-size: 0.72rem; font-weight: 600;
}
.thinking-toggle:hover { border-color: var(--accent); color: var(--accent); }
.thinking-toggle[aria-expanded="true"] { border-color: var(--accent); color: var(--accent); }

.missed {
    font-size: 0.72rem;
    color: var(--ink-soft);
    border: 1px solid var(--line);
    border-radius: 4px;
    padding: 0 0.3rem;
    margin-left: 0.1rem;
}
.feed-legend { font-size: 0.85rem; color: var(--ink-soft); margin: 0 0 0.75rem; }

/* One full-width feed (the standings rail lives in the hero row above). */
.feed-col-full { min-width: 0; }

/* Narration dock: the single story source while the replay plays. Shows the
   locator, headline, and key moves (as point-delta chips) of the turn the
   animation is currently on, so a watcher follows the match here without the
   feed. A reserved min-height keeps a longer headline or a busy move row from
   reflowing the page mid-play. */
.now-strip {
    display: flex; flex-direction: column; gap: 0.35rem;
    margin: 0 0 1.25rem; padding: 0.7rem 0.9rem;
    min-height: 4.6rem;  /* reserve ~2-line headline + a chip row, so play never reflows */
    background: var(--surface-2); border: 1px solid var(--line);
    border-left: 3px solid var(--accent); border-radius: 0 var(--radius) var(--radius) 0;
}
.now-strip[hidden] { display: none; }
.now-strip .now-strip-main { display: flex; align-items: baseline; gap: 0.6rem; }
.now-strip .now-strip-play { color: var(--accent); font-weight: 800; flex: none; }
.now-strip .now-strip-turn {
    flex: none; font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
    letter-spacing: 0.04em; color: var(--ink-soft); white-space: nowrap;
}
.now-strip .now-strip-headline { font-size: 1.02rem; line-height: 1.4; color: var(--ink); }
/* Live game: the ▶ becomes a pulsing red dot. */
.now-strip.is-live .now-strip-play { color: transparent; position: relative; width: 0.7rem; }
.now-strip.is-live .now-strip-play::before {
    content: ""; position: absolute; top: 0.15rem; left: 0; width: 0.6rem; height: 0.6rem;
    border-radius: 50%; background: var(--hurt); animation: now-live-pulse 1.6s infinite;
}
@keyframes now-live-pulse {
    0% { box-shadow: 0 0 0 0 rgba(193, 69, 47, 0.5); }
    70% { box-shadow: 0 0 0 7px rgba(193, 69, 47, 0); }
    100% { box-shadow: 0 0 0 0 rgba(193, 69, 47, 0); }
}

/* Move chips — the turn's plays, self-sufficient so the feed is never needed to
   follow along. Color carries the move trio but each chip also names the move
   via its delta sign and the betrayal label, so it reads without color too. */
.now-strip-moves {
    display: flex; flex-wrap: wrap; gap: 0.35rem; min-height: 1.5rem; align-items: center;
}
.dock-chip {
    display: inline-flex; align-items: center; gap: 0.3rem;
    font-size: 0.78rem; line-height: 1; padding: 0.2rem 0.45rem;
    border-radius: 999px; border: 1px solid var(--line);
    background: var(--surface); color: var(--ink); white-space: nowrap;
}
.dock-chip-label { font-weight: 600; }
.dock-chip-delta { font-weight: 800; font-variant-numeric: tabular-nums; }
.dock-chip-hurt, .dock-chip-betray { border-color: var(--hurt); color: var(--hurt); }
.dock-chip-help { border-color: var(--help); color: var(--help); }
.dock-chip-pact { border-color: var(--help); color: var(--help); }
.dock-chip-hoard { border-color: var(--hoard); color: var(--hoard); }
.dock-chip-more { color: var(--ink-soft); }

/* The feed block for the turn the animation is currently playing. */
.turn-block.is-current {
    border-color: var(--accent);
    box-shadow: inset 3px 0 0 0 var(--accent);
}

/* Turn header: label on the left, an at-a-glance summary of the turn's shape
   on the right so a 16-bot turn reads without scanning every card. */
.turn-head {
    display: flex; align-items: baseline; justify-content: space-between;
    flex-wrap: wrap; gap: 0.4rem 0.6rem; margin: 0 0 0.6rem;
}
.turn-head-label { font-size: 0.8rem; color: var(--ink-soft); font-weight: 700; }
.turn-summary { display: flex; flex-wrap: wrap; gap: 0.3rem; }
.ts {
    font-size: 0.7rem; font-weight: 700; padding: 0.05rem 0.4rem; border-radius: 999px;
    border: 1px solid var(--line); color: var(--ink-soft); white-space: nowrap;
}
.ts-help { color: var(--help); border-color: color-mix(in srgb, var(--help) 35%, var(--line)); }
.ts-hurt { color: var(--hurt); border-color: color-mix(in srgb, var(--hurt) 35%, var(--line)); }
.ts-hoard { color: var(--hoard); border-color: color-mix(in srgb, var(--hoard) 35%, var(--line)); }
.ts-mutual { color: var(--help); border-color: color-mix(in srgb, var(--help) 35%, var(--line)); }
.ts-betrayal { color: var(--hurt); background: var(--bad-bg); border-color: var(--bad-line); }
.ts-missed { color: var(--ink-soft); }
.action-line .arrow { color: var(--ink-soft); font-weight: 700; }

/* View switcher (Story / Cards / Compact), pushed to the right of the round-nav.
   A segmented control — one pill highlighted for the active view. */
.round-nav-spacer { flex: 1 1 auto; }
.view-switch { display: inline-flex; border: 1px solid var(--line); border-radius: 20px; overflow: hidden; }
.view-btn {
    background: transparent; color: var(--ink-soft); border: 0; cursor: pointer;
    font-weight: 600; font-size: 0.78rem; padding: 0.3rem 0.7rem;
    border-left: 1px solid var(--line);
}
.view-btn:first-child { border-left: 0; }
.view-btn:hover { color: var(--accent); }
.view-btn[aria-pressed="true"] { background: var(--accent); color: var(--accent-ink); }

/* The deterministic play-by-play headline. Shown only in Story view. */
.commentary {
    display: flex; gap: 0.55rem; align-items: baseline;
    margin: 0.1rem 0 0; padding: 0.55rem 0.7rem;
    background: var(--surface-2); border-left: 3px solid var(--accent); border-radius: 0 8px 8px 0;
}
.commentary-play { color: var(--accent); font-weight: 800; flex: none; }
.commentary-text { font-size: 1rem; line-height: 1.45; }

/* --- View modes (class on #live-region, so they survive SSE feed swaps) --- */
/* Story: just the headline (+ the turn-head summary). Hide the per-bot cards. */
.view-story .moves { display: none; }
/* Cards (default) and Compact: hide the headline. */
.view-cards .commentary,
.view-compact .commentary { display: none; }
/* Compact swaps the per-bot cards for the grouped block (one line per action
   type, delta stated once, hoards collapsed to a named list). */
.moves-grouped { display: none; list-style: none; margin: 0.3rem 0 0; padding: 0; }
.view-compact .moves { display: none; }
.view-compact .moves-grouped { display: block; }
.view-compact .turn-summary { display: none; }
.view-compact .turn-block { padding: 0.65rem 0.8rem; }

.cgroup {
    display: flex; gap: 0.6rem; align-items: baseline;
    padding: 0.35rem 0; border-top: 1px solid var(--line);
}
.cgroup:first-child { border-top: 0; }
.cglabel {
    flex: none; width: 5.2rem; font-weight: 800; font-size: 0.78rem;
    display: flex; gap: 0.25rem; align-items: baseline; white-space: nowrap;
}
.cgdelta { font-variant-numeric: tabular-nums; }
.cgroup-hurt .cgverb, .cgroup-hurt .cgdelta { color: var(--hurt); }
.cgroup-pact .cgverb, .cgroup-pact .cgdelta,
.cgroup-help .cgverb, .cgroup-help .cgdelta { color: var(--help); }
.cgroup-hoard .cgverb, .cgroup-hoard .cgdelta { color: var(--hoard); }
.citems { color: var(--ink); font-size: 0.9rem; line-height: 1.55; }
.citems .cwho { font-weight: 600; }
.citems .ccount { color: var(--ink-soft); margin-left: 0.2rem; }
.citems .cbetray {
    font-size: 0.6rem; font-weight: 800; text-transform: uppercase;
    letter-spacing: 0.03em; color: var(--hurt); background: var(--bad-bg);
    padding: 0 0.25rem; border-radius: 4px;
}

/* Action color-coding (works in every theme) */
.act {
    font-size: 0.78rem;
    font-weight: 850;
    padding: 0.12rem 0.48rem;
    border-radius: 6px;
}
.act-hoard { color: var(--hoard); background: color-mix(in srgb, var(--hoard) 12%, transparent); }
.act-help { color: var(--help); background: color-mix(in srgb, var(--help) 13%, transparent); }
.act-hurt { color: var(--hurt); background: var(--bad-bg); }

/* Drama markers: pact (mutual help), betrayal (hurt a recent partner) */
.tag { font-size: 0.7rem; font-weight: 700; padding: 0.05rem 0.4rem; border-radius: 5px; white-space: nowrap; }
.tag-pact { color: var(--help); background: color-mix(in oklab, var(--help) 16%, transparent); }
.tag-betrayal { color: var(--hurt); background: var(--bad-bg); }
.move-row.is-hurt .thought, .move-row.is-betrayal .thought { border-left-color: var(--hurt); }
.move-row.is-betrayal { box-shadow: inset 3px 0 0 0 var(--hurt); }

/* Player dashboard */
.key {
    font-family: var(--font-mono);
    background: var(--surface-2);
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 0.5rem 0.7rem;
    word-break: break-all;
}
.setup {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 1rem 1.25rem;
    margin-bottom: 1rem;
}
.setup pre, pre {
    background: var(--code-bg);
    color: var(--code-ink);
    padding: 0.8rem 1rem;
    border-radius: 8px;
    overflow-x: auto;
    font-size: 0.85rem;
    font-family: var(--font-mono);
}
code {
    font-family: var(--font-mono);
    font-size: 0.9em;
    background: var(--surface-2);
    padding: 0.1rem 0.35rem;
    border-radius: 4px;
}
pre code { background: none; padding: 0; }

.key-row { display: flex; gap: 0.75rem; align-items: center; flex-wrap: wrap; margin: 0.5rem 0; }
.key-row code { font-size: 1em; padding: 0.4rem 0.6rem; word-break: break-all; }

.auth { text-align: center; margin: 4rem auto; }


/* ---- Connect-your-AI (MCP connection) ---- */
/* Readiness banner: green-tinted when an agent exists, accent-nudge when not. */
.byo-readiness.is-ready { border-color: color-mix(in srgb, var(--help) 45%, var(--line)); }
.byo-readiness.needs-agent { border-color: var(--accent); }

/* Copy button: smaller than the big .btn, sits above its <pre>. */
.btn-copy {
    color: var(--ink);
    background: var(--surface);
    border: 1.5px solid var(--line);
    border-radius: var(--radius);
    padding: 0.35rem 0.75rem;
    font-size: 0.85rem;
    cursor: pointer;
    margin-bottom: 0.4rem;
}
.btn-copy:hover { border-color: var(--accent); }
.btn-copy:disabled { color: var(--ink-soft); cursor: default; }

/* CSS-only client picker: hidden radios drive which panel shows via :checked. */
.byo-tab-input { position: absolute; opacity: 0; pointer-events: none; }
.byo-tab-labels { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 0.9rem; }
.byo-tab-label {
    display: inline-block;
    padding: 0.4rem 0.85rem;
    border: 1.5px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface);
    color: var(--ink-soft);
    font-size: 0.9rem;
    cursor: pointer;
    user-select: none;
}
.byo-tab-label:hover { border-color: var(--accent); }
.byo-tab-panel { display: none; }
/* Map each checked radio to its label (highlight) and its panel (show). The
 * order matches the template's loop: Claude Code, Codex, Gemini, Claude Desktop. */
#byo-tab-claude-code:checked ~ .byo-tab-labels label[for="byo-tab-claude-code"],
#byo-tab-codex:checked ~ .byo-tab-labels label[for="byo-tab-codex"],
#byo-tab-gemini:checked ~ .byo-tab-labels label[for="byo-tab-gemini"],
#byo-tab-claude-desktop:checked ~ .byo-tab-labels label[for="byo-tab-claude-desktop"] {
    background: var(--accent);
    color: var(--accent-ink);
    border-color: var(--accent);
}
#byo-tab-claude-code:checked ~ #byo-panel-claude-code,
#byo-tab-codex:checked ~ #byo-panel-codex,
#byo-tab-gemini:checked ~ #byo-panel-gemini,
#byo-tab-claude-desktop:checked ~ #byo-panel-claude-desktop { display: block; }

/* Numbered click-through steps for GUI clients (Claude Desktop). */
.byo-steps { margin: 0 0 0.4rem; padding-left: 1.3rem; }
.byo-steps li { margin-bottom: 0.35rem; }

/* Numbered sub-steps for the act of connecting (paste / sign in), tied together
 * by a rail down the left so they read as one sequence, not stray boxes. */
.byo-flow { list-style: none; counter-reset: byoflow; margin: 0.6rem 0 0; padding: 0; }
.byo-flow-step {
    counter-increment: byoflow;
    position: relative;
    padding-left: 2.3rem;
    padding-bottom: 1.1rem;
}
.byo-flow-step:last-child { padding-bottom: 0; }
.byo-flow-step::before {
    content: counter(byoflow);
    position: absolute;
    left: 0;
    top: 0;
    width: 1.65rem;
    height: 1.65rem;
    border-radius: 50%;
    background: var(--ink);
    color: var(--surface);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.82rem;
    font-weight: 700;
}
.byo-flow-step:not(:last-child)::after {
    content: "";
    position: absolute;
    left: calc(0.825rem - 1px);
    top: 1.95rem;
    bottom: 0.2rem;
    width: 2px;
    background: var(--line);
}
.byo-flow-title { display: block; font-weight: 600; margin-bottom: 0.5rem; }
.byo-flow-step pre { margin: 0; }

/* Copyable command block: the Copy button sits to the RIGHT of the text, not
 * above it. The text scrolls horizontally if it's long; the button never shrinks. */
.byo-cmd { display: flex; align-items: flex-start; gap: 0.5rem; }
.byo-cmd-text { flex: 1; min-width: 0; margin: 0; overflow-x: auto; }
.byo-cmd-btn { flex: none; margin: 0; }
@media (max-width: 480px) {
    /* Too narrow to sit side by side — stack with the button under the text. */
    .byo-cmd { flex-direction: column; align-items: stretch; }
}

/* Short command (e.g. /mcp): a small inline chip, not a full block, so a tiny
 * keystroke doesn't visually outweigh the real steps described next to it. */
.byo-cmd-inline { display: inline-flex; align-items: center; gap: 0.4rem; vertical-align: middle; }
.byo-cmd-inline code {
    background: var(--surface-2);
    color: var(--ink);
    padding: 0.2rem 0.5rem;
    border-radius: 6px;
    font-size: 0.95rem;
}
.byo-cmd-inline-btn { margin: 0; padding: 0.2rem 0.6rem; font-size: 0.78rem; }

/* Short "Sign in with Google" note shown under a command / steps. */
.byo-signin-note { margin-top: 0.5rem; }

.byo-connector summary { cursor: pointer; font-weight: 700; }
.byo-connector summary:hover { color: var(--accent); }
.byo-connector-body { margin-top: 0.9rem; }

/* Collapsed secondary blocks (returning "✓ Set up", reconnect). */
.byo-collapsed summary { cursor: pointer; font-weight: 700; }
.byo-collapsed summary:hover { color: var(--accent); }
.byo-tick { color: var(--help); }

/* Waiting region: a pulsing dot in a calm box while we wait for the AI. */
.byo-listening-box {
    display: flex;
    align-items: flex-start;
    gap: 0.65rem;
    margin-top: 1.2rem;
    padding: 0.85rem 1rem;
    background: var(--surface-2);
    border-radius: var(--radius);
}
.byo-listening-box .byo-pulse-dot { margin-top: 0.35rem; flex: none; }
.byo-listening-title { margin: 0; font-weight: 600; }
.byo-pulse-dot {
    width: 0.6rem;
    height: 0.6rem;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 60%, transparent);
    animation: byo-pulse 1.6s ease-out infinite;
}
@keyframes byo-pulse {
    0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 55%, transparent); }
    70% { box-shadow: 0 0 0 0.6rem color-mix(in srgb, var(--accent) 0%, transparent); }
    100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
    .byo-pulse-dot { animation: none; }
}

/* Post-connect: a clear green "Connected" banner so the content swap is a payoff,
 * not a surprise — then the single next step. */
.byo-connected { margin-top: 1.2rem; }
.byo-connected-banner {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.85rem 1rem;
    border-radius: var(--radius);
    background: color-mix(in srgb, var(--help) 12%, var(--surface));
    border: 1.5px solid color-mix(in srgb, var(--help) 40%, var(--line));
}
.byo-connected-check {
    flex: none;
    width: 1.9rem;
    height: 1.9rem;
    border-radius: 50%;
    background: var(--help);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.05rem;
    font-weight: 700;
}
.byo-connected-title { margin: 0; font-weight: 700; }
.byo-connected-sub { margin: 0.1rem 0 0; color: var(--ink-soft); font-size: 0.9rem; }
.byo-next-label {
    margin: 1.3rem 0 0.2rem;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ink-soft);
}
.byo-next-title { margin: 0 0 0.3rem; }
.byo-next-body { margin: 0 0 0.9rem; color: var(--ink-soft); }
.byo-playprompt { margin-top: 1.2rem; }
.byo-playprompt pre { margin: 0; }

/* Playing: the play-prompt took — the AI is calling the game on its own. A live
 * green banner with a pulsing dot confirms it's working so the user can move on. */
.byo-playing { margin-top: 1.2rem; }
.byo-playing-banner {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.85rem 1rem;
    border-radius: var(--radius);
    background: color-mix(in srgb, var(--help) 14%, var(--surface));
    border: 1.5px solid color-mix(in srgb, var(--help) 45%, var(--line));
}
.byo-playing-dot {
    flex: none;
    margin-top: 0.45rem;
    width: 0.65rem;
    height: 0.65rem;
    border-radius: 50%;
    background: var(--help);
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--help) 60%, transparent);
    animation: byo-play-pulse 1.6s ease-out infinite;
}
@keyframes byo-play-pulse {
    0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--help) 55%, transparent); }
    70% { box-shadow: 0 0 0 0.6rem color-mix(in srgb, var(--help) 0%, transparent); }
    100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--help) 0%, transparent); }
}
@media (prefers-reduced-motion: reduce) {
    .byo-playing-dot { animation: none; }
}
.byo-playing-title { margin: 0; font-weight: 700; }
.byo-playing-sub { margin: 0.1rem 0 0; color: var(--ink-soft); font-size: 0.9rem; }
.byo-playing-status { margin: 0.4rem 0 0; font-weight: 600; font-size: 0.9rem; }
.byo-playing-actions { margin: 0.9rem 0 0; }


/* ---- Lobby ---- */
.hero { margin-bottom: 2.5rem; }
.hero h1 { margin-bottom: 0.5rem; }
.hero p { color: var(--ink-soft); max-width: 62ch; margin: 0; }
.hchips { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 1rem; }
.hchip {
    font-size: 0.8rem;
    font-weight: 700;
    padding: 0.3rem 0.65rem;
    border-radius: 6px;
    border: 1px solid currentColor;
}
.hchip.hoard { color: var(--hoard); }
.hchip.help { color: var(--help); }
.hchip.hurt { color: var(--hurt); }

.section-head { display: flex; align-items: baseline; gap: 0.6rem; margin: 2rem 0 0.75rem; }
.section-head h2 { margin: 0; }
.section-head .count {
    font-size: 0.78rem;
    color: var(--ink-soft);
    background: var(--surface-2);
    border-radius: 999px;
    padding: 0.05rem 0.5rem;
}
.lobby-section { margin-bottom: 1.75rem; }
.lobby-section:last-of-type { margin-bottom: 0; }
.section-head-row { align-items: flex-start; justify-content: space-between; flex-wrap: wrap; gap: 0.75rem 1rem; }
.section-head-copy { min-width: 0; }
.section-note { color: var(--ink-soft); margin: 0.2rem 0 0; font-size: 0.88rem; max-width: 60ch; }
.section-head-actions { display: flex; align-items: center; gap: 0.65rem; flex-shrink: 0; flex-wrap: wrap; }
.section-link { color: var(--accent); font-size: 0.88rem; font-weight: 700; text-decoration: none; }
.section-link:hover { text-decoration: underline; }
.empty { color: var(--ink-soft); padding: 0.25rem 0 0.5rem; }

.game-card-info { min-width: 0; }
.game-card-info h3 { margin: 0 0 0.2rem; }
.game-card-action { display: flex; align-items: center; gap: 0.85rem; flex-shrink: 0; }

/* Agent list — compact grouped rows */
.agent-group { margin-bottom: 1.75rem; }
.agent-group-title { font-size: 0.72rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--ink-soft); margin: 0 0 0.35rem; }
.agent-row { display: flex; align-items: center; gap: 0.65rem; padding: 0.5rem 0.6rem; border-bottom: 1px solid var(--line); text-decoration: none; color: inherit; transition: background 0.12s; }
.agent-group .agent-row:first-of-type { border-top: 1px solid var(--line); }
.agent-row:hover { background: var(--surface-2); }
.agent-row-name { font-weight: 600; font-size: 0.9rem; flex-shrink: 0; min-width: 7rem; }
.agent-row-meta { color: var(--ink-soft); font-size: 0.82rem; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.agent-row-chevron { color: var(--ink-soft); font-size: 1.1rem; flex-shrink: 0; opacity: 0; transition: opacity 0.12s, transform 0.12s; }
.agent-row:hover .agent-row-chevron { opacity: 1; transform: translateX(2px); }
@media (max-width: 600px) {
    .agent-row-meta { display: none; }
    .agent-row-chevron { opacity: 0.4; }
}

.badge {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: 0.22rem 0.55rem;
    border-radius: 999px;
}
.badge-live { background: color-mix(in srgb, var(--hurt) 18%, transparent); color: var(--hurt); }
.badge-soon { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.badge-done { background: var(--surface-2); color: var(--ink-soft); }
/* Bot operational health: green = runner alive, red = runner down (needs action). */
.badge-ok { background: color-mix(in srgb, var(--help) 18%, transparent); color: var(--help); }
.badge-alert { background: color-mix(in srgb, var(--hurt) 16%, transparent); color: var(--hurt); }
.badge .dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; animation: hhh-pulse 1.4s ease-in-out infinite; }
/* A static (non-pulsing) dot for steady states like Ready. */
.badge .dot-still { animation: none; }
.bot-health-meta { color: var(--ink-soft); }
@keyframes hhh-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }

/* ---- Game viewer ---- */
.game-head { display: flex; align-items: center; gap: 0.85rem; flex-wrap: wrap; margin-bottom: 1rem; }
.game-head .meta { color: var(--ink-soft); font-size: 0.9rem; }
.scorepanel { position: sticky; top: 1rem; }
.rail-title { margin: 0 0 0.6rem; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--ink-soft); }
.rail { list-style: none; margin: 0 0 0.6rem; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.rail-row {
    display: grid;
    grid-template-columns: 1.2rem minmax(0, 1fr) auto;
    grid-template-areas: "rank name wins" "rank bar bar";
    column-gap: 0.55rem; row-gap: 0.35rem;
    align-items: center;
    padding: 0.5rem 0.6rem;
    border: 1px solid transparent;
    border-radius: 9px;
}
.rail-row.leader { background: var(--surface-2); border-color: var(--line); }
.rail-row .rk { grid-area: rank; color: var(--ink-soft); font-variant-numeric: tabular-nums; font-weight: 700; text-align: center; }
.rail-row.leader .rk { color: var(--accent); }
.rail-row .nm { grid-area: name; min-width: 0; display: flex; flex-direction: column; line-height: 1.2; }
.rail-row .name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rail-row .pts { font-size: 0.72rem; color: var(--ink-soft); }
.rail-row .sc { grid-area: wins; justify-self: end; display: flex; align-items: baseline; gap: 0.25rem; font-variant-numeric: tabular-nums; font-weight: 800; font-size: 1.15rem; }
.rail-row .sc-unit { font-size: 0.62rem; font-weight: 700; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.04em; }
.rail-row .track { grid-area: bar; height: 7px; background: var(--surface-2); border-radius: 999px; overflow: hidden; }
.rail-row.leader .track { background: var(--bg); }
.rail-row .bar { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
.feed .empty { padding: 1.5rem 0; }

/* ---- Sideline coach panel ---- */
.coach-panel {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 0.65rem 0.85rem;
    margin-bottom: 1rem;
}
.coach-panel-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.35rem;
}
.coach-panel-head h3 {
    margin: 0;
    font-size: 0.82rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ink-soft);
    font-weight: 700;
}
.coach-panel-link {
    border: 0;
    background: transparent;
    color: var(--accent);
    font: inherit;
    font-size: 0.82rem;
    font-weight: 700;
    padding: 0.05rem 0;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 0.18em;
}
.coach-panel-link:hover { color: var(--accent-hover); }
.coach-panel-link:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 4px;
}
.coach-status {
    font-size: 0.78rem;
    color: var(--ink-soft);
    margin-top: 0.45rem;
}
.coach-status.armed { color: var(--accent); font-weight: 600; }
.coach-status.active-now { color: var(--help); font-weight: 600; }
.coach-prompt-dialog {
    width: min(860px, calc(100vw - 2rem));
    border: 1px solid var(--line);
    border-radius: var(--al-radius-lg);
    padding: 0;
    background: var(--surface);
    color: var(--ink);
    box-shadow: var(--al-shadow-soft);
}
.coach-prompt-dialog::backdrop {
    background: rgba(36, 28, 51, 0.55);
}
.coach-prompt-shell {
    padding: 1rem 1.1rem 1.05rem;
}
.coach-prompt-head {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    align-items: flex-start;
    margin-bottom: 0.9rem;
}
.coach-prompt-head h4 {
    margin: 0;
    font-family: var(--font-head);
    font-size: 1.05rem;
    letter-spacing: var(--head-spacing);
}
.coach-dialog-close {
    border: 0;
    background: var(--surface-2);
    color: var(--ink);
    width: 2rem;
    height: 2rem;
    border-radius: 999px;
    font-size: 1.1rem;
    line-height: 1;
    font-weight: 700;
    cursor: pointer;
    flex: none;
}
.coach-dialog-close:hover { background: var(--line); }
.coach-prompt-grid {
    display: grid;
    grid-template-columns: minmax(0, 1.1fr) minmax(280px, 0.9fr);
    gap: 0.9rem;
    align-items: start;
}
.coach-prompt-copy-wrap,
.coach-prompt-form {
    min-width: 0;
}
.coach-prompt-label {
    font-size: 0.76rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ink-soft);
    margin-bottom: 0.35rem;
}
.coach-prompt-copy {
    margin: 0;
    padding: 0.9rem 0.95rem;
    min-height: 15rem;
    border: 1px solid var(--line);
    border-radius: var(--radius);
    background: var(--surface-2);
    color: var(--ink);
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-size: 0.9rem;
    line-height: 1.55;
}
.coach-prompt-footnote {
    margin: 0.55rem 0 0;
    color: var(--ink-soft);
    font-size: 0.82rem;
}
.coach-prompt-field textarea {
    width: 100%;
    min-height: 12rem;
    resize: vertical;
    font-size: 0.92rem;
    font-family: var(--font-body);
    margin-top: 0.35rem;
}
.coach-prompt-actions {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    flex-wrap: wrap;
    margin-top: 0.85rem;
}
.coach-prompt-actions .btn {
    font-size: 0.85rem;
    padding: 0.38rem 0.82rem;
}
.coach-prompt-field .field-label {
    margin-bottom: 0;
}
@media (max-width: 760px) {
    .coach-prompt-grid { grid-template-columns: 1fr; }
    .coach-prompt-copy { min-height: 10rem; }
}
@media (max-width: 560px) {
    .coach-panel-head { flex-direction: column; align-items: flex-start; }
    .coach-panel-link { padding-left: 0; }
    .coach-prompt-shell { padding: 0.85rem 0.85rem 0.9rem; }
    .coach-prompt-head { flex-direction: column; }
    .coach-prompt-actions { flex-direction: column; align-items: stretch; }
    .coach-prompt-actions .btn { width: 100%; }
}
/* rc-rail "you" indicator */
.rc-rail-row.rc-you .nm-name::after {
    content: " · you";
    color: var(--accent);
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}
.delta { font-variant-numeric: tabular-nums; margin-left: 0.25rem; }
.delta.pos { color: var(--help); }
.delta.neg { color: var(--hurt); }
.delta.zero { color: var(--ink-soft); }
.turn-block .msg { color: var(--ink-soft); }

/* Round navigation: a sticky chip bar that filters the feed to one round. */
.feed-col { min-width: 0; }
.round-nav {
    position: sticky;
    top: 0;
    z-index: 5;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 1rem;
    padding-bottom: 0.85rem;
    border-bottom: 1px solid var(--line);
    background: var(--bg);
}
.round-nav-label {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ink-soft);
    margin-right: 0.2rem;
}
.round-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    background: transparent;
    color: var(--ink);
    border: 1px solid var(--line);
    border-radius: 20px;
    font-weight: 600;
    font-size: 0.85rem;
    padding: 0.3rem 0.7rem;
}
.round-chip:hover { border-color: var(--accent); color: var(--accent); background: transparent; }
.round-chip.is-active { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
.round-chip.is-active:hover { background: var(--accent-hover); color: var(--accent-ink); }
.round-chip .live-dot {
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--hurt);
    animation: hhh-pulse 1.4s ease-in-out infinite;
}
.round-chip.is-active .live-dot { background: currentColor; }
.round-heading {
    margin: 0 0 0.75rem;
    font-size: 0.95rem;
    text-transform: var(--head-transform);
    letter-spacing: var(--head-spacing);
}
.round-section { margin-bottom: 1.5rem; }
.round-section[hidden] { display: none; }
@media (max-width: 720px) { .scorepanel { position: static; } }

/* ---- Toolbar (page-top action row) ---- */
.toolbar { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem; }
.toolbar h1 { margin: 0; }

/* Interior page chrome — every app page (viewer, join, dashboards, admin)
 * opens the same way: a muted back link, then the title block. Keeps the
 * inside of the app reading like the marketing/lobby front. */
.backlink {
    display: inline-flex; align-items: center; gap: 0.3rem;
    margin: 0.25rem 0 1rem;
    font-weight: 700; font-size: 0.9rem;
    color: var(--ink-soft); text-decoration: none;
}
.backlink:hover { color: var(--ink); }
.page-head { margin: 0 0 1.5rem; }
.page-head h1 { margin: 0; }
.page-head .sub { color: var(--ink-soft); margin: 0.45rem 0 0; }
.page-head .sub .badge { vertical-align: middle; }
/* A right-aligned actions row under a title (e.g. Analysis link on the viewer). */
.page-head-row { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.page-head .coach-panel { margin: 0.6rem 0 0.45rem; }
/* A submit/cancel row under a form. */
.form-actions { display: flex; gap: 0.75rem; align-items: center; flex-wrap: wrap; margin-top: 1.5rem; }
.admin-prompts-link { margin-top: 2rem; }
.report-table-wrap {
    overflow-x: auto;
    border: 1px solid var(--line);
    border-radius: var(--al-radius-lg);
    background: var(--surface);
}
.report-table-wrap table { margin: 0; border: 0; }
.report-table-wrap th:first-child,
.report-table-wrap td:first-child { padding-left: 1rem; }
.report-table-wrap th:last-child,
.report-table-wrap td:last-child { padding-right: 1rem; }
.report-empty {
    padding: 1rem;
    margin: 0;
    color: var(--ink-soft);
}

/* ---- Player dashboard ---- */
.dl-grid { display: grid; grid-template-columns: auto 1fr; gap: 0.35rem 1.25rem; margin: 0; }
.dl-grid dt { color: var(--ink-soft); font-size: 0.85rem; align-self: center; }
.dl-grid dd { margin: 0; font-weight: 600; }
.copy-row { display: flex; gap: 0.5rem; align-items: center; }
.copy-row .key { flex: 1; margin: 0; }
.copy-row button { flex-shrink: 0; }
.ai-picker { display: inline-flex; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; margin-bottom: 0.5rem; }
.ai-picker label { margin: 0; }
.ai-picker input { position: absolute; opacity: 0; pointer-events: none; }
.ai-picker span { display: block; padding: 0.5rem 1rem; cursor: pointer; font-weight: 600; font-size: 0.9rem; border-right: 1px solid var(--line); }
.ai-picker label:last-child span { border-right: none; }
.ai-picker input:checked + span { background: var(--accent); color: var(--accent-ink); }
.danger-zone { margin-top: 2rem; }
.danger-zone button,
button.danger,
.cta.danger { background: transparent; color: var(--bad); border: 1px solid var(--bad-line); }
.danger-zone button:hover,
button.danger:hover,
.cta.danger:hover { background: var(--bad-bg); }
/* Inline forms in card actions shouldn't add vertical margin. */
.game-card-action form { margin: 0; }

.game-card-link { display: block; text-decoration: none; color: inherit; }
.game-card-link:hover .game-card { border-color: var(--accent); }

/* ---- Guide pages ---- */
.doc { white-space: pre-wrap; word-wrap: break-word; line-height: 1.55; }

/* ============================================================
 * MOBILE — small-screen overrides
 * ============================================================ */
@media (max-width: 600px) {
    main.shell { margin: 1.25rem auto; padding: 0 1rem; }

    h1 { font-size: 1.35rem; }
    h2 { font-size: 1.1rem; }

    /* Stack card content + action on narrow screens. */
    .game-card { flex-direction: column; align-items: stretch; }
    .game-card-action { justify-content: space-between; }
    .game-card-action .cta,
    .game-card-action .btn { flex: 1; justify-content: center; text-align: center; }

    .toolbar { flex-direction: column; align-items: stretch; }
    .toolbar .cta { text-align: center; }

    /* Segmented AI picker becomes full-width, even thirds. */
    .ai-picker { display: flex; width: 100%; }
    .ai-picker label { flex: 1; }
    .ai-picker span { text-align: center; padding: 0.55rem 0.4rem; }

    /* Copy rows stack so the button isn't cramped. */
    .copy-row { flex-direction: column; align-items: stretch; }
    .copy-row button { width: 100%; }

    /* Definition grids go single-column. */
    .dl-grid { grid-template-columns: 1fr; gap: 0.1rem; }
    .dl-grid dt { margin-top: 0.5rem; }

    /* Wide tables scroll horizontally instead of overflowing the page. */
    table { display: block; overflow-x: auto; }

    /* Forms: comfortable tap targets. */
    button, .cta { padding: 0.65rem 1.1rem; }
    input, textarea, select { font-size: 16px; } /* avoids iOS zoom-on-focus */
}

/* --- Bot onboarding status panel (005) --- */
.bot-status-head {
    margin: 0;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}
/* Meaning never rides on color alone: the ✓ glyph carries it too. */
.bot-status-head .ok { color: var(--help); font-weight: 700; }
.bot-status .dot.pulse {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--ink-soft);
    animation: hhh-pulse 1.4s ease-in-out infinite;
}
.bot-status .hint { margin-top: 0.35rem; }
.bot-status .cta { margin-top: 0.75rem; }
.bot-status-line {
    margin: 0;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}
.bot-status-trouble { margin-top: 0.85rem; }
.bot-status-trouble summary {
    cursor: pointer;
    color: var(--ink-soft);
    font-size: 0.85rem;
}
.bot-status-trouble form { margin-top: 0.5rem; }

/* One-shot flourish applied only on a live SSE update (see detail.html). */
.status-flash { animation: hhh-status-flash 1.1s ease-out; }
@keyframes hhh-status-flash {
    0% { background: color-mix(in srgb, var(--help) 22%, transparent); }
    100% { background: transparent; }
}

@media (max-width: 640px) {
    .bot-status .cta { display: block; text-align: center; }
}

/* ============================================================
 * LOBBY v2 — adaptive hero (live marquee / quiet replay), tiers
 * Variables only; no literal colors.
 * ============================================================ */

/* Onboarding success banner — shown after bot connects, before first match join. */
.onboarding-banner {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    background: #e8f5ef;
    border: 1.5px solid var(--help);
    border-radius: var(--radius);
    padding: 0.875rem 1.125rem;
    margin-bottom: 1.75rem;
    font-size: 0.95rem;
}
.onboarding-banner-check {
    color: var(--help);
    font-weight: 700;
    font-size: 1.1rem;
    flex-shrink: 0;
}

/* Game lobby identity header — persists in both live and quiet states. */
.lobby-header { padding: 1.5rem 0 1.25rem; border-bottom: 1.5px solid var(--line); margin-bottom: 1.75rem; }
.lobby-title { font-size: clamp(1.6rem, 5vw, 2.4rem); margin: 0; line-height: 1.1; letter-spacing: -0.01em; }
.lobby-sub { color: var(--ink-soft); margin: 0.35rem 0 0; font-size: 0.95rem; }
.hhh-hoard { color: var(--hoard); }
.hhh-hurt  { color: var(--hurt); }
.hhh-help  { color: var(--help); }

/* Warm body background for HHH pages (lobby + viewer) — distinct from the
   marketing home's Lilac. The game_theme vars land on <main>; this tints the
   body so the full viewport feels like it's inside the game. */
.body-game-hoard-hurt-help { background: #f0e8d8; }

/* Quiet-state hero: pitch without the full marketing h1. */
.hero-quiet { margin-bottom: 1.4rem; }
.hero-quiet h1 { font-size: 1.95rem; max-width: 20ch; margin: 0 0 0.6rem; }
.hero-quiet p { color: var(--ink-soft); max-width: 56ch; margin: 0; }
.hero-lede { font-size: 1.3rem; font-weight: 600; max-width: 32ch; margin: 0 0 0.5rem; line-height: 1.3; }

/* The three moves, shown as chips. Effect text means color is never the only
   cue, so the legend reads for color-blind viewers too. */
.move-legend { list-style: none; display: flex; flex-wrap: wrap; gap: 0.5rem; padding: 0; margin: 0 0 2rem; }
.move-legend .hchip { display: inline-flex; align-items: baseline; gap: 0.4rem; }
.hchip-move { font-weight: 800; }
.hchip-eff { color: var(--ink-soft); font-weight: 400; font-size: 0.82rem; }

/* Live marquee — the single most-watchable thing, given real weight. */
.marquee {
    background: var(--surface);
    border: 2px solid var(--line);
    border-left: 4px solid var(--hurt);
    border-radius: var(--al-radius-lg);
    box-shadow: var(--al-shadow-soft);
    padding: 1.5rem 1.5rem 1.6rem;
    margin-bottom: 1rem;
}
.marquee-top { display: flex; align-items: center; gap: 0.85rem; flex-wrap: wrap; }
.marquee-meta { color: var(--ink-soft); font-size: 0.9rem; }
.marquee-title { margin: 0.55rem 0 1.1rem; font-size: 1.85rem; }
/* Brighter, larger LIVE pill than the row badge — this is the hero. */
.marquee .badge-live {
    font-size: 0.78rem;
    background: color-mix(in srgb, var(--hurt) 26%, transparent);
    color: var(--hurt);
    border: 1px solid color-mix(in srgb, var(--hurt) 45%, transparent);
}

.marquee-standings { list-style: none; margin: 0 0 1.3rem; padding: 0; display: flex; flex-direction: column; gap: 0.3rem; max-width: 32rem; }
.marquee-standings li {
    display: grid;
    grid-template-columns: 1.5rem 1fr auto auto;
    align-items: baseline;
    gap: 0.85rem;
    padding: 0.35rem 0.55rem;
    border-radius: 6px;
}
.marquee-standings li.leader { background: var(--surface-2); }
.ms-rank { color: var(--ink-soft); text-align: right; font-variant-numeric: tabular-nums; }
.ms-name { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.marquee-standings li.leader .ms-name { color: var(--accent); }
/* Round-wins is what wins the game, so it's the prominent number; the
   current-round score is muted, secondary context. */
.ms-score { color: var(--ink-soft); font-size: 0.85rem; text-align: right; font-variant-numeric: tabular-nums; }
.ms-wins { font-weight: 700; min-width: 3.4rem; text-align: right; font-variant-numeric: tabular-nums; }
.marquee-cta { padding: 0.7rem 1.45rem; font-size: 1.02rem; }

/* Tier cues: live cards carry the same accent edge as the marquee. */
.game-card.tier-live { border-left: 3px solid var(--hurt); }

/* Recent: muted, dense rows — finished games shouldn't outweigh live ones. */
.recent-list {
    list-style: none; margin: 0 0 1rem; padding: 0;
    border: 2px solid var(--line); border-radius: var(--al-radius);
    background: var(--surface); overflow: hidden;
}
.recent-row {
    display: flex; align-items: center; gap: 0.75rem;
    padding: 0.55rem 0.9rem; border-bottom: 1px solid var(--line);
}
.recent-row:last-child { border-bottom: none; }
.recent-link {
    display: flex; align-items: baseline; gap: 0.75rem; flex-wrap: wrap;
    flex: 1; min-width: 0; text-decoration: none; color: var(--ink);
}
.recent-name { font-weight: 600; }
.recent-result { color: var(--ink-soft); font-size: 0.85rem; }
.watch-link { margin-left: auto; color: var(--accent); font-size: 0.88rem; font-weight: 600; }
.recent-link:hover .recent-name { color: var(--accent); }

@media (max-width: 600px) {
    .hero-quiet h1 { font-size: 1.5rem; }
    .marquee { padding: 1.1rem 1.1rem 1.25rem; }
    .marquee-title { font-size: 1.45rem; }
    /* Drop the muted "pts" column on phones — round-wins is the number that
       decides the game, so leave one unambiguous figure next to the name. */
    .marquee-standings li { grid-template-columns: 1.4rem 1fr auto; gap: 0.55rem; }
    .marquee-standings .ms-score { display: none; }
    /* The hero CTA must be a full-width tap target. .btn (inline-flex) is
       defined later in the file, so qualify the selector to win on source order. */
    .marquee .marquee-cta { display: block; width: 100%; text-align: center; }
    .recent-row { flex-wrap: wrap; }
}

/* Quiet-state replay: on phones the rc-layout collapses to one column (≤620px,
   set in robot_circle_standings.html). Lead with the animated robots — the
   moment that matters — and let the standings rail follow below it. */
@media (max-width: 620px) {
    .home-replay .home-replay-stage { order: -1; }
}

/* ============================================================
 * AGENT LUDUM — components for the marketing page + lobby.
 *
 * Tokens now live in :root (the platform design language, above). `.al` is the
 * marketing front page's local reset/scope; the shared utilities (.btn, .wrap,
 * .pill, .eyebrow, .mono, .al-nav, .al-footer) are global so every page draws
 * the same controls. The live "arena" islands (hero card, leaderboard band, the
 * lobby's live marquee) add `.al-plum` to flip the surface tokens to dark.
 * ============================================================ */
.al {
    background: var(--bg);
    color: var(--ink);
    font-family: var(--al-body);
    font-size: 17px;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
}

/* Plum — the live arena (dark). Same tokens, flipped. */
.al-plum {
    --bg: #3f2f52;
    --bg-2: #372849;
    --surface: #4a3960;
    --ink: #f3edf9;
    --ink-soft: #b6a6c6;
    --line: #574470;
    --line-bold: #574470;
    --brand: #f0843a;
    --brand-2: #b58cf0;
    --accent: #ecc25a;
    --on-brand: #2a2038;
    --hoard: #ecc25a;
    --hurt: #ee7256;
    --help: #5bd193;
    --al-shadow: none;
    --al-shadow-soft: 0 22px 50px -22px rgba(0, 0, 0, 0.6);

    background: var(--bg);
    color: var(--ink);
}

/* ---- AL base + components (all scoped under .al so game pages are untouched) ---- */
.al, .al * { box-sizing: border-box; }
.al { margin: 0; min-height: 100vh; max-width: none; padding: 0; }
.al h1, .al h2, .al h3 {
    font-family: var(--al-display);
    font-weight: 800;
    line-height: 1.04;
    letter-spacing: -0.02em;
    margin: 0;
    text-wrap: balance;
}
.al a { color: inherit; text-decoration: none; }
.al p { margin: 0; }
.mono { font-family: var(--al-mono); }
.wrap { max-width: var(--al-maxw); margin: 0 auto; padding: 0 28px; }
.eyebrow {
    font-family: var(--al-mono); font-size: 12px; font-weight: 700;
    text-transform: uppercase; letter-spacing: 0.12em; color: var(--brand);
}
.al .card { background: var(--surface); border: 2px solid var(--line); border-radius: var(--al-radius-lg); }
.pill {
    display: inline-flex; align-items: center; gap: 8px;
    font-family: var(--al-mono); font-size: 12.5px; font-weight: 700;
    padding: 6px 13px; border-radius: 999px; border: 1.5px solid var(--line);
    color: var(--ink-soft); background: var(--surface);
}
.al .dot { width: 8px; height: 8px; border-radius: 999px; background: var(--brand); display: inline-block; }
.al .dot-help { background: var(--help); }

/* buttons: 2px outline + hard offset shadow on Lilac; flat on Plum */
.btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    font-family: var(--al-body); font-weight: 700; font-size: 14.5px;
    padding: 10px 18px; border-radius: 999px; cursor: pointer;
    border: 2px solid var(--line-bold); background: var(--surface); color: var(--ink);
    box-shadow: var(--al-shadow); transition: transform 0.12s ease, box-shadow 0.12s ease;
    text-decoration: none; /* button-as-link must never underline (interior pages aren't .al-scoped) */
}
.btn:hover { transform: translate(-2px, -2px); box-shadow: 5px 5px 0 var(--line-bold); }
.btn:active { transform: none; box-shadow: var(--al-shadow); }
.btn-primary { background: var(--brand); color: var(--on-brand); }
.btn-ghost { background: transparent; }
.al-plum .btn { box-shadow: none; }
.al-plum .btn:hover { transform: translateY(-2px); box-shadow: none; }
.btn.is-disabled, .btn[aria-disabled="true"] {
    opacity: 0.5; cursor: not-allowed; box-shadow: none;
}
.btn.is-disabled:hover { transform: none; box-shadow: none; }
.al-btn-lg { font-size: 16px; padding: 14px 26px; }
.al-btn-invert { background: var(--on-brand); color: var(--brand); }
.al-btn-on-brand { color: var(--on-brand); border-color: var(--on-brand); background: transparent; }

/* nav */
.al-nav {
    position: sticky; top: 0; z-index: 50;
    background: color-mix(in oklab, var(--bg) 86%, transparent);
    backdrop-filter: blur(10px); border-bottom: 1.5px solid var(--line);
}
.al-nav-inner { display: flex; align-items: center; gap: 18px; height: 70px; }
/* Brand stays pinned left; its auto margin pushes the wayfinding row + right
   group over to the right. Desktop shows the links inline; phones collapse
   them into the single right-corner menu in the mobile block below. */
.al-brand { order: 0; margin-right: auto; }
.al-navlinks { order: 1; }
.al-nav-right { order: 2; }
.al-brand { display: flex; align-items: center; gap: 11px; }
.al-logo { display: block; }
.al-wordmark { font-family: var(--al-display); font-weight: 800; font-size: 21px; letter-spacing: -0.02em; }
.al-navlinks { display: flex; align-items: center; gap: 28px; }
.al-navlinks a { font-size: 13.5px; font-weight: 700; color: var(--ink-soft); }
.al-navlinks a:hover { color: var(--ink); }
.al-nav-right { display: flex; align-items: center; gap: 16px; font-size: 13.5px; font-weight: 700; }
.al-inline-form { display: inline; margin: 0; }
.al-linkbtn { background: none; border: none; font: inherit; color: inherit; cursor: pointer; padding: 0; }
/* Brand + utility links read the same on every page (interior pages would
   otherwise pick up the orange link color). */
.al-brand { color: var(--ink); text-decoration: none; }
.al-nav-right > a:not(.btn) { color: var(--ink-soft); text-decoration: none; }
.al-nav-right > a:not(.btn):hover { color: var(--ink); }

/* Smart "Play" CTA — the single emphasis in the otherwise calm bar, and the
   front door for joining. A compact solid pill (the bar is only 70px tall, so
   it can't use the big .btn). Equal specificity to the link reset above, placed
   after it so the on-brand color wins. */
.al-nav-right a.al-nav-cta {
    display: inline-flex; align-items: center;
    padding: 8px 16px; border-radius: 999px;
    background: var(--brand); color: var(--on-brand); text-decoration: none;
    font-weight: 800; white-space: nowrap;
    border: 2px solid var(--line-bold); box-shadow: var(--al-shadow);
    transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.al-nav-right a.al-nav-cta:hover {
    color: var(--on-brand);
    transform: translate(-1px, -1px); box-shadow: 4px 4px 0 var(--line-bold);
}

/* Account menu — a native <details> dropdown (no JS framework). The avatar is
   the actor's initial; the menu holds everything that used to crowd the bar. */
.al-acct { position: relative; }
.al-acct > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 5px; }
.al-acct > summary::-webkit-details-marker { display: none; }
.al-acct > summary:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; border-radius: 999px; }
.al-acct-ava {
    width: 30px; height: 30px; border-radius: 999px;
    display: grid; place-content: center;
    background: var(--brand); color: var(--on-brand);
    font-family: var(--al-display); font-weight: 800; font-size: 13px;
    border: 2px solid var(--line-bold);
}
.al-acct-caret { color: var(--ink-soft); font-size: 10px; transition: transform 0.15s ease; }
.al-acct[open] .al-acct-caret { transform: rotate(180deg); }
/* The ☰ half of the phone's unified pill. Desktop hides it — there the avatar
   alone is the account trigger, and the wayfinding links sit inline in the bar. */
.al-acct-burger { display: none; font-size: 15px; line-height: 1; color: var(--ink); }
/* The wayfinding group inside the account panel exists for the phone's unified
   menu (see the mobile block); desktop hides it because the same links are
   already visible inline in the bar. */
.al-acct-nav { display: none; }
.al-acct-menu {
    position: absolute; right: 0; top: calc(100% + 12px);
    min-width: 200px; display: flex; flex-direction: column; gap: 1px;
    background: var(--surface); border: 2px solid var(--line-bold);
    border-radius: var(--al-radius); box-shadow: var(--al-shadow-soft);
    padding: 8px; z-index: 60;
}
.al-acct-header {
    padding: 4px 8px 10px;
    border-bottom: 1px solid var(--line); margin-bottom: 4px;
}
.al-acct-ident { font-size: 13px; font-weight: 700; color: var(--ink); word-break: break-all; }
.al-acct-menu a, .al-acct-signout {
    display: flex; align-items: center; justify-content: space-between;
    text-align: left; width: 100%;
    font: inherit; font-size: 13.5px; font-weight: 700; color: var(--ink);
    background: none; border: none; cursor: pointer;
    padding: 8px; border-radius: 8px; text-decoration: none;
}
.al-acct-submenu {
    display: flex;
    flex-direction: column;
    gap: 1px;
}
.al-acct-submenu > summary {
    list-style: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    width: 100%;
    padding: 8px;
    border-radius: 8px;
    font: inherit;
    font-size: 13.5px;
    font-weight: 700;
    color: var(--ink);
    cursor: pointer;
}
.al-acct-submenu > summary::-webkit-details-marker { display: none; }
.al-acct-submenu > summary:hover,
.al-acct-submenu > summary:focus-visible,
.al-acct-submenu[open] > summary { background: var(--bg-2); }
.al-acct-submenu-caret {
    color: var(--ink-soft);
    font-size: 10px;
    transition: transform 0.15s ease;
}
.al-acct-submenu[open] .al-acct-submenu-caret { transform: rotate(90deg); }
.al-acct-submenu-panel {
    display: none;
    flex-direction: column;
    gap: 1px;
    margin: 0 0 2px 8px;
    padding-left: 8px;
    border-left: 1px solid var(--line);
}
.al-acct-submenu:hover > .al-acct-submenu-panel,
.al-acct-submenu:focus-within > .al-acct-submenu-panel,
.al-acct-submenu[open] > .al-acct-submenu-panel { display: flex; }
.al-acct-submenu-panel a {
    padding-left: 10px;
    font-weight: 600;
}
.al-acct-badge {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: 11px; font-weight: 400; color: var(--ink-soft);
}
.al-acct-dot {
    width: 7px; height: 7px; border-radius: 999px;
    background: var(--ink-soft); flex-shrink: 0;
}
.al-acct-badge-live .al-acct-dot { background: #4ade80; }
.al-acct-badge-off .al-acct-dot { background: var(--hurt); }
.al-acct-menu a:hover, .al-acct-signout:hover { background: var(--bg-2); }
.al-acct-form { margin: 4px 0 0; padding: 4px 0 0; border-top: 1px solid var(--line); }
.al-acct-signout { color: var(--hurt); }

/* Wayfinding menu — the wrapper that holds Games / Leaderboard / How it works.
   Desktop keeps this hidden because the links already show inline. On a phone
   (≤560px, below) this becomes the signed-out visitor's single right-corner
   menu; signed-in visitors get the account pill instead and this hides
   entirely (.al-nav-menu-authed). Same native <details> disclosure — no JS. */
.al-nav-menu { position: relative; display: none; align-items: center; }
.al-nav-menu-btn { display: none; }
/* The menu's Sign in item is a phone-only affordance — on desktop, signed-out
   pages keep the bar's own entry (Play pill, or the marketing home's quiet
   "Sign in"), so a second copy inline would be noise. */
.al-nav-menu-signin { display: none; }

/* sections */
.al-section { padding: clamp(64px, 9vw, 120px) 0; }
.al-section-alt { background: var(--bg-2); }
.al-section-head { max-width: 620px; margin-bottom: clamp(32px, 4vw, 52px); }
.al-section-head-row { max-width: none; display: flex; justify-content: space-between; align-items: flex-end; gap: 18px; flex-wrap: wrap; }
.al-h2 { font-size: clamp(30px, 4vw, 50px); margin-top: 14px; }

/* hero */
.al-hero { padding: clamp(18px, 3vw, 36px) 0 clamp(48px, 7vw, 90px); }
.al-hero-viewer { margin-top: clamp(32px, 4vw, 52px); }

/* replay placeholder — shown when no game data exists yet */
.al-rc-ph { max-width: 920px; margin: 0 auto; }
.al-rc-ph-card { background: #fff; border: 1.5px solid var(--line-bold); border-radius: 10px; overflow: hidden; box-shadow: var(--al-shadow-soft); }
.al-rc-ph-head { display: flex; align-items: center; gap: 8px; padding: 10px 14px; border-bottom: 1.5px solid var(--line-bold); background: var(--surface-2); }
.al-rc-ph-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ink-soft); flex: none; }
.al-rc-ph-label { font-size: 12px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-soft); }
.al-rc-ph-stage { height: 430px; display: flex; flex-direction: column; align-items: center; justify-content: center; background: radial-gradient(72% 72% at 50% 44%, #fff 0%, var(--surface) 72%, var(--surface-2) 100%); }
.al-rc-ph-inner { display: flex; flex-direction: column; align-items: center; gap: 10px; border: 2px dashed var(--line); border-radius: 12px; padding: 28px 40px; }
.al-rc-ph-icon { font-size: 28px; color: var(--ink-soft); line-height: 1; }
.al-rc-ph-stage p { color: var(--ink-soft); font-size: 14px; margin: 0; text-align: center; }
@media (max-width: 560px) { .al-rc-ph-stage { height: 260px; } }
.al-h1 { font-size: clamp(40px, 4.8vw, 58px); margin-top: 18px; text-wrap: balance; }
.al-h1-pop { color: var(--brand); }
.al-step p a { color: var(--brand); font-weight: 700; white-space: nowrap; }
.al-sub { font-size: clamp(17px, 1.4vw, 21px); color: var(--ink-soft); margin: 0; max-width: 480px; }
.al-sub-row { display: flex; align-items: center; gap: 24px; margin-top: 20px; }
.al-sub-cta { flex: none; font-size: 18px; padding: 16px 32px; }
.al-cta-row { display: flex; gap: 14px; margin-top: 30px; flex-wrap: wrap; }
.al-cta-center { justify-content: center; }
.al-meta { display: flex; gap: 18px; margin-top: 26px; flex-wrap: wrap; font-size: 12.5px; color: var(--ink-soft); }
.al-diamond { color: var(--brand); }

/* hero match card (Plum) */
.al-matchcard {
    border-radius: var(--al-radius-lg); padding: 22px;
    box-shadow: var(--al-shadow-soft); animation: al-floaty 7s ease-in-out infinite;
}
.al-mc-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 14px; }
.al-mc-tag { color: var(--accent); font-size: 12px; }
.al-mc-name { color: var(--ink-soft); font-size: 12px; }
.al-feed { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 11px; }
.al-move { font-size: 14px; line-height: 1.4; }
.al-arrow { color: var(--ink-soft); }
.al-msg { color: var(--ink-soft); display: block; font-size: 12.5px; margin-top: 2px; }
.al-reason {
    color: var(--ink-soft); display: -webkit-box; -webkit-box-orient: vertical;
    -webkit-line-clamp: 2; overflow: hidden; font-size: 12.5px; font-style: italic;
    margin-top: 3px; line-height: 1.35;
}
.al-chip {
    font-family: var(--al-mono); font-weight: 700; font-size: 11.5px;
    padding: 2px 8px; border-radius: 7px; border: 1.5px solid currentColor;
    margin: 0 2px; white-space: nowrap;
}
.al-chip-hoard { color: var(--hoard); }
.al-chip-hurt { color: var(--hurt); }
.al-chip-help { color: var(--help); }
.al-mc-foot {
    display: flex; flex-wrap: wrap; gap: 8px 14px; margin-top: 16px;
    padding-top: 14px; border-top: 1px solid var(--line); font-size: 12px; color: var(--ink-soft);
}
.al-mc-stand.leader { color: var(--ink); }
.al-mc-rank { color: var(--accent); margin-right: 5px; }
.al-mc-empty { text-align: center; padding: 18px 8px; }
.al-mc-empty p { color: var(--ink-soft); margin: 12px 0 18px; font-size: 14px; }
/* auto-play reveal — hidden only while playing; static otherwise */
.al-feed.is-playing .al-move { opacity: 0; transform: translateY(6px); transition: opacity 0.4s ease, transform 0.4s ease; }
.al-feed.is-playing .al-move.is-shown { opacity: 1; transform: none; }

/* how-it-works */
.al-steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; }
.al-step { padding: 26px; }
.al-step h3 { font-size: 23px; }
.al-step p { color: var(--ink-soft); margin-top: 12px; font-size: 15.5px; }
.al-step-top { display: flex; align-items: center; gap: 12px; margin-bottom: 18px; }
.al-step-n { font-family: var(--al-mono); font-weight: 700; font-size: 14px; color: var(--c); border: 2px solid var(--c); border-radius: 9px; padding: 4px 10px; }
.al-step-rule { flex: 1; height: 2px; background: var(--line); }

/* games grid */
.al-games { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
.al-feature-game { max-width: 440px; margin: 0 auto; }
.al .gamecard { padding: 14px; display: flex; flex-direction: column; transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease; }
.al .gamecard:hover { transform: translateY(-5px); box-shadow: var(--al-shadow-soft); border-color: var(--line-bold); }
.al .gamecard.is-lab { opacity: 0.9; }
.al .gamecard.is-lab:hover { transform: none; box-shadow: none; border-color: var(--line); }
.al-art { position: relative; height: 150px; border-radius: var(--al-radius); border: 2px solid var(--line); overflow: hidden; }
.al-art-hoard { background: repeating-linear-gradient(45deg, #efe4c2, #efe4c2 8px, #e6d6a4 8px, #e6d6a4 16px); }
.al-art-tell { background: repeating-linear-gradient(45deg, #f1d9d3, #f1d9d3 8px, #e9c6bd 8px, #e9c6bd 16px); }
.al-art-holdfast { background: repeating-linear-gradient(45deg, #cfe7d8, #cfe7d8 8px, #b9dcc6 8px, #b9dcc6 16px); }
.al-art-accord { background: repeating-linear-gradient(45deg, #ddd6f3, #ddd6f3 8px, #cabfe9 8px, #cabfe9 16px); }
.al .badge-live {
    position: absolute; right: 12px; top: 12px; display: inline-flex; align-items: center; gap: 5px;
    background: var(--hurt); color: #fff; font-size: 10.5px; font-weight: 700;
    padding: 4px 9px; border-radius: 999px; letter-spacing: 0.06em;
}
.al .badge-live .dot { background: #fff; }
.al .badge-lab {
    position: absolute; right: 12px; top: 12px;
    background: var(--surface); color: var(--ink-soft); border: 1.5px solid var(--line);
    font-size: 10.5px; font-weight: 700; padding: 4px 9px; border-radius: 999px;
}
.al-game-body { padding: 14px 6px 6px; display: flex; flex-direction: column; flex: 1; }
.al-game-meta { display: flex; justify-content: space-between; font-size: 11px; color: var(--ink-soft); text-transform: uppercase; letter-spacing: 0.07em; }
.al-game-body h3 { font-size: 20px; margin-top: 8px; }
.al-game-body p { color: var(--ink-soft); margin-top: 8px; font-size: 14px; flex: 1; }
.al-game-cta { margin-top: 16px; width: 100%; }
.al-games-note { margin-top: 22px; text-align: center; font-size: 12.5px; color: var(--ink-soft); }

/* standings band (Plum) */
.al-band { padding: clamp(64px, 9vw, 120px) 0; }
.al-lb { padding: 0; overflow: hidden; }
.al-lb-row { display: grid; grid-template-columns: 48px 1fr 120px 110px; align-items: center; gap: 10px; padding: 13px 18px; border-top: 1px solid var(--line); }
.al-lb-head { border-top: none; font-size: 11.5px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--ink-soft); }
.al-num { text-align: right; }
.al-lb-row.leader { background: color-mix(in oklab, var(--brand) 12%, var(--surface)); }
.al-lb-rank { display: grid; place-content: center; width: 26px; height: 26px; border-radius: 7px; background: var(--line); color: var(--ink); font-weight: 700; font-size: 13px; }
.al-lb-rank.top { background: var(--accent); color: var(--on-brand); }
.al-lb-name { font-weight: 700; font-size: 15px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.al-lb-cap { text-align: center; margin-top: 18px; font-size: 13px; color: var(--ink-soft); }
.al-lb-empty { text-align: center; padding: 36px 20px; }
.al-lb-empty p { color: var(--ink-soft); margin-bottom: 18px; }

/* Global leaderboard */
.lb-note { color: var(--ink-soft); margin-top: 10px; max-width: 68ch; }
.lb-toolbar {
    margin-bottom: 1.5rem;
    padding: 18px;
    display: flex;
    gap: 18px 24px;
    flex-wrap: wrap;
    align-items: flex-end;
}
.lb-control { display: flex; flex-direction: column; gap: 0.45rem; }
.lb-control-label {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--ink-soft);
}
.lb-section { margin-bottom: 1.5rem; overflow: hidden; }
.lb-section:last-of-type { margin-bottom: 0; }
.lb-table { border-top: 1px solid var(--line); }
.lb-row {
    display: grid;
    grid-template-columns: 56px minmax(0, 1fr) 110px 92px 150px;
    gap: 10px;
    align-items: center;
    padding: 12px 18px;
    border-top: 1px solid var(--line);
}
.lb-head {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ink-soft);
    border-top: none;
    background: var(--surface-2);
}
.lb-row.leader { background: color-mix(in oklab, var(--brand) 10%, var(--surface)); }
.lb-rank {
    display: grid;
    place-content: center;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background: var(--line);
    color: var(--ink);
    font-weight: 700;
    font-size: 13px;
}
.lb-row.leader .lb-rank { background: var(--accent); color: var(--on-brand); }
.lb-name {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.lb-name-main {
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    font-weight: 700;
    font-size: 15px;
}
/* Owner credit under the agent name — present, but quiet. The agent is the
   competitor; the human is the byline. */
.lb-owner {
    font-size: 12px;
    font-weight: 400;
    color: var(--ink-soft);
}
/* Owner credit on the winner card — the earned bragging moment, kept quiet. */
.winner-owner { color: var(--ink-soft); font-weight: 400; }
.lb-num { text-align: right; font-variant-numeric: tabular-nums; }
.lb-last { color: var(--ink-soft); }
.lb-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    font-weight: 700;
    padding: 2px 8px;
    border-radius: 999px;
    border: 1px solid var(--line);
    white-space: nowrap;
}
.lb-tag-sim {
    color: var(--help);
    border-color: color-mix(in srgb, var(--help) 35%, var(--line));
}
.lb-tag-provisional {
    color: var(--brand);
    border-color: color-mix(in srgb, var(--brand) 35%, var(--line));
}
.lb-empty { text-align: center; padding: 36px 20px; }
.lb-empty-note { color: var(--ink-soft); margin-top: 10px; }

/* CTA band */
.al-cta-band { background: var(--brand); border: 2px solid var(--line-bold); border-radius: var(--al-radius-lg); padding: clamp(36px, 5vw, 64px); text-align: center; box-shadow: var(--al-shadow-soft); }
.al-cta-band h2 { color: var(--on-brand); }
.al-cta-band p { color: var(--on-brand); opacity: 0.88; font-size: 18px; margin-top: 14px; max-width: 100%; margin-inline: auto; }

/* footer */
.al-footer { border-top: 1.5px solid var(--line); padding: 54px 0 38px; }
.al-footer-grid { display: grid; grid-template-columns: 1.5fr 1fr 1fr; gap: 32px; }
.al-foot-blurb { font-size: 13px; color: var(--ink-soft); margin-top: 14px; max-width: 280px; }
.al-foot-col { display: flex; flex-direction: column; gap: 10px; }
.al-foot-h { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; color: var(--ink); margin-bottom: 4px; }
.al-foot-col a { font-size: 13.5px; color: var(--ink-soft); }
.al-foot-col a:hover { color: var(--ink); }
.al-footer-bottom { margin-top: 40px; padding-top: 20px; border-top: 1px solid var(--line); display: flex; justify-content: space-between; flex-wrap: wrap; gap: 10px; font-size: 12.5px; color: var(--ink-soft); }

@keyframes al-floaty { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-7px); } }

@media (prefers-reduced-motion: reduce) {
    .al-matchcard { animation: none; }
    .al-feed.is-playing .al-move { opacity: 1; transform: none; }
}

@media (max-width: 900px) {
    .al-steps { grid-template-columns: repeat(2, 1fr); }
    .al-games { grid-template-columns: repeat(2, 1fr); }
    .al-footer-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 560px) {
    .al-navlinks { display: none; }
    .al-nav-menu { display: flex; }
    .al-steps { grid-template-columns: 1fr; }
    .al-games { grid-template-columns: 1fr; }
    .al-footer-grid { grid-template-columns: 1fr; }
    .al-meta { gap: 12px; }
    .al-sub-row { flex-direction: column; align-items: flex-start; }
    .al-sub-cta { width: 100%; text-align: center; }
    .al-cta-row .btn { width: 100%; }
    /* Phones can't hold the full bar, so it narrows to what matters most: the
       brand mark, the Play CTA (.al-nav-cta, the front door), and exactly ONE
       menu in the right corner. Signed in, that menu is the account pill
       (☰ + avatar) and it carries the wayfinding links too; signed out it's
       the plain ☰ with Sign in folded in. Account stuff lives top-right by
       convention, so the merged menu lives there — and it matches where the
       desktop avatar menu already sits. */
    /* Signed in: the account pill is the one menu, so the ☰ <details> goes. */
    .al-nav-menu-authed { display: none; }
    /* Signed out: the ☰ takes the same right-corner spot the pill would hold. */
    .al-nav-menu { order: 3; }
    .al-nav-menu-btn {
        display: inline-flex; align-items: center; justify-content: center;
        list-style: none; cursor: pointer;
        width: 38px; height: 38px; border-radius: 999px;
        border: 2px solid var(--line-bold); background: var(--surface);
        font-size: 16px; line-height: 1; color: var(--ink);
    }
    .al-nav-menu-btn::-webkit-details-marker { display: none; }
    .al-nav-menu-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
    .al-nav-menu:not([open]) > .al-nav-menu-panel { display: none; }
    .al-nav-menu[open] > .al-nav-menu-panel {
        display: flex;
        position: absolute; right: 0; top: calc(100% + 12px);
        flex-direction: column; align-items: stretch; gap: 1px;
        min-width: 200px; z-index: 60;
        background: var(--surface); border: 2px solid var(--line-bold);
        border-radius: var(--al-radius); box-shadow: var(--al-shadow-soft);
        padding: 8px;
    }
    .al-nav-menu[open] > .al-nav-menu-panel a {
        padding: 12px 10px; border-radius: 8px; font-size: 13.5px; color: var(--ink);
    }
    .al-nav-menu[open] > .al-nav-menu-panel a:hover { background: var(--bg-2); }
    /* Sign in joins the signed-out menu, set off from wayfinding by a rule. */
    .al-nav-menu[open] > .al-nav-menu-panel .al-nav-menu-signin {
        display: flex; margin-top: 4px; padding-top: 12px;
        border-top: 1px solid var(--line); border-radius: 0 0 8px 8px;
    }
    /* …so the bar's own Sign in (marketing home) hides — one entry, not two. */
    .al-nav-right .al-nav-auth { display: none; }
    /* The unified pill: ☰ + avatar in one bordered control, telling the thumb
       that both site nav and account live here. */
    .al-acct > summary {
        gap: 8px; padding: 2px 2px 2px 12px;
        border: 2px solid var(--line-bold); border-radius: 999px;
        background: var(--surface);
    }
    .al-acct-burger { display: inline-flex; }
    .al-acct-caret { display: none; }
    /* Wayfinding group inside the pill's panel — navigation first (it's the
       most frequent action), then a rule before the account items. */
    .al-acct-nav {
        display: flex; flex-direction: column; gap: 1px;
        padding-bottom: 4px; margin-bottom: 4px;
        border-bottom: 1px solid var(--line);
    }
    /* Comfortable thumb targets (~44px) for every menu row on a phone. */
    .al-acct-menu a, .al-acct-signout { padding: 12px 10px; }
    .al-acct-submenu > summary { padding: 12px 10px; }
    .al-acct-submenu-panel { margin-left: 4px; padding-left: 6px; }
    /* Drop the nav brand to the logo mark on a phone so the CTA + auth never get
       crowded off the bar. The footer keeps the full wordmark. */
    .al-nav-inner .al-wordmark { display: none; }
    .al-lb-row { grid-template-columns: 40px 1fr 90px; }
    .al-lb-row > .al-num:last-child, .al-lb-head > span:last-child { display: none; }
    .lb-toolbar { padding: 14px; }
    .lb-row { grid-template-columns: 40px minmax(0, 1fr) 86px; }
    .lb-row > .lb-num:nth-child(4), .lb-row > .lb-last, .lb-head > .lb-matches, .lb-head > .lb-last { display: none; }
}

/* ── Admin: Add Sims ───────────────────────────────────────────────────────
   The roster builder. A small, calm set of controls: quick-add packs, a
   per-personality stepper, and the live roster of seats being added. */
.notice-ok {
    color: var(--help);
    background: color-mix(in srgb, var(--help) 10%, var(--surface));
    border: 1px solid color-mix(in srgb, var(--help) 35%, var(--line));
    border-radius: 8px;
    padding: 0.6rem 0.8rem;
    margin: 0.5rem 0;
}
.admin-actions { margin: 0.5rem 0 1rem; }
.muted { color: var(--ink-soft); }
.tag-sim { color: var(--accent); background: color-mix(in srgb, var(--accent) 16%, transparent); }

.sims-section { margin: 1.5rem 0; }
.sims-section h2 { margin: 0 0 0.5rem; }

.sims-pack-row { display: flex; flex-wrap: wrap; gap: 0.5rem; }

/* The action-lean dot: cooperative / aggressive / self, by colour + position. */
.lean-dot {
    display: inline-block;
    width: 9px; height: 9px;
    border-radius: 50%;
    background: var(--ink-soft);
    vertical-align: middle;
}
.lean-help { background: var(--help); }
.lean-hurt { background: var(--hurt); }
.lean-hoard { background: var(--hoard); }

.sims-personality-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.4rem; }
.sims-personality {
    display: grid;
    grid-template-columns: minmax(9rem, auto) 1fr auto;
    align-items: center;
    gap: 0.4rem 0.85rem;
    padding: 0.55rem 0.7rem;
    border: 1.5px solid var(--line);
    border-radius: 8px;
    background: var(--surface);
}
.sims-p-head { display: inline-flex; align-items: center; gap: 0.45rem; }
.sims-p-name { font-weight: 600; }
.sims-p-desc { color: var(--ink-soft); font-size: 0.85rem; }

.stepper { display: inline-flex; align-items: center; gap: 0.5rem; }
.stepper button {
    width: 1.9rem; height: 1.9rem;
    border: 1.5px solid var(--line-bold);
    background: var(--surface);
    border-radius: 6px;
    font-size: 1.05rem; line-height: 1;
    cursor: pointer;
}
.stepper button:hover { background: var(--surface-2); }
.stepper button:disabled { opacity: 0.4; cursor: not-allowed; }
.step-count { min-width: 1.4rem; text-align: center; font-variant-numeric: tabular-nums; }

.sims-legend {
    display: flex; flex-wrap: wrap; gap: 1rem;
    color: var(--ink-soft); font-size: 0.8rem; margin: 0.6rem 0 0;
}
.sims-legend > span { display: inline-flex; align-items: center; gap: 0.35rem; }

.sims-roster-list { display: grid; gap: 0.4rem; }
.sims-seat {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: 0.6rem;
    padding: 0.4rem 0.6rem;
    border: 1.5px solid var(--line);
    border-radius: 8px;
    background: var(--surface);
}
.sims-seat .seat-name {
    font: inherit;
    padding: 0.3rem 0.5rem;
    border: 1.5px solid var(--line);
    border-radius: 6px;
    max-width: 12rem;
}
.seat-personality { color: var(--ink-soft); font-size: 0.9rem; }
.seat-remove {
    border: none; background: transparent;
    color: var(--hurt); font-size: 1rem; line-height: 1; cursor: pointer;
}

@media (max-width: 560px) {
    .sims-personality { grid-template-columns: 1fr auto; }
    .sims-p-desc { grid-column: 1 / -1; }
}

/* Join picker — agents grouped by provider, connected providers first. */
.provider-group { margin-bottom: 1rem; }
.provider-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
    padding-bottom: 0.5rem;
    margin-bottom: 0.25rem;
    border-bottom: 1px solid var(--line);
}
.provider-name { font-weight: 600; }
.provider-status {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.85rem;
}
.provider-status .dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; display: inline-block; }
.provider-status.status-live { color: var(--help); }
.provider-status.status-live .dot { animation: hhh-pulse 1.4s ease-in-out infinite; }
.provider-status.status-off { color: var(--ink-soft); }
.provider-group.provider-offline,
.provider-group.provider-unconfigured { opacity: 0.92; }
.agent-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.55rem 0;
    margin: 0;
    border-top: 1px solid var(--line);
}
.agent-row:first-of-type { border-top: 0; }
.agent-row-name { font-weight: 500; }
.agent-row-model { color: var(--ink-soft); font-family: var(--font-mono); font-weight: 400; }

/* Post-join connect countdown. */
.seat-countdown { text-align: center; margin: 0.5rem 0 1rem; }
.seat-countdown-time {
    display: block;
    font-family: var(--font-mono);
    font-size: 2.4rem;
    line-height: 1;
    color: var(--ink);
}
.seat-countdown-label { font-size: 0.8rem; color: var(--ink-soft); }
