    *, *::before, *::after {
      box-sizing: border-box; margin: 0; padding: 0;
      -webkit-tap-highlight-color: transparent;  /* kill iOS grey flash on tap */
    }
    button, .glass-btn, .send-btn { touch-action: manipulation; }  /* disable double-tap-to-zoom delay */

    :root {
      /* Brand surfaces — see reference/brand.jsx BRAND */
      --bg:         #000000;
      --surface:    #141414;
      --card:       #141414;
      --border:     rgba(255,255,255,0.06);
      --border-mid: rgba(255,255,255,0.12);
      --white:      #ffffff;
      --text:       #F5F5F5;
      --text-dim:   #8C8C8C;
      --text-faint: #5A5A5A;
      --muted:      rgba(255,255,255,0.55);

      /* Per-round palette — reference/brand.jsx THEME.
         PLAY = orange, UNITE = lime, EMPOWER = cyan. */
      --play-accent:    #FF6701;
      --play-soft:      #C24E00;
      --unite-accent:   #BEFF00;
      --unite-soft:     #8CC400;
      --empower-accent: #00FFFF;
      --empower-soft:   #00B8B8;

      /* Team palette — reference/brand.jsx TEAM.
         DB/OSC identifiers stay 'RED' / 'BLUE'; these are display-only.
         _teamColorVar() maps 'RED' → --team-red, 'BLUE' → --team-purple. */
      --team-red:        #F23B3B;
      --team-red-soft:   #B02828;
      --team-purple:     #A855F7;
      --team-purple-soft:#7B2FF2;

      /* Legacy aliases — kept so the brand mark and a few stable surfaces
         (status-bar idle dot etc.) keep reading even when no round is active.
         New code should prefer --accent (round-bound) over --lime. */
      --lime:       var(--unite-accent);
      --lime-soft:  var(--unite-soft);
      --coral:      #E84A2C;
      --cyan:       var(--empower-accent);

      /* Type system — reference/brand.jsx FONT (sans-only; the old Charter serif
         was dropped from the brand). --narrative now resolves to the body sans;
         the var name is kept so its many consumers don't need touching. */
      --display:    'obviously-wide', sans-serif;
      --mono:       'mono45-headline', monospace;
      --narrative:  'neue-haas-grotesk-text', 'Helvetica Neue', Helvetica, Arial, sans-serif;
      --radius:     0px;

      /* Default round binding — idle / intro screens fall back to brand lime. */
      --accent:      var(--unite-accent);
      --accent-soft: var(--unite-soft);
      --accent-text: #000;
    }

    /* Round theming — set by JS as `document.body.dataset.round = '1' | '2' | '3'`
       on phase transitions, cleared on idle / introduction / movie / ending.
       Every UI highlight inside a round (chat bubbles, send button, status dot,
       timer, mini-game chrome, declaration card) reads --accent. */
    body[data-round="1"] {
      --accent:      var(--play-accent);
      --accent-soft: var(--play-soft);
      --accent-text: #000;
    }
    body[data-round="2"] {
      --accent:      var(--unite-accent);
      --accent-soft: var(--unite-soft);
      --accent-text: #000;
    }
    body[data-round="3"] {
      --accent:      var(--empower-accent);
      --accent-soft: var(--empower-soft);
      --accent-text: #000;
    }

    html, body {
      height: 100%;
      font-family: 'neue-haas-grotesk-text', sans-serif;
      background: var(--bg);
      color: var(--white);
    }

    /* ── Background canvas ── */
    #particles {
      position: fixed; top: 0; left: 0; width: 100%; height: 100%;
      pointer-events: none; z-index: 0;
    }

    /* Step label — tiny mono eyebrow on game screens.
       Set via setStepLabel() in JS; hidden by default. */
    #step-label {
      position: fixed; top: 28px;
      left: 0; right: 0;
      text-align: center;
      font-family: var(--mono);
      font-size: 10px;
      letter-spacing: 0.18em;
      color: var(--text-faint);
      text-transform: uppercase;
      z-index: 19;
      pointer-events: none;
      opacity: 0; transition: opacity 0.4s ease;
    }
    #step-label.visible { opacity: 1; }

    /* ── App shell ── */
    #app {
      position: fixed; top: 0; left: 0; right: 0; bottom: 0;
      z-index: 10; padding-top: 80px;
      display: flex; flex-direction: column;
      background: transparent;
    }
    /* Chat screen reclaims the top reserve so bubbles scroll behind the fixed
       timer overlay (their own padding-top clears the pill). Other screens keep 80px. */
    #app:has(#screen-chat.active) { padding-top: 0; }

    /* ── Screens ── */
    .chat-screen {
      flex: 1; min-height: 0; display: none;
      flex-direction: column; justify-content: center; align-items: center;
      padding: 24px 20px; gap: 16px;
    }
    .chat-screen.active { display: flex; }
    #screen-chat { justify-content: flex-start; align-items: stretch; padding: 0; min-height: 0; }
    #screen-processing { overflow-y: auto; -webkit-overflow-scrolling: touch; justify-content: flex-start; padding-top: 16px; }

    /* ── Cards ── */
    .glass {
      background: var(--surface);
      border: 1px solid var(--border);
    }
    .glass-card {
      max-width: 340px; width: 92%;
      padding: 28px 24px;
      text-align: center;
      font-size: 14px; line-height: 1.6; color: var(--white);
      background: var(--surface);
      border: 1px solid var(--border);
    }

    /* ── Pop animations ── */
    @keyframes pop-in {
      0%   { transform: scale(0.88) translateY(8px); opacity: 0; }
      65%  { transform: scale(1.02) translateY(-2px); opacity: 1; }
      100% { transform: scale(1)    translateY(0);    opacity: 1; }
    }
    @keyframes pop-out {
      0%   { transform: scale(1);    opacity: 1; }
      100% { transform: scale(0.92) translateY(4px); opacity: 0; }
    }
    .glass-card { animation: pop-in 0.38s cubic-bezier(0.34, 1.4, 0.64, 1) both; }

    /* ── Value label (PLAY / UNITE / EMPOWER) ── */
    .value-label {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 52px;
      color: var(--accent);
      letter-spacing: 0.06em;
      line-height: 1;
      display: block;
      margin-bottom: 8px;
    }

    /* ── Chat ── */
    .chat-messages {
      flex: 1; min-height: 0;
      overflow-y: auto; -webkit-overflow-scrolling: touch;
      overscroll-behavior: contain;
      touch-action: pan-y;
      padding: 72px 16px 20px; display: flex; flex-direction: column; gap: 12px;
      transition: opacity 0.7s ease;
    }
    .msg {
      max-width: 82%; padding: 12px 16px;
      font-size: 15px; line-height: 1.55;
      animation: pop-in 0.35s cubic-bezier(0.34, 1.4, 0.64, 1) both;
    }
    .msg-host {
      align-self: flex-start;
      background: var(--surface);
      border: 1px solid var(--border);
      border-radius: 2px 12px 12px 12px;
      color: var(--white);
    }
    .msg-user {
      align-self: flex-end;
      background: var(--accent);
      border-radius: 12px 2px 12px 12px;
      color: var(--accent-text);
      font-weight: 500;
    }
    /* Personal declaration — the agent's stage_complete closer, rendered as
       a framed takeaway card (the "your declaration" moment). The chat above
       dims via .chat-dimmed so the card reads as the focal point. */
    .msg-declaration {
      align-self: stretch;
      max-width: 100%;
      position: relative;
      padding: 20px 22px 18px;
      margin-top: 8px;
      background: #0E0E0E;
      border: 1.5px solid var(--decl-color, var(--accent));
      border-radius: 0;
      color: var(--white);
      box-shadow: 0 0 30px color-mix(in srgb, var(--decl-color, var(--accent)) 14%, transparent),
                  0 -20px 40px rgba(0, 0, 0, 0.6);
      animation: pop-in 0.5s cubic-bezier(0.34, 1.4, 0.64, 1) both;
    }
    /* Corner bracket ticks — eight 2px bars, painted with the round color */
    .msg-declaration .decl-tick {
      position: absolute;
      background: var(--decl-color, var(--accent));
      pointer-events: none;
    }
    .msg-declaration .decl-tick.tl-h { top: 0; left: 0; width: 10px; height: 2px; }
    .msg-declaration .decl-tick.tl-v { top: 0; left: 0; width: 2px; height: 10px; }
    .msg-declaration .decl-tick.tr-h { top: 0; right: 0; width: 10px; height: 2px; }
    .msg-declaration .decl-tick.tr-v { top: 0; right: 0; width: 2px; height: 10px; }
    .msg-declaration .decl-tick.bl-h { bottom: 0; left: 0; width: 10px; height: 2px; }
    .msg-declaration .decl-tick.bl-v { bottom: 0; left: 0; width: 2px; height: 10px; }
    .msg-declaration .decl-tick.br-h { bottom: 0; right: 0; width: 10px; height: 2px; }
    .msg-declaration .decl-tick.br-v { bottom: 0; right: 0; width: 2px; height: 10px; }
    .msg-declaration .decl-head {
      display: flex; align-items: center; gap: 8px;
      margin-bottom: 10px;
    }
    .msg-declaration .decl-head-dot {
      width: 7px; height: 7px;
      background: var(--decl-color, var(--accent));
      flex-shrink: 0;
    }
    .msg-declaration .decl-label {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 12px;
      letter-spacing: 0.16em;
      color: var(--decl-color, var(--accent));
      text-transform: uppercase;
    }
    .msg-declaration .decl-body {
      /* Narrative voice — body sans (the brand dropped the Charter serif). */
      font-family: var(--narrative);
      font-weight: 500;
      font-size: 22px;
      line-height: 1.32;
      letter-spacing: 0.005em;
      color: var(--white);
    }
    .msg-declaration .decl-footer {
      margin-top: 14px;
      display: flex; justify-content: space-between;
      font-family: 'mono45-headline', monospace;
      font-size: 10px;
      letter-spacing: 0.14em;
      color: var(--text-faint);
    }

    /* When the declaration card appears, the prior chat dims into a "ghost
       thread" — bubbles fade, the card stays full opacity. */
    .chat-messages.chat-dimmed .msg:not(.msg-declaration) {
      opacity: 0.45;
      transition: opacity 0.6s ease;
    }

    /* ── End-of-show recap: "TONIGHT YOU SAID —" + three colored cards ── */
    #screen-personal-recap {
      justify-content: flex-start; align-items: stretch;
      padding: 0; gap: 0;
    }
    .recap-scroll {
      flex: 1; min-height: 0;
      overflow-y: auto; -webkit-overflow-scrolling: touch;
      padding: 16px 16px 12px;
    }
    .recap-header { margin-bottom: 18px; padding-top: 4px; }
    .recap-title {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 36px; line-height: 0.98;
      color: var(--white);
      letter-spacing: -0.005em;
      text-transform: uppercase;
    }
    .recap-said {
      color: var(--lime);
      position: relative;
      display: inline-block;
    }
    .recap-said-underline {
      position: absolute; bottom: -6px; left: 0;
      width: 70px; height: 10px;
    }
    .recap-sub {
      margin-top: 12px;
      font-size: 12px; line-height: 1.45;
      color: var(--muted);
      max-width: 280px;
    }
    .recap-cards {
      display: flex; flex-direction: column; gap: 10px;
    }
    .recap-loading {
      font-size: 13px; color: var(--muted);
      text-align: center; padding: 24px 0;
    }
    .decl-card {
      position: relative;
      display: flex;
      background: #0E0E0E;
      border: 1px solid var(--border-mid);
      overflow: hidden;
      min-height: 140px;
    }
    .decl-card-stripe {
      width: 4px; flex-shrink: 0;
      background: var(--card-color, var(--lime));
    }
    .decl-card-body {
      flex: 1; min-width: 0;
      padding: 14px 16px;
      display: flex; flex-direction: column; gap: 8px;
      position: relative; z-index: 1;
    }
    .decl-card-meta {
      display: flex; justify-content: space-between; align-items: baseline;
      font-family: 'mono45-headline', monospace;
      font-size: 9px; letter-spacing: 0.16em;
    }
    .decl-card-meta .decl-card-idx {
      color: var(--card-color, var(--lime));
    }
    .decl-card-meta .decl-card-your {
      color: var(--text-faint);
      letter-spacing: 0.14em;
    }
    .decl-card-keyword {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 40px; line-height: 0.9;
      color: var(--card-color, var(--lime));
      letter-spacing: -0.012em;
      text-transform: uppercase;
    }
    .decl-card-sentence {
      /* Narrative voice — same body sans as the in-round declaration card. */
      font-family: var(--narrative);
      font-weight: 500;
      font-size: 14px;
      line-height: 1.4;
      color: var(--white);
    }
    .decl-card-sentence.is-missing {
      color: var(--muted);
      font-style: italic;
    }
    .decl-card-watermark {
      position: absolute;
      right: -6px; bottom: -28px;
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 110px; line-height: 0.85;
      color: var(--card-color, var(--lime));
      opacity: 0.07;
      letter-spacing: -0.04em;
      text-transform: uppercase;
      pointer-events: none;
      z-index: 0;
    }
    .recap-footer {
      flex-shrink: 0;
      margin: 0 16px;
      margin-bottom: max(16px, env(safe-area-inset-bottom));
      padding: 12px 16px;
      background: rgba(20, 20, 20, 0.92);
      border: 1px solid var(--border-mid);
      display: flex; align-items: center; justify-content: space-between;
      gap: 12px;
    }
    .recap-footer-text { min-width: 0; }
    .recap-footer-title {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 14px; letter-spacing: 0.07em;
      color: var(--lime);
      text-transform: uppercase;
    }
    .recap-footer-sub {
      font-size: 11px; color: var(--muted);
      margin-top: 2px;
      line-height: 1.35;
    }
    .recap-share-btn {
      flex-shrink: 0;
      padding: 11px 18px;
      background: var(--lime);
      border: none; border-radius: 0;
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 14px; letter-spacing: 0.09em;
      color: #000;
      text-transform: uppercase;
      cursor: pointer;
    }
    .recap-share-btn:disabled { opacity: 0.5; cursor: not-allowed; }
    .recap-share-btn:active { transform: translateY(1px); }

    /* ── Input area ── */
    #input-area {
      flex-shrink: 0;
      padding: 10px 16px;
      padding-bottom: max(12px, env(safe-area-inset-bottom));
      background: var(--bg);
      border-top: 1px solid var(--border);
      transition: opacity 0.7s ease;
    }
    /* Card-filled input row matching the onboarding form-card pattern.
       Reference: onboarding-chat.jsx ChatScreen input block. */
    .input-row {
      display: flex; gap: 8px; align-items: stretch;
    }
    .glass-input {
      flex: 1;
      padding: 14px 16px;
      background: var(--surface);
      border: 1px solid var(--border-mid);
      color: var(--white);
      font-size: 16px; font-family: 'neue-haas-grotesk-text', sans-serif;
      outline: none;
      caret-color: var(--accent);
    }
    .glass-input::placeholder { color: var(--text-dim); }
    .send-btn {
      width: 52px; flex-shrink: 0;
      background: var(--accent); border: none; color: var(--accent-text); cursor: pointer;
      display: flex; align-items: center; justify-content: center;
    }
    .send-btn:hover { filter: brightness(1.1); }
    .send-btn:disabled { opacity: 0.3; cursor: not-allowed; }

    /* ── Multiple choice buttons ── */
    .glass-btn {
      width: 100%; padding: 14px 12px;
      background: var(--surface);
      border: 1px solid var(--border);
      color: var(--white);
      font-size: 14px; font-family: 'neue-haas-grotesk-text', sans-serif;
      cursor: pointer;
      transition: background 0.15s, color 0.15s, border-color 0.15s;
      text-align: center;
    }
    .glass-btn:hover:not(:disabled) {
      background: var(--accent);
      color: var(--accent-text);
      border-color: var(--accent);
    }
    .glass-btn:disabled { opacity: 0.4; cursor: not-allowed; }

    /* ── Slider ── */
    input[type=range] { accent-color: var(--accent); width: 100%; height: 32px; }

    /* ── Thinking dots ── */
    .thinking-dots { display: inline-flex; gap: 5px; align-items: center; }
    .thinking-dots span {
      width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
      animation: dot-pulse 1.4s ease-in-out infinite;
    }
    .thinking-dots span:nth-child(2) { animation-delay: 0.2s; }
    .thinking-dots span:nth-child(3) { animation-delay: 0.4s; }
    @keyframes dot-pulse {
      0%,80%,100% { transform: scale(0.65); opacity: 0.3; }
      40%          { transform: scale(1);    opacity: 1;   }
    }

    /* Timer pill: see #chat-timer in the onboarding section (structured ChatTimer
       with circular progress ring + MM:SS + thin horizontal bar). */

    /* Name entry: full-bleed overlay (.ob-overlay) — see onboarding section below. */

    /* ── Reveal card ── */
    .reveal-selected {
      border-color: var(--accent) !important;
    }
    .reveal-icon {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 40px;
      color: var(--accent);
      margin-bottom: 12px;
      display: block;
    }

    /* ── Contribution cards ── */
    .contrib-card {
      padding: 16px;
      margin-bottom: 10px;
      background: var(--surface);
      border: 1px solid var(--border);
    }
    .contrib-card.selected {
      border-color: var(--accent);
    }
    .contrib-round-label {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 18px;
      color: var(--accent);
      letter-spacing: 0.08em;
      margin-bottom: 6px;
    }

    /* ── Muted label ── */
    .muted-label { color: var(--muted); font-size: 13px; text-align: center; padding: 12px 0; }

    /* ── Stats notif (kept for compatibility, styled to 3x3) ── */
    #stats-notif {
      position: fixed;
      top: 20px; left: 50%; transform: translateX(-50%);
      z-index: 300;
      width: min(90vw, 320px);
      padding: 20px 24px;
      background: var(--surface);
      border: 1px solid var(--accent);
      text-align: center;
      pointer-events: none;
      opacity: 0; transition: opacity 0.35s ease;
    }
    #stats-notif.visible { opacity: 1; }
    .sn-icon  { font-size: 28px; margin-bottom: 8px; color: var(--accent); }
    .sn-title { font-family: 'obviously-wide', sans-serif; font-weight: 700; font-size: 22px; color: var(--white); margin-bottom: 4px; letter-spacing: 0.06em; }
    .sn-sub   { font-size: 12px; color: var(--muted); line-height: 1.4; }

    /* ── Waiting message ── */
    #waiting-message { font-size: 13px; color: var(--muted); }
    #waiting-message strong { color: var(--white); }

    /* ── Mini-game ── */
    #screen-game {
      /* Fixed + inset:0 so the game fills the whole viewport (reclaims the 80px
         #app top padding) — the hoop/ball/scoreboard top-align instead of sitting
         in a black band. Opaque bg keeps the game on pure black (no ambient
         particles bleeding through). */
      position: fixed; inset: 0;
      background: var(--bg);
      touch-action: none;
      user-select: none;
      -webkit-user-select: none;
      overflow: hidden;
    }
    /* p5.js canvas host for PLAY + UNITE-B (Messenger-style swipe-up mechanic).
       Display toggled by JS when a sketch mounts. z-index sits below all HUDs
       (#game-team-progress z:5, #unite-pass-phase, drop screen) and below the
       legacy DOM rig (which is hidden via display:none when p5 mode is active). */
    #p5-game-host {
      position: absolute; inset: 0;
      display: none;
      touch-action: none;
      z-index: 1;
    }
    #p5-game-host canvas {
      display: block;
      width: 100% !important; height: 100% !important;
    }
    /* Hoop SVG container. PLAY mini-game: drag the ball back, slingshot it up into
       this hoop. Position is fixed near the top so the aim arc has somewhere to
       point. */
    #game-hoop {
      position: absolute;
      left: 50%; top: 210px;
      transform: translateX(-50%);
      width: 168px; height: 96px;
      pointer-events: none;
      display: none;
      z-index: 3;
    }
    #game-hoop svg { width: 100%; height: 100%; overflow: visible; }
    #game-circle {
      position: absolute;
      left: 50%;
      bottom: 18%;
      width: 92px; height: 92px;
      background: url('/ball.png') center/contain no-repeat;
      cursor: grab;
      --gb-x: 0px; --gb-y: 0px;
      transform: translateX(calc(-50% + var(--gb-x))) translateY(var(--gb-y));
      display: none;
      z-index: 6;
      will-change: transform, opacity;
      transition: transform 0.12s ease-out;
    }
    /* PLAY swipe-hint overlay — small "SWIPE TO SHOOT ↑" label + bobbing
       chevrons just above the resting ball. Shown only during PLAY idle. */
    #play-swipe-hint {
      position: absolute;
      left: 50%; bottom: calc(14% + 60px);
      transform: translateX(-50%);
      display: none;
      flex-direction: column; align-items: center; gap: 6px;
      pointer-events: none;
      z-index: 5;
      opacity: 0.85;
    }
    #play-swipe-hint.visible { display: flex; }
    #play-swipe-hint .psh-label {
      font-family: var(--mono); font-size: 11px;
      letter-spacing: 0.22em; color: var(--text-faint);
      text-transform: uppercase;
    }
    #play-swipe-hint .psh-chev {
      width: 22px; height: 14px;
      animation: chev-bob 1.2s ease-in-out infinite;
    }
    #play-swipe-hint .psh-chev:nth-child(3) { animation-delay: 0.18s; opacity: 0.5; }
    @keyframes chev-bob {
      0%, 100% { transform: translateY(2px); opacity: 0.4; }
      50%      { transform: translateY(-4px); opacity: 1; }
    }
    #game-circle.dragging { cursor: grabbing; transition: none; }
    #game-circle.flying   { transition: none; z-index: 8; }
    /* Power ring around the ball during drag. */
    #game-power-ring {
      position: absolute;
      left: 50%; bottom: 18%;
      width: 124px; height: 124px;
      margin-left: -62px; margin-bottom: -16px;
      pointer-events: none;
      display: none;
      z-index: 5;
    }
    /* Slingshot anchor — dashed ring marking where the ball rests. */
    #game-anchor {
      position: absolute;
      left: 50%; bottom: 18%;
      width: 116px; height: 116px;
      margin-left: -58px; margin-bottom: -12px;
      border-radius: 50%;
      border: 1.5px dashed rgba(255,255,255,0.18);
      pointer-events: none;
      display: none;
      z-index: 4;
    }
    /* Aim arc preview SVG layer covering the full screen. */
    #game-aim-arc {
      position: absolute;
      inset: 0;
      pointer-events: none;
      display: none;
      z-index: 5;
    }
    /* Swish flash — brief lime glow on the hoop after a hit. */
    #game-hoop.swish { animation: hoop-swish 0.6s ease-out; }
    @keyframes hoop-swish {
      0%   { filter: drop-shadow(0 0 0 transparent); }
      30%  { filter: drop-shadow(0 0 24px var(--accent)); }
      100% { filter: drop-shadow(0 0 0 transparent); }
    }
    #game-circle.dragging { cursor: grabbing; }
    /* PLAY: ball snapping back to anchor after release (the JS sets transition
       on release and tweens --gb-x/--gb-y back to 0). The .snapback class just
       softens the spring feel. */
    #game-circle.snapback { transition: transform 0.22s cubic-bezier(0.34, 1.5, 0.64, 1); }
    /* PLAY: miss feedback — quick wobble + dim. */
    @keyframes ball-miss {
      0%, 100% { filter: none; }
      50%      { filter: brightness(0.6); }
    }
    .ball-miss-anim { animation: ball-miss 0.45s ease-out; }
    /* PLAY: new ball pops into the circle after the thrown ball exits the screen. */
    @keyframes ballSpawn {
      0%   { opacity: 0; transform: translateX(calc(-50% + var(--gb-x))) translateY(var(--gb-y)) scale(0.1); }
      70%  { opacity: 1; transform: translateX(calc(-50% + var(--gb-x))) translateY(var(--gb-y)) scale(1.12); }
      100% { opacity: 1; transform: translateX(calc(-50% + var(--gb-x))) translateY(var(--gb-y)) scale(1); }
    }
    #game-circle.ball-spawn { animation: ballSpawn 0.32s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; }
    /* UNITE: incoming ball rises from off-screen bottom into the centred resting
       position. Distance + duration are JS-tunable via inline style; this is the
       base curve only. */
    @keyframes ball-incoming {
      0%   { transform: translateX(-50%) translateY(80vh) scale(0.55); opacity: 0; }
      40%  { opacity: 1; }
      100% { transform: translateX(-50%) translateY(0)    scale(1);    opacity: 1; }
    }
    .ball-incoming-anim { animation: ball-incoming 0.55s cubic-bezier(0.2, 0.7, 0.3, 1) forwards; }
    /* UNITE catch zone pulse when active. Uses the round accent so it
       reads as UNITE lime — but stays correct if UNITE's color ever shifts. */
    @keyframes catch-zone-pulse {
      0%, 100% { box-shadow: 0 0 20px color-mix(in srgb, var(--accent) 18%, transparent); }
      50%       { box-shadow: 0 0 52px color-mix(in srgb, var(--accent) 55%, transparent); }
    }
    .catch-zone-active { animation: catch-zone-pulse 0.9s ease-in-out infinite; }
    /* PLAY team progress bar at the top — shows both teams' running totals racing
       toward PLAY_WIN_THRESHOLD (100 by default). */
    #game-team-progress {
      position: absolute;
      top: max(env(safe-area-inset-top), 16px); left: 50%;
      transform: translateX(-50%);
      width: min(90%, 380px);
      display: none;
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      letter-spacing: 0.08em;
      pointer-events: none;
      z-index: 5;
    }
    #game-team-progress .gtp-row {
      display: flex; justify-content: space-between;
      font-size: 24px; margin-bottom: 8px;
    }
    #game-team-progress .gtp-red  { color: var(--team-red); }
    #game-team-progress .gtp-blue { color: var(--team-purple); }
    #game-team-progress .gtp-bar {
      position: relative; height: 6px;
      background: rgba(255,255,255,0.12); border-radius: 3px; overflow: visible;
    }
    #game-team-progress .gtp-fill-red {
      position: absolute; left: 0; top: 0; bottom: 0;
      min-width: 4px;
      background: var(--team-red);
      box-shadow: 0 0 10px var(--team-red);
      border-radius: 3px;
      transition: width 0.18s ease-out;
    }
    #game-team-progress .gtp-fill-blue {
      position: absolute; right: 0; top: 0; bottom: 0;
      min-width: 4px;
      background: var(--team-purple);
      box-shadow: 0 0 10px var(--team-purple);
      border-radius: 3px;
      transition: width 0.18s ease-out;
    }
    /* Confetti rain — generated as 26 absolutely-positioned divs in JS.
       Shared by #screen-reveal on win. */
    .mw-confetti-layer {
      position: absolute; inset: 0;
      pointer-events: none; overflow: hidden;
      z-index: 5;
    }
    .mw-confetti {
      position: absolute; top: -20px;
      opacity: 0.85;
      animation: mwConfFall var(--conf-dur, 2.4s) var(--conf-delay, 0s) infinite linear;
    }
    @keyframes mwConfFall {
      0%   { transform: translateY(-20px) rotate(0deg); opacity: 0; }
      10%  { opacity: 0.9; }
      100% { transform: translateY(120vh) rotate(540deg); opacity: 0; }
    }

    /* ── Reveal screen layout (reference/interstitials.jsx ResultScreen) ── */
    #screen-reveal {
      /* Fixed + inset:0 fills the viewport (reclaims the 80px #app top padding) so
         the result is top-aligned and the confetti falls from the very top. */
      position: fixed; inset: 0;
      display: none;
      background: var(--bg);
      overflow: hidden;
      padding: 0;
    }
    #screen-reveal.active { display: block; }
    #reveal-glow {
      position: absolute; top: -80px; left: 50%;
      transform: translateX(-50%);
      width: 420px; height: 320px;
      pointer-events: none;
      background: radial-gradient(circle, var(--reveal-color, var(--accent)) 0%, transparent 70%);
      opacity: 0.22;
    }
    #reveal-eyebrow {
      position: absolute; top: 56px; left: 0; right: 0;
      text-align: center;
      font-family: var(--mono); font-size: 11px;
      letter-spacing: 0.24em; color: var(--reveal-color, var(--accent));
      text-transform: uppercase;
    }
    #reveal-headline-wrap {
      position: absolute; top: 92px; left: 0; right: 0;
      display: flex; justify-content: center; align-items: center;
      pointer-events: none;
    }
    #reveal-marker {
      position: absolute;
      pointer-events: none;
      opacity: 0.55;
    }
    #reveal-headline {
      position: relative;
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: clamp(72px, 22vw, 110px);
      line-height: 0.85; letter-spacing: -0.04em;
      color: var(--reveal-color, var(--accent));
      text-transform: uppercase;
      text-align: center;
      z-index: 1;
    }
    #reveal-scorecard {
      position: absolute; top: 210px; left: 20px; right: 20px;
      display: grid; grid-template-columns: 1fr 1fr;
      gap: 8px;
    }
    #reveal-scorecard .rev-col {
      padding: 14px 16px;
      background: var(--surface);
      border: 1px solid var(--border);
    }
    /* Right column right-aligns label + number; left column inherits default left. */
    #reveal-scorecard .rev-col[data-col="right"] { text-align: right; }
    .rev-col-label {
      font-family: var(--mono); font-size: 10px;
      letter-spacing: 0.18em;
      color: var(--col-color, var(--text-faint));
      text-transform: uppercase;
    }
    .rev-col-num {
      margin-top: 4px;
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 40px; line-height: 1;
      color: var(--col-color, var(--white));
      letter-spacing: 0.02em;
    }
    #reveal-personal {
      position: absolute; top: 300px; left: 0; right: 0;
      text-align: center;
    }
    #reveal-personal-label {
      font-family: var(--mono); font-size: 10px;
      letter-spacing: 0.22em; color: var(--text-faint);
      text-transform: uppercase;
    }
    #reveal-personal-num {
      margin-top: 8px;
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 72px; line-height: 0.9;
      color: var(--reveal-color, var(--accent));
      letter-spacing: -0.03em;
    }
    #reveal-caption {
      position: absolute; left: 24px; right: 24px;
      bottom: 132px;
      text-align: center;
      font-size: 14px; line-height: 1.45;
      color: var(--muted);
    }
    /* Bottom panel — both the CTA label and the sub line share one fill that runs
       to the very bottom edge (safe-area aware), so the color never stops short. */
    #reveal-cta-panel {
      position: absolute; left: 0; right: 0; bottom: 0;
      padding-bottom: env(safe-area-inset-bottom);
    }
    #reveal-cta {
      padding: 18px 22px 8px;
      display: flex; align-items: center; justify-content: space-between;
      gap: 12px;
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 18px; letter-spacing: 0.06em;
      text-transform: uppercase;
      text-align: left;
    }
    #reveal-cta-sub {
      text-align: left;
      font-size: 12px;
      padding: 0 22px 16px;
    }
    /* Win = solid accent panel with black text; loss = dark panel with accent border. */
    #screen-reveal.reveal-win  #reveal-cta-panel { background: var(--reveal-color, var(--accent)); }
    #screen-reveal.reveal-win  #reveal-cta     { color: #000; }
    #screen-reveal.reveal-win  #reveal-cta-sub { color: rgba(0,0,0,0.66); }
    #screen-reveal.reveal-loss #reveal-cta-panel { background: #000; border-top: 1px solid var(--reveal-color, var(--accent)); }
    #screen-reveal.reveal-loss #reveal-cta     { color: var(--reveal-color, var(--accent)); }
    #screen-reveal.reveal-loss #reveal-cta-sub { color: var(--muted); }
    /* Per-state slot visibility — JS toggles classes on #screen-reveal. */
    #screen-reveal.reveal-no-card    #reveal-scorecard { display: none; }
    #screen-reveal.reveal-no-personal #reveal-personal { display: none; }
    #screen-reveal.reveal-no-cta     #reveal-cta-panel { display: none; }

    /* ── Final declaration screen (MY / OUR toggle) — reference/declarations.jsx
       FinalDeclarationsScreen. Fills the viewport (fixed) so it's top-aligned;
       header + toggle + 3 flex cards + credits + share stack top→bottom. The whole
       screen is the share-capture node; .is-exporting drops the toggle + button. */
    #screen-declaration {
      position: fixed; inset: 0;
      display: none;
      background: var(--bg);
      flex-direction: column;
      padding: max(env(safe-area-inset-top), 52px) 16px max(env(safe-area-inset-bottom), 18px);
      overflow: hidden;
    }
    #screen-declaration.active { display: flex; }
    .fd-emblem {
      position: absolute; top: max(env(safe-area-inset-top), 18px); right: 16px;
      width: 44px; height: 44px; opacity: 0.92; pointer-events: none; z-index: 2;
    }
    .fd-header { flex-shrink: 0; padding-right: 56px; }
    .fd-title {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 24px; line-height: 0.96; letter-spacing: -0.5px;
      color: var(--white); text-transform: uppercase;
    }
    .fd-caption {
      margin-top: 8px;
      font-family: var(--mono); font-size: 10px; letter-spacing: 1.6px;
      color: var(--text-dim); text-transform: uppercase;
    }
    .fd-switch {
      position: relative; display: flex; height: 46px; flex-shrink: 0;
      margin: 14px 0 12px;
      border: 1.5px solid var(--border-mid); background: #0E0E0E;
    }
    .fd-switch-fill {
      position: absolute; top: 0; bottom: 0; left: 0; width: 50%;
      background: var(--lime);
      transition: transform 0.32s cubic-bezier(0.4,0,0.2,1);
    }
    .fd-switch-btn {
      position: relative; flex: 1; border: none; background: transparent; cursor: pointer;
      font-family: 'obviously-wide', sans-serif; font-weight: 700; font-size: 12.5px;
      letter-spacing: 0.6px; text-transform: uppercase; color: var(--white);
      transition: color 0.2s;
    }
    .fd-switch-btn.is-active { color: #000; }
    #fd-cards {
      display: flex; flex-direction: column; flex: 1; min-height: 0; gap: 10px;
    }
    .fd-card {
      flex: 1; min-height: 0; display: flex; position: relative; overflow: hidden;
    }
    /* OURS — solid theme fill, black text, voice count */
    .fd-card.is-ours {
      flex-direction: column; justify-content: center; gap: 6px;
      background: var(--card-color); padding: 13px 16px;
    }
    .fd-card.is-ours .fd-card-top {
      display: flex; align-items: center; justify-content: space-between;
    }
    .fd-card.is-ours .fd-card-kw {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 22px; line-height: 0.9; letter-spacing: -0.3px;
      color: #000; text-transform: uppercase;
    }
    .fd-card.is-ours .fd-card-voices {
      font-family: var(--mono); font-size: 9px; letter-spacing: 1.2px; color: rgba(0,0,0,0.6);
    }
    .fd-card.is-ours .fd-card-body {
      font-family: var(--narrative); font-size: 14px; line-height: 1.3;
      color: #000; font-weight: 500;
    }
    /* MINE — outlined card, color stripe, first-person sentence */
    .fd-card.is-mine {
      background: rgba(14,14,14,0.82); border: 1px solid var(--border-mid);
    }
    .fd-card.is-mine .fd-card-stripe { width: 4px; background: var(--card-color); flex-shrink: 0; }
    .fd-card.is-mine .fd-card-inner {
      flex: 1; padding: 13px 16px; display: flex; flex-direction: column;
      justify-content: center; gap: 7px;
    }
    .fd-card.is-mine .fd-card-kw {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 22px; line-height: 0.9; letter-spacing: -0.3px;
      color: var(--card-color); text-transform: uppercase;
    }
    .fd-card.is-mine .fd-card-body {
      font-family: var(--narrative); font-size: 14px; line-height: 1.32; color: var(--white);
    }
    .fd-card.is-mine .fd-card-body.is-missing { color: var(--text-faint); font-style: italic; }
    .fd-credits {
      display: flex; align-items: center; gap: 10px; flex-shrink: 0; margin-top: 12px;
    }
    .fd-credits-logo { height: 16px; width: auto; opacity: 0.85; }
    .fd-credits-text {
      font-family: var(--mono); font-size: 8.5px; letter-spacing: 1.1px;
      color: var(--text-faint); text-transform: uppercase;
    }
    #fd-share-btn {
      flex-shrink: 0; margin-top: 12px; width: 100%; padding: 16px 0;
      background: var(--lime); border: none; cursor: pointer;
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 15px; letter-spacing: 1.5px; color: #000; text-transform: uppercase;
      display: flex; align-items: center; justify-content: center; gap: 8px;
    }
    #fd-share-btn:disabled { opacity: 0.5; cursor: default; }
    /* During image export, drop the interactive chrome so the saved JPG is clean. */
    #screen-declaration.is-exporting .fd-switch,
    #screen-declaration.is-exporting #fd-share-btn { display: none; }

    /* PLAY: digit code chips for UNITE pair-find phase */
    .pc-digits { display: flex; gap: 10px; justify-content: center; margin: 14px 0 22px; }
    .pc-digits .pc-digit {
      width: 52px; height: 64px; border: 2px solid var(--border);
      background: var(--surface); color: var(--white);
      font-family: 'obviously-wide', sans-serif; font-weight: 700; font-size: 40px;
      display: flex; align-items: center; justify-content: center;
      letter-spacing: 0;
    }

    /* Used by buttons that are positioned in normal flow (e.g. chant tap btn).
       Applying circle-tap to those would yank them 50% up/left because of the
       translate baked into the keyframe. This one only scales. */
    @keyframes inflow-tap {
      0%   { transform: scale(1); }
      35%  { transform: scale(1.35); }
      100% { transform: scale(1); }
    }
    .inflow-tap-anim { animation: inflow-tap 0.22s ease-out; }
    #game-score-final {
      text-align: center;
      pointer-events: none;
    }
    .game-score-label {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 16px;
      color: var(--muted);
      letter-spacing: 0.16em;
      margin-bottom: 12px;
    }
    .game-score-number {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 100px;
      color: var(--accent);
      letter-spacing: 0.04em;
      line-height: 1;
    }

    /* ── Reveal variants (per-round) ── */
    .hidden { display: none !important; }

    .reveal-scoreboard {
      display: flex; gap: 16px; justify-content: center;
      width: 100%; margin-top: 24px;
    }
    .team-card {
      flex: 1; text-align: center;
      padding: 16px 8px; border-radius: 12px;
      border: 2px solid; background: rgba(0,0,0,0.2);
      transition: opacity 0.25s ease;
    }
    .team-card--pink   { border-color: var(--team-red); }
    .team-card--purple { border-color: var(--team-purple); }
    .team-card--faded  { opacity: 0.45; }
    .team-card-label {
      font-family: 'Inter', sans-serif;
      font-size: 10px; letter-spacing: 0.14em;
      color: var(--muted); margin-bottom: 6px;
      text-transform: uppercase;
    }
    .team-card--pink   .team-card-total { color: var(--team-red); }
    .team-card--purple .team-card-total { color: var(--team-purple); }
    .team-card-total {
      font-family: 'Anton', sans-serif;
      font-size: 56px; line-height: 1; letter-spacing: 0.02em;
    }

    /* EMPOWER (round 3) splash headline override — three short lines fit
       cleaner at 36px than the default 56px. Reference/chant-empower.jsx. */
    body[data-round="3"] #game-splash-headline {
      font-size: 36px;
      line-height: 1.05;
      letter-spacing: -0.5px;
    }

    /* Shared brand-close (3x3 Unites logo + tagline) — EMPOWER reveal + chant_complete */
    .brand-close {
      display: flex; flex-direction: column;
      align-items: center; justify-content: center;
      gap: 20px;
    }
    .brand-close-logo { max-width: 60vw; max-height: 40vh; object-fit: contain; }
    .brand-close-text {
      font-family: 'Anton', sans-serif;
      font-size: 28px; letter-spacing: 0.12em; color: var(--accent);
    }
    /* Full-viewport variant — overlays the chant game at ch3 chant_complete. */
    .brand-close--fullscreen {
      position: fixed; inset: 0; z-index: 9999;
      background: #000; pointer-events: none;
    }

    /* Pre-final chant countdown overlay (READY → 3 → 2 → 1). Black bg + cyan text
       previews the inverted final theme; same z-index ladder as brand-close. */
    .chant-countdown {
      position: fixed; inset: 0; z-index: 9998;
      background: #000; color: var(--empower-accent);
      display: flex; flex-direction: column;
      align-items: center; justify-content: center;
      pointer-events: none;
    }
    .chant-countdown.hidden { display: none; }
    .chant-countdown-label {
      font-family: var(--mono); font-size: 13px;
      letter-spacing: 0.32em; color: var(--empower-accent);
      opacity: 0.75; margin-bottom: 24px; text-transform: uppercase;
    }
    .chant-countdown-num {
      font-family: var(--display); font-weight: 700;
      font-size: 160px; line-height: 1; letter-spacing: -0.04em;
      color: var(--empower-accent);
      text-shadow: 0 0 36px color-mix(in srgb, var(--empower-accent) 60%, transparent);
    }
    .chant-countdown-num.is-ready {
      font-size: 72px; letter-spacing: 0.04em;
    }

    /* Identity card on the mini-game splash — left-edge accent bar + uppercase
       mono label + bold display value + optional small sub-line. Same shape on
       all three rounds; bar color binds to --bar-color (set by JS — team color
       for round 1, round accent for rounds 2 & 3). */
    .splash-identity {
      display: flex;
      flex-direction: column;
      gap: 4px;
      margin: 24px 0 0;
      padding: 12px 16px 14px 18px;
      background: var(--card, rgba(255,255,255,0.04));
      border-left: 4px solid var(--bar-color, var(--accent));
      max-width: 360px;
    }
    .splash-identity-label {
      font-family: var(--mono);
      font-size: 10px;
      letter-spacing: 0.22em;
      color: var(--text-faint);
      text-transform: uppercase;
    }
    .splash-identity-value {
      font-family: var(--display);
      font-weight: 700;
      font-size: 32px;
      line-height: 1.05;
      letter-spacing: 0.02em;
      color: var(--bar-color, var(--accent));
      text-transform: uppercase;
    }
    .splash-identity-value.is-narrative {
      font-family: var(--narrative);
      text-transform: none;
      letter-spacing: 0;
    }
    .splash-identity-sub {
      font-family: var(--mono);
      font-size: 11px;
      letter-spacing: 0.04em;
      color: var(--muted);
      margin-top: 2px;
    }
    .splash-identity-sub .splash-identity-emph {
      color: var(--bar-color, var(--accent));
      font-weight: 700;
    }

    /* ═════════════════════════════════════════════════════════
       Onboarding / introduction screens — reference/onboarding-chat.jsx
       ═════════════════════════════════════════════════════════ */

    /* Screen-waiting becomes a positioned container so onboarding children
       can absolutely position themselves (headline at top, form at bottom). */
    #screen-waiting {
      justify-content: flex-start; align-items: stretch;
      padding: 0; min-height: 0;
      position: relative;
    }
    /* Each onboarding overlay (name/profile/waiting) fills the screen. The
       waiting overlay sits at the lowest z-layer; name + profile cards stack
       on top when shown (their inline `display:` controls visibility). */
    .ob-overlay {
      position: fixed; inset: 0;
      background: var(--bg);
      pointer-events: auto;
    }
    #waiting-screen { z-index: 1; }
    #name-card,
    #profile-card { z-index: 5; }

    /* Stacked headline block — "Hé. / Wat is je / **naam?**" pattern.
       The block is anchored at one shared top across every onboarding step so
       the titles line up; headline + sub flow inside it (sub always sits below
       the headline, even when the title wraps to two lines). */
    .ob-headline-block {
      position: absolute; left: 24px; right: 24px; top: 168px;
    }
    .ob-headline {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      line-height: 0.92; letter-spacing: -0.5px;
      color: var(--white);
      text-transform: uppercase;
    }
    .ob-headline .ob-keyword { color: var(--lime); }
    .ob-sub {
      margin-top: 16px;
      font-size: 13px; line-height: 1.5;
      color: var(--text-dim);
      max-width: 280px;
    }

    /* NL/EN language toggle — top-right pill pair */
    .ob-lang-toggle {
      position: absolute; top: 24px; right: 16px;
      display: flex; gap: 4px;
      z-index: 10;
    }
    .ob-lang-btn {
      padding: 5px 8px;
      background: transparent;
      border: 1px solid var(--border-mid);
      font-family: var(--mono); font-size: 9.5px; letter-spacing: 1px;
      color: var(--text-dim); cursor: pointer;
      text-transform: uppercase;
    }
    .ob-lang-btn.active {
      background: var(--lime);
      border-color: var(--lime);
      color: #000;
    }

    /* Shared form-card pattern: mono label + filled input + lime arrow button */
    .ob-form-block {
      position: absolute; left: 20px; right: 20px;
    }
    .ob-form-label {
      font-family: var(--mono); font-size: 10px;
      letter-spacing: 1.8px; color: var(--text-faint);
      text-transform: uppercase;
      margin-bottom: 10px;
    }
    .ob-form-row {
      display: flex; gap: 10px; align-items: stretch;
    }
    .ob-form-input {
      flex: 1;
      padding: 16px 18px;
      background: var(--surface);
      border: 1px solid var(--border-mid);
      color: var(--white);
      outline: none;
      caret-color: var(--lime);
    }
    .ob-form-input.is-text {
      font-family: 'neue-haas-grotesk-text', sans-serif;
      font-size: 18px;
    }
    .ob-form-btn {
      width: 64px;
      background: var(--lime); border: none; color: #000;
      display: flex; align-items: center; justify-content: center;
      cursor: pointer;
    }
    .ob-form-btn:disabled { opacity: 0.4; cursor: not-allowed; }

    /* Profile age dial — selection band + side ticks + numbers with mono YEARS */
    .ob-dial-wrap {
      position: absolute; left: 20px; right: 20px;
      bottom: 130px; height: 216px;
      background: var(--card);
      border: 1px solid var(--border-mid);
      overflow: hidden;
      touch-action: none; user-select: none; -webkit-user-select: none;
    }
    .ob-dial-fade-top, .ob-dial-fade-bot {
      position: absolute; left: 0; right: 0; height: 96px;
      pointer-events: none; z-index: 5;
    }
    .ob-dial-fade-top {
      top: 0;
      background: linear-gradient(to bottom, var(--card) 0%, transparent 100%);
    }
    .ob-dial-fade-bot {
      bottom: 0;
      background: linear-gradient(to top, var(--card) 0%, transparent 100%);
    }
    .ob-dial-band {
      position: absolute; left: 12px; right: 12px;
      top: 50%; transform: translateY(-30px);
      height: 60px;
      border-top: 1.5px solid var(--lime);
      border-bottom: 1.5px solid var(--lime);
      pointer-events: none; z-index: 4;
    }
    .ob-dial-tick {
      position: absolute; top: 50%; transform: translateY(-50%);
      width: 12px; height: 2px; background: var(--lime); z-index: 4;
    }
    .ob-dial-track {
      position: absolute; left: 0; right: 0; top: 50%;
      text-align: center;
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      transition: transform 0.18s ease-out;
    }

    /* Profile experience — icon card options + confirm */
    .ob-xp-card {
      display: flex; align-items: center; gap: 16px;
      padding: 16px 18px;
      background: var(--card);
      border: 1.5px solid var(--border-mid);
      cursor: pointer; text-align: left;
      transition: border-color 0.15s, background 0.15s;
      width: 100%;
    }
    .ob-xp-card.active {
      border-color: var(--lime);
      background: color-mix(in srgb, var(--lime) 7%, transparent);
    }
    .ob-xp-icon {
      width: 44px; height: 44px; flex-shrink: 0;
      background: #1a1a1a;
      border: 1px solid var(--border-mid);
      display: flex; align-items: center; justify-content: center;
      font-size: 20px;
    }
    .ob-xp-card.active .ob-xp-icon {
      background: var(--lime); border-color: var(--lime);
    }
    .ob-xp-body { flex: 1; }
    .ob-xp-label {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 16px; line-height: 0.95;
      color: var(--white); text-transform: uppercase; letter-spacing: 0;
    }
    .ob-xp-card.active .ob-xp-label { color: var(--lime); }
    .ob-xp-sub {
      font-family: 'neue-haas-grotesk-text', sans-serif;
      font-size: 12px; color: var(--text-dim);
      margin-top: 4px; line-height: 1.3;
    }
    .ob-xp-check {
      width: 20px; height: 20px;
      background: var(--lime);
      display: none; align-items: center; justify-content: center;
      flex-shrink: 0;
    }
    .ob-xp-card.active .ob-xp-check { display: flex; }
    .ob-confirm-btn {
      position: absolute; bottom: 24px; left: 20px; right: 20px;
      padding: 16px 0;
      background: var(--lime); border: none; cursor: pointer;
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 14px; letter-spacing: 1px;
      color: #000; text-transform: uppercase;
      display: flex; align-items: center; justify-content: center; gap: 10px;
    }
    .ob-confirm-btn:disabled { opacity: 0.3; cursor: not-allowed; }

    /* Waiting screen — emblem + Under One Hoop + WAITING dots + player count */
    .ob-wait-bg {
      position: absolute; top: 140px; left: 50%; transform: translateX(-50%);
      filter: blur(8px); opacity: 0.10;
      pointer-events: none;
    }
    .ob-wait-vignette {
      position: absolute; inset: 0;
      pointer-events: none;
      background: radial-gradient(120% 70% at 50% 44%, transparent 25%, rgba(10,10,10,0.92) 75%);
    }
    .ob-wait-center {
      position: absolute; inset: 0;
      display: flex; flex-direction: column; align-items: center; justify-content: center;
      gap: 0;
    }
    .ob-wait-emblem { width: 88px; height: 88px; }
    .ob-wait-headline {
      margin-top: 36px; text-align: center;
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 38px; line-height: 0.88; letter-spacing: -0.5px;
      color: var(--white); text-transform: uppercase;
      transition: color 0.5s ease;
    }
    /* Standby previews the upcoming round's color (intro → PLAY orange, then each
       round in its own accent). Toggled via .is-uoh-tinted on #waiting-screen. */
    #waiting-screen.is-uoh-tinted .ob-wait-headline,
    #waiting-screen.is-uoh-tinted .ob-wait-dots { color: var(--accent); }
    .ob-wait-sub {
      margin-top: 18px; text-align: center;
      font-family: var(--narrative); font-size: 18px;
      color: var(--text-dim); line-height: 1.4;
    }
    .ob-wait-dots {
      margin-top: 48px;
      font-family: var(--mono); font-size: 12px; letter-spacing: 3px;
      color: var(--lime);
    }
    .ob-wait-count {
      position: absolute; bottom: 40px; left: 0; right: 0;
      text-align: center;
      font-family: var(--mono); font-size: 10px; letter-spacing: 2.2px;
      color: var(--text-faint);
    }

    /* LOOK UP performance variant — movie state. Hidden by default; the
       .is-lookup class swaps the waiting content for the big LOOK UP layout.
       Accent (var(--accent)) is cycled inline on #waiting-screen by JS. */
    .ob-lookup { display: none; }
    #waiting-screen.is-lookup .ob-wait-center,
    #waiting-screen.is-lookup .ob-wait-count { display: none; }
    #waiting-screen.is-lookup .ob-lookup { display: block; }
    .ob-lookup-headline {
      position: absolute; top: max(env(safe-area-inset-top), 18vh); left: 0; right: 0;
      text-align: center;
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 72px; line-height: 0.88; letter-spacing: -1px;
      color: var(--accent); text-transform: uppercase;
      text-shadow: 0 0 40px color-mix(in srgb, var(--accent) 27%, transparent);
      transition: color 0.6s ease, text-shadow 0.6s ease;
    }
    .ob-lookup-mid {
      position: absolute; top: 52vh; left: 32px; right: 32px; text-align: center;
    }
    .ob-lookup-pre {
      font-family: var(--narrative); font-size: 20px;
      color: var(--text-dim); line-height: 1.4;
    }
    /* In-round handoff (after a personal declaration): the "get ready to hear the
       declaration" line belongs only to the movie finale, not the per-round look-up. */
    #waiting-screen.is-lookup-round .ob-lookup-pre { display: none; }
    .ob-lookup-uoh {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 22px; line-height: 0.95; letter-spacing: -0.3px;
      color: var(--accent); text-transform: uppercase; margin-top: 14px;
      transition: color 0.6s ease;
    }
    .ob-lookup-stamp {
      position: absolute; bottom: max(env(safe-area-inset-bottom), 48px); left: 0; right: 0;
      display: flex; flex-direction: column; align-items: center; gap: 14px;
    }
    .ob-lookup-stamp img { opacity: 0.5; }
    .ob-lookup-tag {
      font-family: var(--mono); font-size: 9px; letter-spacing: 2.8px;
      color: var(--text-faint);
    }

    /* ChatTimer — pill with circular progress ring + MM:SS + thin horizontal bar */
    #chat-timer {
      position: fixed; top: 16px; left: 50%; transform: translateX(-50%);
      z-index: 18;
      display: none;
      flex-direction: column; align-items: center; gap: 6px;
      pointer-events: none;
    }
    #chat-timer.visible { display: flex; }
    #chat-timer .ct-pill {
      background: var(--surface);
      border: 1px solid var(--border-mid);
      padding: 8px 14px 8px 8px;
      display: flex; align-items: center; gap: 10px;
    }
    #chat-timer .ct-ring { position: relative; width: 26px; height: 26px; }
    #chat-timer .ct-mmss {
      font-family: 'obviously-wide', sans-serif; font-weight: 700;
      font-size: 18px; letter-spacing: 1px;
      color: var(--accent); line-height: 1;
    }
    #chat-timer .ct-bar {
      width: 110px; height: 2px; background: rgba(255,255,255,0.08);
    }
    #chat-timer .ct-bar-fill {
      height: 100%; background: var(--accent); width: 100%;
      transition: width 0.9s linear, background 0.2s;
    }
    #chat-timer.warning .ct-mmss,
    #chat-timer.warning .ct-bar-fill,
    #chat-timer.warning .ct-ring-progress { color: #ff6b35; stroke: #ff6b35; background: #ff6b35; }
