/* Pants on Fire — styling
   Mobile-first, Kahoot-aktig følelse: store knapper, klar typografi,
   leken fargekombinasjon (denim-blå bunn + flamme-orange aksenter).
*/

/* ============================================================
   FILE MAP — sections + approximate line ranges
   ============================================================
   Use this to navigate. Update when sections shift significantly.

      6 →  270  Tokens (color, font, radius, shadow, z-index) + body / app shell
    270 →  500  .screen / .intro slideIn / hero / mascots / wordmark
    500 → 1100  Buttons (.btn / .btn-primary / .btn-cream / .btn-ghost) + cards (.card / .reveal-card)
   1100 → 1400  PANTSED-momentet (vote-timer-bar, vote-waiting, achievements toast)
   1400 → 1500  End-of-game podium / winner hero
   1500 → 1750  Modal / overlay / toast (.onboard-overlay, .brand-confirm, .toast)
   1750 → 2100  Lobby specifics (code-display-card, share-row, QR, players-row)
   2100 → 2500  Categories picker / build-category sheet
   2500 → 3000  Settings sheet, Profile sheet, Stats modal
   3000 → 3400  Clubs sheet / Club detail (identity-hero, leaderboard, moments)
   3400 → 3900  Loading screen, intro animation, audit-error helpers
   3900 → 4170  Settings modal-v2 (full-screen sheet)
   4170 → 4360  Profile field rows, identity card, achievements grid
   4360 → 4720  Profile / clubs misc
   4720 → 5110  Lobby compact, club banner, lobby actions
   5110 → 5250  Vote-screen specifics (.vote-screen, .vote-list, .vote-row chassis — B64 P3)
   5250 → 5350  Result-screen layout (.result-screen, .result-card, particles)
   5350 → 5550  End-of-game (winner-hero, awards, top-3 in club, club totals)
   5550 → 5635  Reveal-screen (.reveal-screen, role cards)
   5635 → 5850  Discuss / clue turn (.clue-screen, .clue-floor-card, peek button)
   5850 → 5930  Mic glyph, clue-round indicator
   5930 → 6170  Best-clue voting + result row breakdown
   6170 → 6270  Vote-button polish, smarty-gold treatment
   6270 → 6960  PANTSY decorative (flame-strut, jeans-strut, ember, dust, stamps)
   6960 → 7270  Achievement overlay v2 (medal SVG, sparkles, slide-in)
   7270 → 7640  Pantsy-7 redesign — final screen, awards card, top3
   7640 → 7820  Build-category AI block, suggested-words card
   7820 → end   Pantsy-7 / Pantsy-8 specifics + reduced-motion fallbacks

   CONVENTIONS
   * All colors via CSS custom properties (--primary, --pantsy, --gold, etc).
   * Z-index layers via tokens (--z-overlay, --z-toast, --z-confirm) — see :root.
   * Animations gated on prefers-reduced-motion at :root level (line ~1527).
   * Class naming: kebab-case for components, ABBR-x suffixes for variants
     (e.g. .ach-grid-icon, .pcr-name, .cs-tile).

   ============================================================ */

:root {
  /* GAME SHOW palett — teatralt party-spill, høy kontrast, store displays.
     Fra Claude Designs redesign-pakke. Mettet aubergine bg, hot orange CTA,
     cream cards, dramatic pantsy-rød.

     Token-system:
       SURFACES (mood) — aubergine bg + cream/cream-glow cards
       ACTION         — primary orange signatur for ALL CTA
       IDENTITY       — pantsy-rød (rolle), smarty-gold (best clue), accent-cool (info)
       STATUS         — danger/success/warning kept separate */

  /* SURFACES — mer dramatisk dybde enn før (svartere bg, varmere cream) */
  --surface-deep: #0F0418;     /* Nesten-svart aubergine — gir mer kontrast */
  --surface-mid:  #1F0E2C;     /* Elevation 1 — for dark cards */
  --surface-hi:   #2B143D;     /* Elevation 2 — modal-overflater */
  --surface-lo:   #160820;     /* Recessed — input bg, secondary */
  --surface-card: #FFF4DE;     /* Cream — varmere enn før */
  --surface-card-bright: #FFF8E8;
  --surface-card-quiet: rgba(255, 244, 222, 0.55);

  /* Bakoverkompatibilitet */
  --bg: var(--surface-deep);
  --bg-2: var(--surface-mid);
  --card: var(--surface-card);

  /* TEKST */
  --text-on-deep: #FFF4DE;     /* Cream på aubergine */
  --text-on-card: #1A0820;     /* Deep aubergine på cream — høyere kontrast */
  --text-muted: rgba(255, 244, 222, 0.7);
  --text-faint: rgba(255, 244, 222, 0.4);
  --ink-soft: #3F1A4A;         /* Soft tekst på cream */
  --ink:      #1A0820;          /* Hardest tekst på cream — for input + body */
  /* Items 2/4 (Bølge 1.9 / 2026-05-08): --text-soft is a TAN/KHAKI neutral
     so it reads correctly on BOTH dark aubergine and cream surfaces. Bølge
     1.8 mistakenly aliased it to --ink-soft (deep purple), which made every
     dark-surface usage (gs-toggle-sub, build-words-list .bw-input, settings
     hints) effectively invisible. The cream-surface call-sites that needed
     deep-purple soft (rules-modal-body, name-modal-a11y-header) reference
     --ink-soft directly, so this change doesn't regress them. */
  --text-soft: #B5A48E;
  --card-fg: var(--text-on-card);
  --muted: var(--text-muted);
  --border: #F0E2C2;

  /* PRIMARY ACTION — Game Show fire-orange, mer mettet enn før */
  --primary: #FF5722;          /* Game Show orange — knall */
  --primary-hover: #D33E14;
  --primary-on: #ffffff;
  --primary-fg: var(--primary-on);
  --primary-2: var(--primary-hover);
  --primary-glow: rgba(255, 87, 34, 0.45);

  /* Bakover: --fire alias */
  --fire: var(--primary);
  --fire-dim: var(--primary-hover);
  --ember: #FFC857;            /* Warm gold-orange aksent */

  /* SECONDARY */
  --secondary: #FFC857;
  --secondary-2: #E8A93A;

  /* COOL ACCENT */
  --accent-cool: #14b8a6;
  --accent-cool-deep: #0f766e;
  --accent-cool-bg: rgba(20, 184, 166, .12);

  /* IDENTITET — Game Show pantsy-rød (sterkere enn rose) + gold */
  --pantsy: #FF1744;           /* Hot crimson — Pantsy-drama */
  --pantsy-2: #D81144;
  --pantsy-deep: #A8082E;
  --pantsy-glow: rgba(255, 23, 68, 0.30);
  --pantsy-hi: #FF3D6B;        /* Lighter for highlights */
  --gold: #FFD24A;             /* Smarty / celebration gold */
  --gold-deep: #C99820;
  --gold-glow: rgba(255, 210, 74, 0.30);
  --smarty-gold: var(--gold);

  /* PLAYER PALETTE — stable per-name color assignment across screens.
     Bølge 64 (2026-05-10): added per Pantsy9 design pack tokens.jsx
     gameshow direction. Consumed by avatar bg in B65+ VoteRow tone-aware
     rendering. Currently unconsumed at root level (B64 ships P1+P2 only —
     timer redesign — and stages these tokens for B65/B66/B67). */
  --player-violet: #9B6BFF;
  --player-aqua:   #5DCFEA;
  --player-pink:   #E27ABE;
  --player-sky:    #7FB0F0;

  /* PANTSY9 ALIASES — Bølge 70.5 (2026-05-10): namespaced token aliases
     mapping the design pack's tokens.jsx gameshow direction onto the
     existing :root vars. Lets primitives + future reskin waves consume
     `var(--pantsy-fire)` etc. and stay portable across direction switches.
     The trailing `bg-grad` is duplicated from the html background-image
     declaration — keep the two in sync if either is touched. */
  --pantsy-fire: var(--fire);
  --pantsy-pantsy-red: var(--pantsy);
  --pantsy-pantsy-red-hi: var(--pantsy-hi);
  --pantsy-smarty-gold: var(--gold);
  --pantsy-cream: var(--surface-card);
  --pantsy-ink: var(--ink);
  --pantsy-ink-soft: var(--ink-soft);
  --pantsy-fg: var(--text-on-deep);
  --pantsy-fg-soft: var(--text-muted);
  --pantsy-fg-faint: var(--text-faint);
  --pantsy-bg: var(--surface-deep);
  --pantsy-bg-grad: radial-gradient(ellipse at 50% 0%, #3A0E2A 0%, #1A0820 50%, #0F0418 100%);
  --pantsy-surface: var(--surface-mid);
  --pantsy-surface-hi: var(--surface-hi);
  --pantsy-surface-lo: var(--surface-lo);
  --pantsy-display: var(--font-display);
  --pantsy-sans: var(--font-body);
  --pantsy-mono: var(--font-mono);
  --pantsy-radius-card: var(--radius-card);
  --pantsy-radius-btn: var(--radius-btn);
  --pantsy-radius-pill: var(--radius-pill);

  /* STATUS */
  --danger: #FF1744;
  --success: #16a34a;
  --warning: #FFC857;

  /* SHAPE — større radius enn før (Game Show: 28 cards, 18 buttons) */
  --radius: 18px;
  --radius-card: 28px;
  --radius-btn: 18px;
  --radius-pill: 999px;
  /* Bølge 168 (2026-05-13): modal-chassis consolidation tokens.
     Centered modal cards (.onboard-modal pattern) standardize on 24px
     radius and the deep-purple 0.94-alpha backdrop. Two outlier modals
     (.host-recovery-modal-overlay rgba(0,0,0,0.7) + .achievements-detail-overlay
     rgba(0,0,0,0.78)) migrate to these tokens in the same wave. .rules-modal-card
     stays at 20px per design decision D-032 (Pantsy-8 Batch 26) — intentional
     tighter rounding, not drift. */
  --radius-modal: 24px;
  --modal-backdrop: rgba(15, 4, 24, 0.94);
  --shadow: 0 10px 30px rgba(0, 0, 0, .35);
  --shadow-lg: 0 20px 50px rgba(0, 0, 0, .50);
  --shadow-glow: 0 8px 24px var(--primary-glow);

  /* Z-INDEX STACK — single source of truth for layering.
     Add 2026-05-04 (code review CR.1 R2): scattered magic numbers across the file
     made stacking conflicts theoretically possible. Tokens fix that.

     Stacking from back to front:
       1   .reveal-card content over reveal-card backdrop (intra-card layering)
       100 lobby code-card sticky badges
       --z-overlay      modal/sheet/onboard backdrop (was 200)
       --z-sheet        full-screen sheets above plain overlays (was 240)
       --z-toast        toast notifications, auto-pick-mix overlay (was 250)
       --z-build-cat    build-category sheet (was 260)
       --z-achievement  achievement-overlay slide-in card (was 270)
       --z-confetti     canvas confetti at game-end (was 300)
       --z-confirm      brand-confirm modal — TOP, even above achievements
                        (so danger-confirm dismisses are always reachable)
  */
  --z-overlay: 200;
  --z-sheet: 240;
  --z-toast: 250;
  --z-build-cat: 260;
  --z-achievement: 270;
  --z-confetti: 300;
  --z-confirm: 400;

  /* TYPOGRAFI — Game Show: Bricolage display, Inter Tight body, JetBrains Mono codes.
     Emoji-fallback (Apple/Segoe/Noto Color Emoji) er lagt til SLUTT på alle stacker
     fordi Bricolage og Inter Tight ikke har emoji-glyfer. Uten dette faller
     emojis til en "tofu-square" på systemer der Bricolage er primary (Linux
     Chromium spesielt) — løste D-CP-D / D-038 / D-047 i kategorier + build-cat. */
  --font-display: "Bricolage Grotesque", "Archivo Black", system-ui, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
  --font-body: "Inter Tight", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", monospace;

  /* B (Bølge 1.8 / 2026-05-08): a11y text-scale token. Replaces the Bølge 1.7
     `zoom: 1.12` approach, which scaled hit-targets + layout (broke modal sheet
     bottoms, sticky bars, and PartyKit input alignment on iOS). The token
     pattern scales ONLY font-size on hot-path selectors (calc(<px> * var(--text-scale))),
     leaving paddings/gaps/buttons untouched so hit-targets remain identical.
     body.a11y-larger-text bumps the value to 1.15. */
  --text-scale: 1;
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0;
  padding: 0;
  font-family: var(--font-body);
  color: var(--text-on-deep);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
/* D (Bølge 1.7 / 2026-05-07): full-height background fix. Earlier the gradient
   sat on body with min-height: 100dvh, which on iOS Safari (URL bar visible)
   shrinks to less than the visible viewport — the area behind the URL bar
   showed only solid html bg-color (no gradient), so a tone discontinuity
   appeared at the top/bottom edges when scrolling.
   Fix: gradient on html (covers full viewport, including under URL bar +
   safe-area + bounce-scroll). body becomes transparent, so the gradient is
   what paints. body keeps 100dvh for content-flow sizing.
   GAME SHOW bakgrunn — radial gradient fra varm aubergine på toppen til
   near-black i bunnen. */
html {
  background-color: #0F0418;
  background-image: radial-gradient(ellipse at 50% 0%, #3A0E2A 0%, #1A0820 50%, #0F0418 100%);
  background-attachment: fixed;
  min-height: 100%;
}
body {
  background: transparent;
  min-height: 100vh;
  min-height: 100dvh;
}

/* GAME SHOW typografi — display på alt stort, Inter Tight på body. */
.brand,
.hero h1,
h2,
.code-display,
.reveal-card .word,
.share-card .share-winner .name,
.share-card .share-brand,
.recap-card .player-name,
.timer span:not(.label) {
  font-family: var(--font-display);
  letter-spacing: -0.035em;
  font-weight: 700;
}

/* Mono brukes for 4-tegns rom-koder + technical readouts */
.code-display,
input.code-input {
  font-family: var(--font-mono);
  letter-spacing: 0.18em;
  font-weight: 700;
}

.app {
  max-width: 480px;
  margin: 0 auto;
  /* Fallback for Safari < 15.4 */
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  /* env(safe-area-inset-*) tar høyde for iPhone-notch + dynamic island.
     Vi LEGGER TIL en buffer på 16px så innhold aldri klippes av dynamic island
     på iPhone 14 Pro+ (env-verdien dekker bare statusbar-høyden, ikke buffer
     for klikkbart område rundt dynamic island).
     Black-translucent status bar mode (PWA) gir env() = full status bar height. */
  padding:
    calc(env(safe-area-inset-top, 0px) + 16px)
    max(12px, env(safe-area-inset-left))
    max(20px, env(safe-area-inset-bottom))
    max(12px, env(safe-area-inset-right));
}

/* Større padding på iPad og oppover */
@media (min-width: 600px) {
  .app { padding-left: 20px; padding-right: 20px; }
}

/* ---------------- Top bar — GAME SHOW ---------------- */
.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
  font-size: calc(14px * var(--text-scale));
  color: rgba(255, 244, 222, .7);
}
.topbar-right { display: flex; align-items: center; gap: 8px; }
.topbar .brand {
  display: flex;
  align-items: center;
  gap: 6px;
  /* Display-font på wordmark — Bricolage Grotesque, ikke samme som body */
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text-on-deep);
  font-size: calc(18px * var(--text-scale));
}
.topbar .brand .flame {
  display: inline-block;
  filter: drop-shadow(0 0 8px var(--primary-glow));
}
/* Brand-pantsy span gets specifikt display-font weight i game show — */
.topbar .brand .brand-pantsy {
  font-family: var(--font-display);
  font-weight: 700;
}
.lang-toggle, .icon-btn {
  background: rgba(255,255,255,.10);
  border: 1px solid rgba(255,255,255,.15);
  color: white;
  border-radius: 999px;
  padding: 6px 12px;
  font-size: calc(13px * var(--text-scale));
  cursor: pointer;
}
.icon-btn { padding: 6px 10px; font-size: calc(16px * var(--text-scale)); }
.icon-btn.muted { opacity: 0.5; }

/* Profil-knapp øverst til høyre — match Claude Designs AppBar-avatar.
   Subtle dark-transparent bg + 1px hvit border + cream-tekst (ikke solid fire).
   Tidligere var den var(--primary) som var altfor påtrengende. */
.profile-btn {
  width: 34px;
  height: 34px;
  border-radius: 999px;
  background: var(--surface-hi);
  border: 1px solid rgba(255, 255, 255, 0.08);
  color: var(--text-on-deep);
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: calc(12px * var(--text-scale));
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  letter-spacing: 0;
  padding: 0;
  transition: transform .12s ease, background .12s ease;
  box-shadow: none;
}
.profile-btn:hover { background: rgba(255, 255, 255, 0.10); }
.profile-btn:active { transform: scale(0.96); }

/* ---------------- Screens ----------------
   `#screen` (i index.html) er parent for alle render()-cycle-screens.
   Den må ha flex:1 og display:flex slik at child .screen får full høyde
   og kan plassere bottom-CTA pinnet via flex-spacer eller margin-top:auto. */
#screen {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.screen {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
/* PRINSIPP 1: bottom-CTA er ALLTID pinnet til bunnen av skjermen.
   Helper-class `.pin-bottom` på en CTA pusher den ned via margin-top:auto.
   PRINSIPP 2: hovedkortet på 03/04/05/06/07 har flex:1 så det vokser til
   å fylle all plass mellom topp-eyebrow og bottom-CTA — se .reveal-card,
   .handover-card, .clue-floor-card og .pre-reveal-card. */
.screen > .pin-bottom,
.screen .pin-bottom {
  margin-top: auto;
}
.screen > .btn:last-child {
  /* Knapper som direkte siste-barn av .screen får automatisk pin-bottom
     hvis det ikke allerede er en flex:1-search før dem. Dette gjelder
     reveal-screen, clue-screen, etc. */
  flex-shrink: 0;
}
/* slideIn-animasjonen er beholdt men bare anvendt på .screen.intro,
   som settes KUN ved fase-skifte (ikke per re-render). Tidligere fikk
   .screen alltid animation, som re-startet på hver state-oppdatering
   og skapte synlig "blink-in" på iOS Safari. */
.screen.intro {
  animation: slideIn .28s cubic-bezier(.32, .72, .32, 1);
}
@keyframes slideIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ---------------- Hero (home) — GAME SHOW ----------------
   Ny mascot-sone: SVG-flamme + SVG-jeans side-ved-side, ingen emoji.
   "Pants on Fire" wordmark i Bricolage med per-bokstav drop-in. */
.hero {
  text-align: center;
  /* Komprimert padding så hjem-skjermen passer uten scroll på mindre telefoner.
     Tidligere 24x16x20 → 8x16x4. */
  padding: 8px 16px 4px;
}
.hero .logo {
  font-size: calc(64px * var(--text-scale));
  line-height: 1;
  filter: drop-shadow(0 6px 20px var(--primary-glow));
  animation: flicker 2s ease-in-out infinite alternate;
}
.hero .logo-img {
  display: block;
  margin: 0 auto;
  width: 96px;
  height: 96px;
  border-radius: 22px;
  animation: none;
  filter: drop-shadow(0 8px 24px var(--primary-glow));
  -webkit-user-select: none;
  user-select: none;
}
@keyframes flicker {
  0%   { transform: rotate(-2deg) scale(1); }
  50%  { transform: rotate(2deg) scale(1.04); }
  100% { transform: rotate(-1deg) scale(1); }
}

/* GAME SHOW mascot composer — flame venstre, jeans høyre, baseline-aligned
   D-001, D-007 (Pantsy-8 user-decision): hero illustration was visually smaller than
   design's commanding mid-screen presence. Bumped height 130→170 — gives the SVG
   children room to render at their natural larger size (which is set via attributes
   on each SVG element directly to avoid clashing with the strut/rock animations). */
.hero-mascot {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 0;
  height: 170px;
  margin: 4px auto 8px;
  position: relative;
  margin-left: -8px;
}
.hero-mascot .mascot-flame {
  transform-origin: 50% 100%;
  animation: heroFlameStrut 1.6s ease-in-out infinite;
  margin-right: -18px;
  margin-bottom: 4px;
}
.hero-mascot .mascot-flame svg {
  display: block;
  filter: drop-shadow(0 0 14px var(--primary));
  transform-origin: 50% 100%;
  animation: heroFlameBlaze 0.6s ease-in-out infinite;
}
.hero-mascot .mascot-jeans {
  transform-origin: 50% 100%;
  animation: heroJeansRock 2.4s ease-in-out infinite;
  filter: drop-shadow(0 6px 12px rgba(0, 0, 0, 0.4));
}
.hero-mascot .mascot-jeans svg { display: block; }
@keyframes heroFlameStrut {
  0%, 100% { transform: translateY(0) rotate(-3deg); }
  50%      { transform: translateY(-6px) rotate(4deg); }
}
@keyframes heroFlameBlaze {
  0%, 100% { transform: scaleY(1) scaleX(1); opacity: 1; }
  33%      { transform: scaleY(1.08) scaleX(0.96); opacity: 0.92; }
  66%      { transform: scaleY(0.95) scaleX(1.04); opacity: 1; }
}
@keyframes heroJeansRock {
  0%, 100% { transform: rotate(-3deg); }
  50%      { transform: rotate(3deg); }
}

/* GAME SHOW per-letter drop-in for "Pants on Fire" */
.hero h1 {
  /* Tighter margin over og under wordmark — komprimerer hele hero-zonen */
  margin: 2px 0 2px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(clamp(38px, 12vw, 48px) * var(--text-scale));
  letter-spacing: -0.04em;
  line-height: 0.95;
  color: var(--text-on-deep);
}
.hero h1 .letter {
  display: inline-block;
  white-space: pre;
  animation: letterDrop 0.5s cubic-bezier(.2, .9, .3, 1.2) both;
}
.hero h1 .letter.fire-pulse {
  animation: letterDrop 0.5s cubic-bezier(.2, .9, .3, 1.2) both,
             letterFirePulse 6s ease-in-out infinite;
  animation-delay: 0s, 1.6s;
}
@keyframes letterDrop {
  0%   { transform: translateY(-14px); opacity: 0; }
  100% { transform: translateY(0);     opacity: 1; }
}
@keyframes letterFirePulse {
  0%, 92%, 100% { color: var(--text-on-deep); text-shadow: none; }
  94% { color: var(--primary);   text-shadow: 0 0 14px rgba(255, 87, 34, .55); }
  96% { color: var(--gold);      text-shadow: 0 0 18px rgba(255, 210, 74, .65); }
  98% { color: var(--primary);   text-shadow: 0 0 14px rgba(255, 87, 34, .55); }
}

.hero p.tagline {
  /* D-002 (Pantsy-8 Batch 22): tagline "A bluffing game. One liar, everyone else hunts."
     wraps to 2 lines in app at 14px / 280px max-width; design fits it on 1 line.
     Reduce font 14→12.5 and bump max-width 280→340 so the full tagline fits horizontally. */
  font-size: calc(12.5px * var(--text-scale));
  color: var(--text-muted);
  margin: 6px auto 0;
  max-width: 340px;
  line-height: 1.35;
}

/* ---------------- Cards — GAME SHOW ----------------
   Større radius (28), varmere cream, sterkere shadow. */
.card {
  background: var(--surface-card);
  color: var(--text-on-card);
  border-radius: var(--radius-card);
  padding: 16px;
  box-shadow: 0 8px 22px rgba(0, 0, 0, .28);
  border: 1px solid rgba(240, 226, 194, .6);
}
.card.bright {
  background: var(--surface-card-bright);
  box-shadow: var(--shadow);
}
.card.quiet {
  background: var(--surface-card-quiet);
  box-shadow: 0 4px 12px rgba(0, 0, 0, .16);
  border-color: rgba(240, 226, 194, .35);
}
/* Dark surface card-variant — matcher Claude Designs `surface` (deep aubergine elevation 1).
   Brukes på lobby-kategorier og lobby-players slik at de ikke konkurrerer med
   det store cream code-kortet (visuell hierarki). Cream forblir for kort med
   primært lese-fokus (code, regler), dark for "sekundære" info-kort. */
.card.dark {
  background: var(--surface-mid);
  color: var(--text-on-deep);
  border: 1px solid rgba(255, 255, 255, 0.06);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.32);
}
.card.dark .label,
.card.dark .eyebrow.on-card {
  color: var(--text-faint);
}
/* Lite "+ invite" / "Edit ›"-link i dark cards — bruker faint-text
   D-023 (Pantsy-8 Batch 11): Edit › affordance was barely visible at --text-faint
   (38%). Lifting to --text-soft (62%) so it reads as a tappable link without being
   loud, matching design's clearly-but-quietly-visible pattern. */
.card.dark .card-row-link {
  font-size: calc(12px * var(--text-scale));
  color: var(--text-soft);
  font-weight: 600;
  cursor: pointer;
  background: none;
  border: none;
  padding: 0;
  font-family: inherit;
}
.card.dark .card-row-link:hover { color: var(--text-on-deep); }
.card.sm { padding: 12px 14px; border-radius: var(--radius-btn); }
.card .label {
  font-size: calc(11px * var(--text-scale));
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-soft);
  margin-bottom: 6px;
}
.card-section {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid rgba(231, 224, 211, .7);
}

/* ---------------- Inputs ----------------
   Cream-tone bakgrunn istedenfor ren hvit — matcher kort og brand,
   slipper "kontorpapir"-følelsen i lobby-form-feltene. */
input[type="text"], input[type="number"], select, textarea {
  width: 100%;
  padding: 14px 16px;
  border: 2px solid var(--border);
  border-radius: 12px;
  font-size: calc(17px * var(--text-scale));
  font-family: inherit;
  background: #fdf8ec;
  color: var(--card-fg);
  outline: none;
  transition: border-color .15s, box-shadow .15s;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 4px var(--primary-glow);
}
textarea {
  min-height: 120px;
  resize: vertical;
  font-size: calc(15px * var(--text-scale));
  line-height: 1.4;
}
input.code-input {
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-weight: 700;
  font-size: calc(28px * var(--text-scale));
  padding: 16px 12px;
  /* GAME SHOW: JetBrains Mono for codes — distinct from body, evokes terminals */
  font-family: var(--font-mono);
  color: var(--card-fg);
}
input.code-input::placeholder {
  /* D-005 (Pantsy-8 Batch 11): design ENTER CODE placeholder has wider tracking
     than app's 0.18em. Bumped to 0.24em to match design's airier monospace feel. */
  color: #a89a86;
  font-weight: 600;
  letter-spacing: 0.24em;
}

/* ---------------- Buttons — GAME SHOW ---------------- */
.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 20px;
  border-radius: var(--radius-btn);
  border: none;
  font-size: calc(16px * var(--text-scale));
  font-weight: 700;
  font-family: inherit;
  letter-spacing: -0.01em;
  cursor: pointer;
  transition: transform .08s, box-shadow .12s, background .15s;
  width: 100%;
  min-height: 52px;
  user-select: none;
}
.btn:active { transform: scale(0.98); }
.btn-primary {
  /* Pantsy-8 D-CP-A: design uses FLAT solid orange (no gradient, no inset
     highlight). Tidligere ga `inset 0 1px 0 rgba(255,255,255,0.18)`
     en topp-highlight som visuelt så ut som en gradient til burnt-orange.
     Beholder en SUBTIL drop-shadow så knappen fortsatt sitter "på" surface. */
  background: var(--primary);
  color: var(--primary-on);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
}
.btn-primary:disabled {
  opacity: 0.6;
}
.btn-secondary {
  background: linear-gradient(180deg, var(--secondary) 0%, var(--secondary-2) 100%);
  color: var(--text-on-card);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.14);
}
.btn-ghost {
  background: transparent;
  color: var(--text-on-deep);
  /* Tydeligere ghost-border for at brukerne ser at det er en knapp.
     Tidligere 0.15 alpha var nesten usynlig på dark bg. */
  border: 1px solid rgba(255, 244, 222, 0.18);
}
.btn-ghost:hover {
  background: rgba(255, 244, 222, 0.06);
  border-color: rgba(255, 244, 222, 0.28);
}
.btn-cream {
  background: var(--surface-card);
  color: var(--text-on-card);
  box-shadow: 0 4px 14px rgba(0, 0, 0, .35);
}
.btn-danger {
  background: var(--danger);
  color: white;
}
.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}
.btn-row { display: flex; gap: 10px; }
.btn-row .btn { flex: 1; }
.btn.btn-sm {
  padding: 10px 16px;
  font-size: calc(14px * var(--text-scale));
  min-height: 42px;
}

/* ---------------- Player list ---------------- */
.player-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.player {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 9px 12px;
  background: rgba(255,255,255,.10);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 12px;
}
.player .avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: linear-gradient(135deg, #f97316, #ec4899);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: calc(16px * var(--text-scale));
  color: white;
  flex-shrink: 0;
}
/* Avatar med rolle-stamp (kjent klubb) — wrapper over standard avatar.
   Stempel sitter nederst-til-høyre som en liten badge. Subtil — ikke
   en stor "klistremerke", bare en hint på rollen. */
.player .avatar.avatar-wrap {
  position: relative;
  overflow: visible;
}
.avatar-initials { display: inline-block; }
.avatar-role {
  position: absolute;
  bottom: -3px;
  right: -3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #1a0e1f;
  border: 2px solid #f5ecd8;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(10px * var(--text-scale));
  line-height: 1;
  z-index: 1;
}
.player .name {
  flex: 1 1 auto;
  font-weight: 600;
  /* Lange navn (maxlength=20) må trunkere så badges ikke pushes ut av rad. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.player .score {
  font-weight: 800;
  font-size: calc(18px * var(--text-scale));
  color: white;
  background: rgba(0,0,0,.25);
  padding: 4px 10px;
  border-radius: 999px;
  min-width: 44px;
  text-align: center;
  /* Hvis raden wrap'er (mange badges), holder vi score helt til høyre slik at
     den aldri ramler til venstre kant av en ny rad. */
  margin-left: auto;
}
.player .badge {
  font-size: calc(11px * var(--text-scale));
  font-weight: 700;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 999px;
  letter-spacing: 0.05em;
}
.badge-host { background: rgba(249,115,22,.25); color: #fed7aa; }
.badge-you { background: rgba(59,130,246,.25); color: #bfdbfe; }
.badge-disc { background: rgba(0,0,0,.3); color: #a89a86; }
.badge-pantsy { background: var(--pantsy); color: white; }
.badge-pantsy-flex {
  margin-left: 6px;
  display: inline-flex !important;
  align-items: center;
  gap: 4px;
  padding: 3px 9px;
  line-height: 1;
}
.badge-pantsy-flex .bp-fire {
  font-size: calc(12px * var(--text-scale));
  line-height: 1;
  display: inline-block;
}
.badge-pantsy-flex .bp-text {
  letter-spacing: .06em;
  line-height: 1;
}
.badge-gold { background: var(--gold); color: #2a1424; }
.player.dimmed { opacity: 0.55; }
.player.winner {
  background: linear-gradient(135deg, #fcd34d 0%, #f59e0b 100%);
  color: #2a1424;
  border: none;
}
.player.winner .score { background: rgba(0,0,0,.15); color: #2a1424; }
.player.winner .name { color: #2a1424; }

/* Vote buttons */
/* ---------------- Vote list — GAME SHOW cream pills ---------------- */
.vote-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  isolation: isolate;
  /* #55 (2026-05-05): vote-list mid-section grows to fill available vertical space
     so the card matches reveal/best-clue rhythm. Without flex:1, the rows hugged
     their natural height and a thick whitespace gap pushed the bottom-row down. */
  flex: 1;
}
/* B98.1 (2026-05-11): legacy `.vote-btn` chassis retired.
   - Vote phase replaced this with `.vote-row` in B64 P3 (commit bf26d4d).
   - BestClue replaced `.vote-btn.smarty-tone` with `.vote-row.smarty` in B65
     (commit 34dba05).
   The legacy `.vote-screen` + `.vote-waiting-bottom` layout helpers are
   preserved by the new `.vote-row` chassis below. ~140 LOC removed. */

/* Vote-screen layout — pinner waiting-row til bunn */
.vote-screen {
  display: flex;
  flex-direction: column;
  /* min-height removed 2026-05-11 (Stian round 7) — `flex: 1` from `.screen` base is sufficient; min-height was making the screen overflow `#screen` and pushing CTAs under the home-indicator on iOS PWA */
}
.vote-waiting-bottom {
  flex-shrink: 0;
  margin-top: 0;
}

/* ────────────────────────────────────────────────────────────────────
   Bølge 64 P3 (2026-05-10): VoteRow chassis swap.

   Pantsy9 gameshow direction (`_audit/_pantsy9/07c.5-point-at-pantsy/
   screens-vote.jsx` VoteRow component) replaces the legacy `.vote-btn`
   pill with a wider btn-radius row in three states + two tones.

   States (mutually exclusive):
     .vote-row.tappable — cream bg, ink fg, tap-eligible
     .vote-row.you      — dim bg, faint fg, pointer-events:none + disabled attr
     .vote-row.selected — pantsy gradient bg + white fg + check badge

   Tone (default = pantsy on Vote phase; B65 will mirror with .smarty
   on BestClue):
     [no modifier] — pantsyRed→fire gradient when selected (Vote · Pantsy)
     .smarty       — gold→fire gradient when selected (BestClue · Smarty,
                     B65 will land this — staged here for token reuse)

   The earlier `.vote-btn` rules above are kept as orphan CSS (no live
   call sites post-P3) until a polish wave deletes them — preserves the
   existing class for any out-of-band references and keeps the diff tight.
   ──────────────────────────────────────────────────────────────────── */

/* Base row chassis — applies to all states. State modifiers below
   override bg/fg/border/shadow. min-height tracks design pack's
   14px vertical padding × 2 + ~28px avatar + line-height = ~56px;
   we let content drive height instead of forcing min-height so a
   font-scale bump doesn't crop the avatar. */
.vote-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-radius: var(--radius-btn, 18px);
  font-family: inherit;
  font-size: calc(16px * var(--text-scale));
  font-weight: 700;
  letter-spacing: -0.01em;
  text-align: left;
  cursor: pointer;
  width: 100%;
  position: relative;
  overflow: hidden;
  transition: transform 0.12s ease, box-shadow 0.18s ease;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04);
}
.vote-row:hover { transform: translateY(-1px); }
.vote-row:active { transform: scale(0.98); }
.vote-row:focus-visible {
  outline: 2px solid var(--pantsy-hi, #FF3D6B);
  outline-offset: 2px;
}

/* Avatar circle — 28px per design pack (was 24px on .vote-btn).
   Background color flows from inline style (playerColor() per-player
   palette assignment). Selected/you variants below override. */
.vote-row .avatar {
  width: 28px;
  height: 28px;
  border-radius: 999px;
  background: var(--primary);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: calc(11px * var(--text-scale));
  font-weight: 800;
  letter-spacing: 0.02em;
  flex-shrink: 0;
  text-transform: uppercase;
  border: none;
  font-family: var(--font-display, inherit);
}

/* Name label — flex:1 so it eats the row width; ellipsis on overflow. */
.vote-row .vote-row-name {
  flex: 1;
  min-width: 0;
  font-weight: 700;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* TAPPABLE — cream bg + ink fg. Default candidate row. */
.vote-row.tappable {
  background: var(--surface-card, #FFF4DE);
  color: var(--text-on-card, #1A0820);
  border: 1px solid rgba(0, 0, 0, 0.08);
}

/* YOU — dim bg + faint fg, disabled. Self-row indicator. The disabled
   attr on the underlying <button> blocks pointer + keyboard activation;
   pointer-events:none belt-and-braces against any synthetic-event paths. */
.vote-row.you {
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-faint, rgba(255, 244, 222, 0.4));
  border: 1px solid rgba(255, 255, 255, 0.06);
  cursor: default;
  pointer-events: none;
  box-shadow: none;
}
.vote-row.you .avatar {
  /* Slightly muted — host's fire stays readable but not loud against dim row. */
  opacity: 0.78;
}

/* SELECTED — pantsy gradient bg + white fg + glow shadow. Pantsy tone
   default (Vote phase). The .smarty modifier below overrides for B65. */
.vote-row.selected {
  background: linear-gradient(160deg, var(--fire, #FF5722) 0%, var(--pantsy, #FF1744) 100%);
  color: #fff;
  border: 1px solid var(--pantsy-hi, #FF3D6B);
  box-shadow: 0 6px 18px rgba(255, 87, 34, 0.33), inset 0 1px 0 rgba(255, 255, 255, 0.18);
}
.vote-row.selected .avatar {
  /* Faint white wash so the per-player palette color reads through dim */
  background: rgba(255, 255, 255, 0.32) !important;
  color: #fff !important;
}

/* SELECTED · SMARTY tone — staged for B65 BestClue mirror. Same chassis,
   gold gradient + dark ink fg per design pack. Inactive on Vote (P3
   doesn't add the modifier client-side); B65 adds .smarty to the row
   when rendering BestClue. */
.vote-row.selected.smarty {
  background: linear-gradient(160deg, #FFE38A 0%, var(--gold, #FFD24A) 55%, var(--fire, #FF5722) 100%);
  color: #3A2410;
  border: 1px solid #8A5A1A;
  box-shadow: 0 6px 18px rgba(255, 210, 74, 0.40), inset 0 1px 0 rgba(255, 255, 255, 0.35);
}
.vote-row.selected.smarty .avatar {
  background: rgba(58, 36, 16, 0.22) !important;
  color: #3A2410 !important;
}

/* YOU-tag pill on the self row. Right-aligned via margin-left:auto. */
.vote-row .you-tag {
  display: inline-flex;
  align-items: center;
  padding: 3px 8px;
  background: rgba(255, 244, 222, 0.10);
  color: var(--text-faint, rgba(255, 244, 222, 0.4));
  border-radius: var(--radius-pill, 999px);
  font-family: var(--font-mono, monospace);
  font-size: calc(10px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.12em;
  margin-left: auto;
}

/* Check badge — 22px white circle with pantsy-red ✓. Smarty tone
   variant inverts to gold ink. Right-aligned via margin-left:auto. */
.vote-row .vote-check {
  width: 22px;
  height: 22px;
  border-radius: 999px;
  background: #fff;
  color: var(--pantsy, #FF1744);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: calc(12px * var(--text-scale));
  line-height: 1;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
  margin-left: auto;
}
.vote-row.smarty .vote-check {
  color: #8A5A1A;
}

/* ---------------- Reveal card — GAME SHOW ----------------
   Konsistent struktur over alle reveal-typer: eyebrow → mascot → stage label
   → big display → coaching footer. Card = dark gradient med fire-tinted border.
   Pantsy-variant = solid pantsy-rød med inner heat-glow.
   Smarty-variant = cream med soft gold glow. */
.reveal-card {
  /* D-091 (Pantsy-8 Batch 24): reveal cards tightened to 22px top so the eyebrow sits
     closer to the top edge as in design. */
  background: linear-gradient(160deg, var(--surface-hi) 0%, var(--surface-lo) 100%);
  color: var(--text-on-deep);
  border: 1px solid rgba(255, 87, 34, 0.20);
  border-radius: var(--radius-card);
  padding: 22px 24px 28px;
  text-align: center;
  box-shadow: var(--shadow-lg);
  /* Prinsipp 2: card fyller all plass mellom outer-eyebrow og bottom-CTA.
     min-height beholdes som fallback; flex:1 vinner når .screen er full-height. */
  min-height: 320px;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 10px;
  position: relative;
  overflow: hidden;
}
/* Soft glow i øverste høyre hjørne — gir warmth uten å være distraherende
   D-079 (Pantsy-8 Batch 15 round 2): 0.32 still read dim; bumping further to 0.50 with
   a slightly larger 260px footprint and a touch more amber so the warm halo lands
   visibly comparable to design's distinct radial heat. */
.reveal-card::before {
  content: "";
  position: absolute;
  top: -70px;
  right: -70px;
  width: 260px;
  height: 260px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 130, 50, 0.50) 0%, rgba(255, 87, 34, 0.20) 40%, transparent 75%);
  pointer-events: none;
}
.reveal-card.pantsy {
  background: var(--pantsy);
  color: #fff;
  border-color: var(--pantsy-hi);
}
.reveal-card.pantsy::before {
  /* Inner heat — bunn-sentrert, varmere */
  top: auto;
  bottom: -80px;
  left: 50%;
  right: auto;
  transform: translateX(-50%);
  width: 280px;
  height: 280px;
  background: radial-gradient(circle, rgba(255, 180, 80, 0.40) 0%, rgba(255, 80, 40, 0.18) 40%, transparent 70%);
  animation: pantsyHeatBreathe 3.4s ease-in-out infinite;
}
@keyframes pantsyHeatBreathe {
  0%, 100% { opacity: 0.55; transform: translateX(-50%) scale(1); }
  50%      { opacity: 0.90; transform: translateX(-50%) scale(1.05); }
}
.reveal-card.smarty {
  background: var(--surface-card);
  color: var(--text-on-card);
  border-color: var(--gold);
}
.reveal-card.smarty::before {
  background: radial-gradient(circle, var(--gold-glow) 0%, transparent 65%);
  animation: smartyGlow 4s ease-in-out infinite;
}
@keyframes smartyGlow {
  0%, 100% { opacity: 0.45; transform: scale(1); }
  50%      { opacity: 0.75; transform: scale(1.03); }
}
.reveal-card .cat-label {
  font-size: calc(11px * var(--text-scale));
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 800;
  opacity: 0.7;
  position: relative;
}
.reveal-card .stage-label {
  font-size: calc(11px * var(--text-scale));
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 700;
  opacity: 0.7;
  position: relative;
}
.reveal-card .word {
  font-family: var(--font-display);
  /* D-082, D-088 (Pantsy-8 user-decision after design review): pushing to 72px to match
     the design pack's apparent visual size (~80px). The role/word reveal is a dramatic
     stage moment — bigger feels more cinematic and matches the eye-test against design.
     Bølge 94 (2026-05-10): swap static 72px for `clamp(40px, 14vw, 72px)` so long
     proper-noun words ("Kim Kardashian", "Methusalem") shrink to fit the cream
     card's ~340px content width on 390px-wide phones instead of breaking
     mid-character. Default size for short words is unchanged (clamp ceiling
     = 72px). `word-break: keep-all` bans char-level wraps (the actual P0
     bug); `overflow-wrap` retained so word-boundary wrap still works.
     `hyphens: auto` is a graceful-degradation fallback for ultra-long
     single words — browser-native syllable hyphenation only kicks in when
     even clamped sizing can't fit the whole word on one line. */
  font-size: clamp(calc(40px * var(--text-scale)), 14vw, calc(72px * var(--text-scale)));
  font-weight: 700;
  letter-spacing: -0.035em;
  line-height: 0.95;
  margin: 10px 0 0;
  word-break: keep-all;
  overflow-wrap: break-word;
  hyphens: auto;
  position: relative;
}
/* Pre-reveal (neutral card) keeps responsive sizing capped at 56px — design uses 56 there. */
.reveal-card:not(.pantsy):not(.smarty) .word {
  font-size: calc(clamp(40px, 12vw, 56px) * var(--text-scale));
}
/* Coaching footer — separated by hairline, calmer copy under big display */
.reveal-card .coaching {
  border-top: 1px solid rgba(255, 255, 255, 0.10);
  padding-top: 14px;
  font-size: calc(13px * var(--text-scale));
  line-height: 1.5;
  opacity: 0.85;
  margin-top: auto;
  position: relative;
}
.reveal-card.smarty .coaching {
  border-top-color: rgba(26, 8, 32, 0.10);
}

/* SVG flame mascot på pre-reveal card — sentered, soft glow ring rundt */
.reveal-flame {
  align-self: center;
  margin-bottom: 18px;
  position: relative;
}
.reveal-flame::before {
  content: "";
  position: absolute;
  inset: -28px;
  background: radial-gradient(circle, rgba(255, 87, 34, 0.30) 0%, transparent 65%);
  animation: revealPulse 2.8s ease-in-out infinite;
  pointer-events: none;
}
.reveal-flame svg {
  position: relative;
  transform-origin: 50% 100%;
  animation: revealFlameFlicker 2s ease-in-out infinite;
  filter: drop-shadow(0 4px 14px rgba(255, 87, 34, 0.55));
}
@keyframes revealPulse {
  0%, 100% { opacity: 0.4; transform: scale(1); }
  50%      { opacity: 0.7; transform: scale(1.05); }
}
@keyframes revealFlameFlicker {
  0%, 100% { transform: scaleY(1) rotate(-2deg); }
  33%      { transform: scaleY(1.06) rotate(3deg); }
  66%      { transform: scaleY(0.96) rotate(-3deg); }
}

/* Pantsy-emoji wrapper for in-game (small, used in scoreboard rows) */
.reveal-card .pantsy-emoji {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 2px;
  font-size: 0;
  margin-bottom: 4px;
}
.reveal-card .pantsy-emoji .pe-pants { font-size: calc(50px * var(--text-scale)); line-height: 1; }
.reveal-card .pantsy-emoji .pe-fire {
  font-size: calc(36px * var(--text-scale));
  line-height: 1;
  filter: drop-shadow(0 0 8px var(--primary-glow));
  animation: pantsyFireFlicker 1.6s ease-in-out infinite alternate;
}
@keyframes pantsyFireFlicker {
  from { transform: scale(1) translateY(0); opacity: 1; }
  to   { transform: scale(1.08) translateY(-2px); opacity: .92; }
}
.reveal-card .hint {
  font-size: calc(14px * var(--text-scale));
  opacity: 0.85;
  margin-top: 6px;
}

.reverse-options-card {
  background: white;
  color: var(--card-fg);
  border-radius: 22px;
  padding: 24px;
  box-shadow: var(--shadow-lg);
}
.reverse-options-card .options-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-top: 12px;
}
.reverse-options-card .opt-tile {
  padding: 16px 12px;
  background: #f5ecd8;
  border: 2px solid var(--border);
  border-radius: 12px;
  font-weight: 700;
  text-align: center;
  font-size: calc(15px * var(--text-scale));
}

.tap-cover {
  background: linear-gradient(150deg, #1e293b 0%, #0f172a 100%);
  color: white;
  border-radius: 22px;
  padding: 60px 24px;
  text-align: center;
  cursor: pointer;
  min-height: 280px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 12px;
  border: 2px dashed rgba(255,255,255,.2);
}
.tap-cover .icon { font-size: calc(56px * var(--text-scale)); }

/* ---------------- Discuss screen ---------------- */
.starter-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);
  color: #2a1424;
  font-weight: 800;
  border-radius: 999px;
  align-self: center;
  box-shadow: 0 4px 12px rgba(251,191,36,.4);
}
.category-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  background: rgba(255, 244, 222, .10);
  border: 1px solid rgba(255, 244, 222, .18);
  border-radius: var(--radius-pill);
  font-size: calc(13px * var(--text-scale));
  font-weight: 600;
  font-family: var(--font-body);
  font-weight: 600;
  align-self: center;
}

/* ---------------- Timer ---------------- */
.timer {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 14px 20px;
  background: var(--surface-card-bright);
  color: var(--text-on-card);
  border-radius: 16px;
  font-size: calc(28px * var(--text-scale));
  font-weight: 900;
  font-variant-numeric: tabular-nums;
  box-shadow: var(--shadow);
}
.timer .label {
  font-size: calc(12px * var(--text-scale));
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 700;
  color: var(--muted);
}
.timer.warning {
  background: linear-gradient(135deg, #fef3c7, #fde68a);
}
.timer.danger {
  background: linear-gradient(135deg, #fee2e2, #fecaca);
  animation: pulse 1s ease-in-out infinite;
}
@keyframes pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.04); }
}

/* ---------------- Result ---------------- */
.banner {
  text-align: center;
  padding: 24px 18px;
  border-radius: 18px;
  font-size: calc(22px * var(--text-scale));
  font-weight: 900;
  margin-bottom: 8px;
}
.banner.caught { background: linear-gradient(135deg, #16a34a, #15803d); color: white; }
.banner.escaped { background: linear-gradient(135deg, var(--pantsy), var(--pantsy-2)); color: white; }
.banner .emoji { font-size: calc(36px * var(--text-scale)); display: block; margin-bottom: 6px; }

.delta-up { color: var(--success); font-weight: 700; }
.delta-down { color: var(--danger); font-weight: 700; }

/* Drama-reveal animation */
.drama-row {
  opacity: 0;
  transform: translateX(-12px);
  animation: dramaSlide .35s ease forwards;
}
@keyframes dramaSlide {
  to { opacity: 1; transform: translateX(0); }
}

/* Pulsing suspense på pantsy-reveal stage 0 */
@keyframes dramaPulse {
  from { transform: scale(1); opacity: 0.85; }
  to   { transform: scale(1.08); opacity: 1; }
}
.drama-suspense { cursor: pointer; }

/* ======= PANTSED-momentet =======
   Stage 1: pantsy avsløres med fallende bukse + "PANTSED!"-stempel.
   Hele kortet er den sentrale visuelle peak-en — STORT navn,
   roterende stempel (på engelsk: "rubber stamp" effect), bouncy entry. */
.pantsy-reveal-card {
  position: relative;
  background: linear-gradient(150deg, #2d1832 0%, #1a0e1f 100%);
  border: 1px solid rgba(245, 158, 11, .25);
  border-radius: 18px;
  padding: 22px 16px 18px;
  text-align: center;
  color: white;
  overflow: hidden;
  animation: pantsyBounce 0.85s cubic-bezier(0.34, 1.56, 0.64, 1);
  /* Flexbox-layout: ikon til venstre, tekst-blokken sentralt+balansert */
  display: flex;
  align-items: center;
  gap: 14px;
}
.pantsy-reveal-card .pantsy-card-text {
  flex: 1;
  min-width: 0;
  text-align: left;
}
/* Inne i flex-tekstblokk skal pantsy-name være litt mer kompakt — ellers wrapper for stygt
   ved siden av det 72px brede ikonet på smale skjermer */
.pantsy-reveal-card .pantsy-card-text .pantsy-name {
  font-size: calc(clamp(28px, 7.4vw, 42px) * var(--text-scale));
  margin: 2px 0 4px;
}
@keyframes pantsyBounce {
  0%   { opacity: 0; transform: scale(0.6) translateY(-30px); }
  35%  { opacity: 1; transform: scale(1.08) translateY(8px); }
  55%  { transform: scale(0.96) translateY(-4px); }
  72%  { transform: scale(1.03) translateY(2px); }
  88%  { transform: scale(0.99) translateY(-1px); }
  100% { opacity: 1; transform: scale(1) translateY(0); }
}
/* Beholder cardPop som alias for tilbakekompatibilitet (winner-banner bruker den) */
@keyframes cardPop {
  0%   { opacity: 0; transform: scale(0.85); }
  60%  { opacity: 1; transform: scale(1.03); }
  100% { opacity: 1; transform: scale(1); }
}

/* Pantsy-navnet — STORT, det største elementet på skjermen */
.pantsy-reveal-card .pantsy-name {
  font-family: "Bricolage Grotesque", system-ui, sans-serif;
  font-size: calc(clamp(34px, 9vw, 48px) * var(--text-scale));
  font-weight: 800;
  line-height: 1.05;
  margin: 4px 0 6px;
  color: #fef3c7;
  text-shadow: 0 2px 18px rgba(245, 158, 11, .35);
  letter-spacing: -0.02em;
}

/* Pantsy-icon på result-kort — flex-child til venstre, balansert med tekst-blokken.
   To varianter:
     - icon-caught (Pantsy ble tatt): 🔥 wiggler side-til-side (på fyr — pantsed!)
     - icon-escaped (Pantsy slapp unna): 👖 spinner rundt — bukse løp avgårde */
.pantsy-icon {
  font-size: calc(64px * var(--text-scale));
  line-height: 1;
  pointer-events: none;
  transform-origin: center center;
  flex-shrink: 0;
  width: 72px;
  text-align: center;
  z-index: 1;
}
.pantsy-icon.icon-caught {
  animation: pantsyFireWiggle 1.1s ease-in-out infinite;
  filter: drop-shadow(0 0 8px rgba(249,115,22,.55));
}
.pantsy-icon.icon-escaped {
  animation: pantsyJeansSpin 2.4s linear infinite;
}
@keyframes pantsyFireWiggle {
  0%, 100% { transform: rotate(-8deg) translateX(-2px) scale(1); }
  50%      { transform: rotate(8deg) translateX(2px) scale(1.06); }
}
@keyframes pantsyJeansSpin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* PANTSED!/ESCAPED!-stempel — rubber stamp effekt:
   pop in med scale-down + rotation, skarp border, semi-transparent for
   "trykket på papir" feel */
.stamp {
  position: absolute;
  top: 14px;
  right: -8px;
  font-family: "Bricolage Grotesque", system-ui, sans-serif;
  font-size: calc(24px * var(--text-scale));
  font-weight: 800;
  letter-spacing: 0.08em;
  padding: 6px 14px 5px;
  border: 3px solid currentColor;
  border-radius: 6px;
  text-transform: uppercase;
  transform: rotate(8deg) scale(1);
  opacity: 0.92;
  /* Pop-in animation med EKTE dramatic delay — pantsy-card bounces inn først (0.85s),
     pants faller (1.1s + 0.25s delay), så STEMPEL slår inn med suspense.
     Total: 1.4s pause før stempel = ekte "drumroll"-feel. */
  animation: stampPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) 1.4s both;
  z-index: 2;
  pointer-events: none;
}
/* Pantsy-navnet fades inn etter card-bounce er ferdig — gir tid til å bygge spenning
   før vi avslører hvem det var. */
.pantsy-reveal-card .pantsy-name {
  animation: pantsyNameReveal 0.5s ease-out 0.85s both;
}
@keyframes pantsyNameReveal {
  0%   { opacity: 0; transform: translateY(8px) scale(0.95); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
.stamp.pantsed {
  /* D-116 (Pantsy-8 Batch 11): design uses saturated red-pink. Bumped from #fb7185
     (washed pink) to var(--pantsy-hi) (#FF1744) for crisp, dramatic stamp. */
  color: var(--pantsy-hi);
  background: rgba(255, 23, 68, 0.10);
  border-color: var(--pantsy-hi);
  text-shadow: 0 1px 0 rgba(0, 0, 0, .3);
}
.stamp.escaped {
  /* D-133: design uses vibrant orange-red for ESCAPED (Pantsy got away — dramatic win).
     App was using green which read as "successful" but didn't match the design tone. */
  color: var(--pantsy-hi);
  background: rgba(255, 23, 68, 0.10);
  border-color: var(--pantsy-hi);
  text-shadow: 0 1px 0 rgba(0, 0, 0, .3);
}
@keyframes stampPop {
  0%   { opacity: 0; transform: rotate(8deg) scale(2.2); }
  50%  { opacity: 0.92; transform: rotate(8deg) scale(0.92); }
  75%  { transform: rotate(8deg) scale(1.04); }
  100% { opacity: 0.92; transform: rotate(8deg) scale(1); }
}

/* Vote-timer som horisontal progress bar. Fyll-bredde 100% → 0% over timer-perioden.
   Farge skifter fra amber (ok) → rød (danger) når det nærmer seg 0. Mer dramatisk enn ren tekst. */
.vote-timer-bar {
  /* D-102, D-110 (Pantsy-8 Batch 4): design timer is 44px tall with vivid gold→fire gradient
     and prominent "26s". App was 28px tall with a flatter yellow→amber gradient.
     Match design height + gradient. */
  position: relative;
  height: 44px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: 999px;
  overflow: hidden;
  margin: 8px 0 14px;
  isolation: isolate;
}
.vote-timer-bar-fill {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, var(--gold) 0%, var(--fire) 100%);
  /* Smooth interpolering — synker jevnt selv om JS oppdaterer hver 100ms */
  transition: width 0.12s linear, background 0.4s ease;
}
/* Bølge 64 P2 (2026-05-10): VoteTimer port to Pantsy9 design pack
   (`_audit/_pantsy9/07c.5-point-at-pantsy/screens-vote.jsx` line 27-30).
   Single `.urgent` flip at remaining ≤ 10 (was 2-tier data-urgency =
   warning|danger). Gradient swaps to pantsyRed→fire. Pulse animation
   moves from fill to text (subtler, matches design line 38). */
.vote-timer-bar.urgent .vote-timer-bar-fill {
  background: linear-gradient(90deg, var(--pantsy) 0%, var(--fire) 100%);
}
.vote-timer-bar.urgent .vote-timer-bar-text {
  animation: pantsy-vote-timer-pulse 0.6s ease-in-out infinite;
}
@keyframes pantsy-vote-timer-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.6; }
}
.vote-timer-bar-text {
  /* D-102 (Pantsy-8 Batch 4): bumped to 16px, 700 weight, design font for readability. */
  position: relative;
  z-index: 1;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(16px * var(--text-scale));
  letter-spacing: -0.01em;
  color: white;
  text-shadow: 0 1px 2px rgba(0,0,0,.4);
  font-variant-numeric: tabular-nums;
}

/* Confidence-popup overlay — vises når en kandidat tappes (ikke permanent UI) */
.conf-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: var(--z-overlay);
  padding: 20px;
  animation: toastIn 0.18s ease;
}
.conf-popup {
  background: var(--surface-card-bright);
  border-radius: 18px;
  padding: 18px;
  max-width: 360px;
  width: 100%;
  box-shadow: 0 20px 60px rgba(0,0,0,.4);
}
.conf-row {
  display: flex;
  gap: 8px;
  margin-top: 10px;
}
.conf-star {
  flex: 1;
  background: #f5ecd8;
  border: 1.5px solid var(--border);
  border-radius: 12px;
  padding: 12px 6px;
  cursor: pointer;
  font-family: inherit;
  transition: transform 0.1s ease, background 0.15s ease;
}
.conf-star:hover, .conf-star:active {
  background: #fef3c7;
  border-color: var(--secondary);
  transform: scale(1.04);
}

/* ======= End-of-game podium =======
   Vinner-banner → 3-plass podium → resten i kompakt liste → awards. */
.winner-banner {
  text-align: center;
  background: linear-gradient(150deg, #2d1832 0%, #1a0e1f 100%);
  border: 1px solid rgba(245, 158, 11, .3);
  border-radius: 22px;
  padding: 24px 18px 18px;
  color: white;
  animation: cardPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.winner-banner .winner-tag {
  font-size: calc(11px * var(--text-scale));
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 800;
  color: var(--secondary);
  margin: 6px 0 2px;
}
.winner-banner .winner-name {
  font-family: "Bricolage Grotesque", system-ui, sans-serif;
  font-size: calc(clamp(36px, 9vw, 50px) * var(--text-scale));
  font-weight: 800;
  line-height: 1.05;
  color: #fef3c7;
  text-shadow: 0 2px 18px rgba(245, 158, 11, .35);
  letter-spacing: -0.02em;
}
.winner-banner .winner-score {
  font-size: calc(14px * var(--text-scale));
  font-weight: 700;
  color: rgba(255, 255, 255, 0.65);
  margin-top: 2px;
}

.podium-row {
  display: flex;
  justify-content: center;
  align-items: flex-end;
  gap: 10px;
  margin-top: 12px;
  padding: 0 6px;
}
.podium-slot {
  flex: 1;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 0;
}
.podium-avatar {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--secondary);
  color: #1a0e1f;
  font-weight: 800;
  font-size: calc(18px * var(--text-scale));
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 4px;
}
.podium-name {
  font-size: calc(13px * var(--text-scale));
  font-weight: 700;
  color: white;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.podium-pts {
  font-size: calc(12px * var(--text-scale));
  font-weight: 700;
  color: rgba(255,255,255,.6);
  margin-bottom: 6px;
}
.podium-block {
  width: 100%;
  background: rgba(255,255,255,.08);
  border-radius: 8px 8px 0 0;
  padding: 14px 0;
  font-weight: 800;
  font-size: calc(16px * var(--text-scale));
  color: rgba(255,255,255,.55);
}
.podium-slot.rank-1 .podium-block { background: linear-gradient(180deg, var(--secondary), var(--secondary-2)); color: #1a0e1f; padding: 30px 0 24px; }
.podium-slot.rank-2 .podium-block { background: rgba(255,255,255,.18); color: white; padding: 22px 0 18px; }
.podium-slot.rank-3 .podium-block { background: rgba(255,255,255,.10); color: white; padding: 16px 0 14px; }
.podium-slot.rank-1 .podium-avatar { background: var(--secondary); width: 56px; height: 56px; font-size: calc(20px * var(--text-scale)); box-shadow: 0 0 0 3px rgba(245,158,11,.4); }

.rest-list {
  background: rgba(255,255,255,.04);
  border-radius: 12px;
  margin-top: 12px;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.rest-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 4px;
  color: rgba(255,255,255,.85);
}
.rest-rank { min-width: 28px; font-weight: 800; color: rgba(255,255,255,.45); font-size: calc(13px * var(--text-scale)); text-align: center; }
.rest-name { flex: 1; font-size: calc(14px * var(--text-scale)); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rest-score { font-weight: 800; font-size: calc(14px * var(--text-scale)); }

.awards-grid {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.award-card {
  display: flex;
  align-items: center;
  gap: 12px;
  background: linear-gradient(135deg, rgba(245,158,11,.18), rgba(245,158,11,.06));
  border: 1px solid rgba(245,158,11,.3);
  border-radius: 12px;
  padding: 12px 14px;
  color: white;
}
.award-icon { font-size: calc(32px * var(--text-scale)); }
.award-title { font-size: calc(11px * var(--text-scale)); text-transform: uppercase; letter-spacing: 0.08em; font-weight: 800; color: var(--secondary); }
.award-name { font-size: calc(18px * var(--text-scale)); font-weight: 800; line-height: 1.1; margin-top: 2px; color: #fef3c7; }
.award-sub { font-size: calc(12px * var(--text-scale)); opacity: 0.7; margin-top: 2px; }

/* Reduser motion-respekt — alle dramatiske animasjoner deaktiveres for brukere
   som har slått på "Reduce Motion" på OS-nivå. Vi beholder layout/sluttilstand,
   men dropper bouncy/spinning effekter. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .pantsy-icon { animation: none !important; }
  .stamp { transform: rotate(8deg); }
}

/* Settings collapse-knapp — visuell pille i header når settings-panelet er åpent.
   Tidligere var det bare en grå tekst-link som var lett å overse. Pillen har
   bakgrunn + ramme + clear "▴" chevron + tekst, så det er åpenbart at den lukker
   panelet. Holder samme paret-cream-tone som card-quiet for å ikke konkurrere
   med innholdet, men har nok kontrast til å bli sett. */
.settings-collapse-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  background: #efe7d2;
  border: 0.5px solid #d6c9ad;
  border-radius: 999px;
  color: #2a1424;
  cursor: pointer;
  font-family: inherit;
  line-height: 1;
  transition: background-color .15s ease, border-color .15s ease, transform .1s ease;
}
.settings-collapse-btn:hover {
  background: #e6dcc1;
  border-color: #b8a880;
}
.settings-collapse-btn:active {
  transform: scale(0.97);
}

/* Fokus-stil for tastatur-navigasjon — synlig outline når elementer fokuseres
   via Tab. Browsers default outline kan være knapt synlig på mørk bg. */
:focus-visible {
  outline: 2px solid var(--secondary);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Minimal scoreboard for round-result. Én tett linje per spiller — ingen avatarer,
   ingen badges, bare rank · navn · score · delta. */
.mini-board {
  background: rgba(255,255,255,.04);
  border-radius: 12px;
  padding: 6px 10px;
  display: flex;
  flex-direction: column;
}
.mini-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 4px;
  color: white;
  border-bottom: 0.5px solid rgba(255,255,255,.06);
  /* Slide-inn animasjon med staggered delay (satt i JS via inline style) */
  opacity: 0;
  transform: translateX(-8px);
  animation: miniRowIn 0.32s ease-out forwards;
}
@keyframes miniRowIn {
  to { opacity: 1; transform: translateX(0); }
}
.mini-row:last-child { border-bottom: none; }
.mini-row.top { color: var(--secondary); }
.mini-arrow {
  font-size: calc(11px * var(--text-scale));
  font-weight: 800;
  padding: 1px 5px;
  border-radius: 4px;
  font-variant-numeric: tabular-nums;
  /* Pop-in animasjon — gir live "rank changed!"-følelse */
  animation: arrowPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) 0.4s both;
}
.mini-arrow.up { color: #34d399; background: rgba(52,211,153,.15); }
.mini-arrow.down { color: #f87171; background: rgba(248,113,113,.15); }
@keyframes arrowPop {
  0%   { transform: scale(0); opacity: 0; }
  60%  { transform: scale(1.2); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
/* Delta-pille bouncer inn på samme måte */
.mini-delta {
  animation: arrowPop 0.5s cubic-bezier(0.34, 1.56, 0.64, 1) 0.5s both;
}
.mini-rank {
  min-width: 26px;
  font-weight: 800;
  font-size: calc(13px * var(--text-scale));
  color: rgba(255,255,255,.5);
  font-variant-numeric: tabular-nums;
}
.mini-row.top .mini-rank { color: var(--secondary); }
.mini-name {
  flex: 1;
  font-weight: 700;
  font-size: calc(15px * var(--text-scale));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mini-score {
  font-weight: 900;
  font-size: calc(16px * var(--text-scale));
  font-variant-numeric: tabular-nums;
  min-width: 36px;
  text-align: right;
}
.mini-delta {
  font-size: calc(12px * var(--text-scale));
  font-weight: 700;
  min-width: 38px;
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.mini-delta.up   { color: #34d399; }
.mini-delta.down { color: #f87171; }

/* Velocity-leaderboard: rank-arrows for rang-endring fra forrige runde */
.drama-leaderboard {
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: rgba(255,255,255,.04);
  border-radius: 14px;
  padding: 10px 8px;
}
.drama-leaderboard .player {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: rgba(255,255,255,.06);
  border-radius: 10px;
  color: white;
}
.drama-leaderboard .player.winner {
  background: linear-gradient(135deg, rgba(245,158,11,.35), rgba(245,158,11,.15));
  border: 1px solid rgba(245,158,11,.5);
}
.drama-leaderboard .player .name {
  flex: 1;
  font-weight: 700;
  font-size: calc(14px * var(--text-scale));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rank-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 30px;
  font-size: calc(12px * var(--text-scale));
  font-weight: 800;
  padding: 2px 6px;
  border-radius: 6px;
}
.rank-arrow.up   { color: #34d399; background: rgba(52,211,153,.12); }
.rank-arrow.down { color: #f87171; background: rgba(248,113,113,.12); }
.rank-arrow.flat { color: rgba(255,255,255,.35); background: transparent; }

/* ---------------- Misc ---------------- */
h2 { font-size: calc(24px * var(--text-scale)); margin: 0 0 4px; font-weight: 800; }
h3 { font-size: calc(18px * var(--text-scale)); margin: 0 0 8px; font-weight: 700; }
.subtitle { color: rgba(255,255,255,.7); margin: 0 0 8px; font-size: calc(14px * var(--text-scale)); }
.field { display: flex; flex-direction: column; gap: 6px; }
.field label { font-size: calc(13px * var(--text-scale)); font-weight: 600; color: var(--muted); }
.row { display: flex; gap: 10px; align-items: center; }
.row > * { flex: 1; }
.center { text-align: center; }
.muted { color: rgba(255,255,255,.65); font-size: calc(14px * var(--text-scale)); }
.tiny { font-size: calc(12px * var(--text-scale)); }
.divider { height: 1px; background: rgba(255,255,255,.10); margin: 12px 0; }
.hidden { display: none !important; }

/* Bølge 8 (2026-05-07) — F10/F3 footer-height per screen. Toast positioning
   uses var(--footer-height, 0px); these rules supply per-screen values so
   the toast clears any bottom action bar present. The screen scopes use
   :has() to set the variable on the document root context — the `.toast`
   itself is appended to body, not inside `.screen`, so we propagate via
   :has() on the screen wrapper. Browsers without :has() fall through to
   0px (toast still respects --safe-bottom + 24px). */
body:has(> #screen .lobby-screen),
body:has(> #screen .ended.final-screen),
body:has(> #screen .final-stand-judge-screen),
body:has(> #screen .pantsy-speaks-screen) {
  /* B44 D-014 (2026-05-09): bumped 56 → 80. The lobby bottom-actions
     stack — primary CTA (Need at least 2 players → / Start game →) plus
     the "Game settings · How it works ↘ · Leave" link row underneath —
     measures ~76px on iPhone-narrow once both rows are present + safe-
     area padding kicks in. Pre-B44 the 56px estimate was a single-row
     measurement; toasts fired during lobby ("✓ You're in! Waiting for
     others…") landed on top of the link row. 80px clears the full stack
     with a few px of headroom. */
  --footer-height: 80px;
}
.toast {
  position: fixed;
  /* --footer-height defaults to 0 and is bumped above for screens with a
     bottom action bar (lobby's "Game settings · Leave", game-end's "Play
     again · Exit", verdict screen's vote-row CTAs). --safe-bottom is the
     iOS home-indicator safe area. */
  bottom: calc(var(--safe-bottom, 0px) + var(--footer-height, 0px) + 24px);
  left: 50%;
  transform: translateX(-50%);
  background: rgba(15,23,42,.95);
  color: white;
  padding: 12px 20px;
  border-radius: 999px;
  font-size: calc(14px * var(--text-scale));
  font-weight: 600;
  box-shadow: var(--shadow-lg);
  z-index: var(--z-toast);
  animation: toastIn .25s ease;
}
@keyframes toastIn {
  from { opacity: 0; transform: translate(-50%, 10px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}

.code-display {
  /* GAME SHOW: JetBrains Mono med per-letter wave-animasjon */
  font-size: calc(clamp(40px, 14vw, 52px) * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.18em;
  text-align: center;
  font-family: var(--font-mono);
  color: var(--card-fg);
  padding: 4px 0;
  line-height: 1;
}
.code-display .code-letter {
  display: inline-block;
  animation: codeLetterWave 2.8s ease-in-out infinite;
}
@keyframes codeLetterWave {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-2px); }
}
@media (prefers-reduced-motion: reduce) {
  .code-display .code-letter { animation: none; }
}

.connection-status {
  font-size: calc(12px * var(--text-scale));
  color: rgba(255,255,255,.6);
  text-align: center;
  padding: 4px 0;
}
.connection-status.error { color: #fca5a5; }

/* ---------------- New: Settings widgets ---------------- */

/* Toggle switch */
.toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0;
  gap: 10px;
}
.toggle-row .label-block {
  flex: 1;
  min-width: 0;
}
.toggle-row .label-block .lbl {
  font-weight: 700;
  font-size: calc(15px * var(--text-scale));
  color: #2a1424;
}
.toggle-row .label-block .desc {
  font-size: calc(13px * var(--text-scale));
  color: #4a3d34;
  margin-top: 3px;
  line-height: 1.4;
}
.switch {
  position: relative;
  width: 48px;
  height: 28px;
  background: #e7d9bd;
  border-radius: 14px;
  cursor: pointer;
  flex-shrink: 0;
  transition: background .2s;
}
.switch::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 22px;
  height: 22px;
  background: white;
  border-radius: 50%;
  box-shadow: 0 2px 4px rgba(0,0,0,.2);
  transition: left .2s;
}
.switch.on { background: var(--primary); }
.switch.on::after { left: 23px; }
.switch.disabled { opacity: 0.4; cursor: not-allowed; }

/* Segmented control (for difficulty, timer etc.) */
.segmented {
  display: flex;
  background: #efe7d2;
  border-radius: 12px;
  padding: 4px;
  gap: 2px;
}
.segmented button {
  flex: 1;
  border: none;
  background: transparent;
  padding: 9px 8px;
  font-size: calc(13px * var(--text-scale));
  font-weight: 700;
  color: var(--muted);
  cursor: pointer;
  border-radius: 9px;
  font-family: inherit;
  transition: all .15s;
}
.segmented button.active {
  background: var(--surface-card-bright);
  color: var(--text-on-card);
  box-shadow: 0 2px 6px rgba(0,0,0,.1);
}

/* Multi-select category checkboxes */
.cat-grid {
  display: grid;
  /* minmax(0, 1fr) tillater at celler kan skrumpe under sitt min-content, så
     lange kategorinavn ikke pusher griden bredere enn parent-kortet */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 8px;
}
.cat-pill {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  background: #f5ecd8;
  border: 2px solid var(--border);
  border-radius: 10px;
  cursor: pointer;
  /* Disable text-selection ved long-press (vi bruker long-press til sample preview).
     Uten dette markerer iOS Safari teksten under fingeren. */
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  font-size: calc(14px * var(--text-scale));
  font-weight: 600;
  color: #2a1424;
  text-align: left;
  transition: all .15s;
  user-select: none;
}
.cat-pill .cat-icon { font-size: calc(18px * var(--text-scale)); }
.cat-pill .cat-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cat-pill .cat-count { font-size: calc(11px * var(--text-scale)); color: var(--muted); font-weight: 600; }
/* Adult-kategori: bruker rose/pantsy-sonen (spicy/edgy = thematisk match) */
.cat-pill.adult { border-color: var(--pantsy-glow); background: rgba(225, 29, 72, .04); }
/* Valgt-tilstand: sterk kontrast så host umiddelbart ser hva som er aktivt.
   Solid amber-fyll + mørk aubergine-tekst gir høy lesbarhet uten å skrike. */
/* GAME SHOW: selected = primary orange (CTA-farge), kraftig signal */
.cat-pill.selected {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
  font-weight: 700;
  box-shadow: 0 4px 12px var(--primary-glow);
}
.cat-pill.selected .cat-name { color: #fff; }
.cat-pill.selected .cat-count { color: rgba(255, 255, 255, 0.75); }
.cat-pill.selected.adult {
  background: var(--pantsy);
  border-color: var(--pantsy-2);
  color: #fff;
  box-shadow: 0 4px 12px var(--pantsy-glow);
}
.cat-pill.selected.adult .cat-name { color: #fff; }
.cat-pill.custom {
  background: linear-gradient(135deg, #ecfeff, #cffafe);
  border-color: #06b6d4;
}

/* QR code — cream bg matcher resten av code-card (ikke ren hvit som stikker ut) */
.qr-container {
  display: flex;
  justify-content: center;
  padding: 16px;
  background: var(--surface-card);
  border-radius: 12px;
  margin-top: 12px;
}
.qr-container > div { display: block; }
.qr-container img, .qr-container canvas { display: block; }

/* Confidence vote stars */
.confidence-row {
  display: flex;
  justify-content: center;
  gap: 12px;
  padding: 12px 0;
}
.confidence-star {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: rgba(255,255,255,.10);
  border: 2px solid rgba(255,255,255,.2);
  color: white;
  font-size: calc(22px * var(--text-scale));
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
}
.confidence-star.selected {
  background: linear-gradient(135deg, var(--gold), var(--primary));
  border-color: transparent;
  color: #2a1424;
  transform: scale(1.1);
}

/* Onboarding modal
   D-062 (Pantsy-8 Batch 19): backdrop alpha was 0.85 with only 4px blur, allowing
   lobby content (SRXC code, share row, Start game) to read through clearly. Design
   shows fully blurred / dim backdrop where the underlying screen is suggested but not
   readable. Bump to 0.92 alpha + 8px blur — modal becomes the unambiguous focus. */
.onboard-overlay {
  position: fixed;
  inset: 0;
  /* Bølge 46.1 (2026-05-09): bg color shifted from slate-blue
     rgba(15,23,42,.92) to deep-purple rgba(15,4,24,0.94) — matches the
     page bg token (#0F0418) so any residual translucency reads as a
     darker page rather than a blue-tinted halo at the modal-card edge.
     Stian flagged the Recovery code modal showing Profile content
     bleeding through during B47 smoke; root cause was the slate-blue
     mismatch + 0.92 alpha being insufficient at iPhone Safari.
     Bølge 168 (2026-05-13): routed through --modal-backdrop token. */
  background: var(--modal-backdrop);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: var(--z-overlay);
  padding: 20px;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  /* Mykt fade-in for backdrop + blur — føles mindre brått enn pop */
  animation: overlayFadeIn .2s ease-out both;
}
@keyframes overlayFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes modalFadeScale {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: scale(1); }
}
.onboard-modal {
  background: white;
  color: #2a1424;
  /* Bølge 168 (2026-05-13): routed through --radius-modal token (= 24px). */
  border-radius: var(--radius-modal);
  max-width: 380px;
  width: 100%;
  padding: 28px 22px;
  text-align: center;
  box-shadow: var(--shadow-lg);
  /* Mykere fade+scale i stedet for slideIn — føles mindre brå mellom intro-stegene */
  animation: modalFadeScale .25s cubic-bezier(.32, .72, .32, 1) both;
  /* Modal må scrolle internt på korte landscape-skjermer (iPhone SE landscape = 320px tall) */
  max-height: calc(100dvh - 32px);
  max-height: calc(100vh - 32px);
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.onboard-modal .step-icon { font-size: calc(56px * var(--text-scale)); margin-bottom: 8px; }
img.step-icon {
  display: block;
  margin: 0 auto 8px;
  width: 72px;
  height: 72px;
  border-radius: 16px;
  font-size: 0;
}
.onboard-modal h2 { color: #2a1424; }
.onboard-modal .desc {
  font-size: calc(15px * var(--text-scale));
  color: #4a3d34;
  line-height: 1.5;
  margin: 12px 0 20px;
}
.onboard-dots {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin: 16px 0;
}
.onboard-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #e7d9bd;
}
.onboard-dot.active { background: var(--primary); width: 24px; border-radius: 4px; }

/* Onboarding-stegene skal alle ha SAMME størrelse — ellers hopper modalen
   visuelt mellom stegene fordi tekstmengden varierer. Vi gir den en min-høyde
   som passer det LENGSTE steget, og lar step-body fylle plassen så dots og
   knapper alltid sitter nederst. */
.onboard-modal.onboarding-step {
  min-height: 460px;
  display: flex;
  flex-direction: column;
}
.onboard-step-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  /* Step-content-crossfade — ny step entrer fra høyre, gammel forlater til venstre.
     Tidligere fjernet vi hele overlay-elementet ved hvert step-skifte, som ga
     flicker (overlay-fadeIn + modal-bounce kjørte på nytt). Nå er overlay+modal
     persistent og kun innholdet i .onboard-step-body krysses inn/ut. */
  transition: opacity 200ms ease-out, transform 240ms cubic-bezier(.32, .72, .32, 1);
  will-change: opacity, transform;
}
/* JS setter inline-styles for direction-aware transitions
   (forward = -14px, back = +14px), så vi trenger ikke separate is-leaving-klasser.
   Når step-body er persistent, må btn-row + dots også reflektere ny step-state
   uten flicker — de fades sammen med body-en. */
.onboard-modal.onboarding-step .onboard-dots,
.onboard-modal.onboarding-step .btn-row {
  transition: opacity 180ms ease-out;
}
.onboard-modal.onboarding-step.swap-fade .onboard-dots,
.onboard-modal.onboarding-step.swap-fade .btn-row {
  opacity: 0.4;
}
/* På veldig lave skjermer (landscape iPhone SE) — drop min-height så modalen
   ikke tvinger scroll. Designet kompromisset: behaviour OK for mobile portrait
   som er 99% av use-casen. */
@media (max-height: 500px) {
  .onboard-modal.onboarding-step { min-height: 0; }
}
/* Reduced motion — slå av crossfade-transformer, behold opacity-fade */
@media (prefers-reduced-motion: reduce) {
  .onboard-step-body { transition: opacity 120ms ease-out; transform: none !important; }
  .onboard-step-body.is-leaving,
  .onboard-step-body.is-entering { transform: none !important; }
}

/* Auto-pick "Tonight's mix" overlay — kort discovery-moment når host velger
   tilfeldige kategorier. Kategori-emojiene rasler inn én etter én. */
.auto-pick-mix {
  position: fixed;
  inset: 0;
  z-index: var(--z-sheet);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  background: rgba(26, 14, 31, 0.45);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  animation: apmFadeIn .2s ease-out both;
}
.auto-pick-mix.apm-leaving { animation: apmFadeOut .25s ease-in forwards; }
@keyframes apmFadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes apmFadeOut { from { opacity: 1; } to { opacity: 0; } }
.apm-card {
  background: linear-gradient(135deg, var(--surface-card-bright), var(--surface-card));
  border: 2px solid var(--secondary);
  border-radius: 18px;
  padding: 20px 28px;
  box-shadow: 0 12px 40px rgba(0,0,0,.4), 0 0 0 4px rgba(245,158,11,.18);
  text-align: center;
  animation: apmCardIn .3s cubic-bezier(.34, 1.56, .64, 1) both;
}
@keyframes apmCardIn {
  0% { transform: scale(.7); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}
.apm-label {
  font-size: calc(11px * var(--text-scale));
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--secondary-2);
  margin-bottom: 10px;
}
.apm-emojis {
  display: flex;
  gap: 10px;
  justify-content: center;
}
.apm-emoji {
  font-size: calc(32px * var(--text-scale));
  line-height: 1;
  animation: apmEmojiIn .4s cubic-bezier(.34, 1.56, .64, 1) both;
  animation-delay: calc(var(--i, 0) * 90ms + 80ms);
}
@keyframes apmEmojiIn {
  0% { transform: translateY(-15px) rotate(-12deg); opacity: 0; }
  100% { transform: translateY(0) rotate(0); opacity: 1; }
}

/* Auto-pick stagger-animasjon — pillene fader inn én etter én når brukeren
   tapper "🎲 Auto-pick". --i er CSS-custom-property satt fra JS (idx 0..N).
   Subtil discovery-vibe uten å bli stort show. */
.cat-pills.auto-pick-anim .cat-pill-summary {
  animation: catPillFadeIn 0.32s cubic-bezier(.34, 1.56, .64, 1) both;
  animation-delay: calc(var(--i, 0) * 50ms);
}
@keyframes catPillFadeIn {
  0%   { opacity: 0; transform: translateY(-6px) scale(0.85); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

/* Klubb-leaderboard rows (i klubb-modalen) */
.club-leaderboard {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.club-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: #fbf6e7;
  border: 0.5px solid var(--border);
  border-radius: 10px;
}
.club-row.is-me {
  background: linear-gradient(135deg, #fff9e0, #fef3c7);
  border-color: var(--gold-deep);
  box-shadow: 0 0 0 2px var(--gold-glow);
}
.club-rank {
  font-family: var(--font-display);
  font-size: calc(16px * var(--text-scale));
  font-weight: 900;
  color: #a89a86;
  width: 30px;
  flex-shrink: 0;
}
.club-row.is-me .club-rank { color: #d97706; }
.club-name {
  flex: 1;
  min-width: 0;
  font-weight: 700;
  font-size: calc(14px * var(--text-scale));
  color: #2a1424;
  overflow: hidden;
}
.club-name-sub {
  font-size: calc(10.5px * var(--text-scale));
  color: #a89a86;
  font-weight: 500;
}
.club-stat-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
}
.club-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 28px;
}
.club-stat-val {
  font-weight: 900;
  font-size: calc(13px * var(--text-scale));
  color: #2a1424;
  line-height: 1;
}
.club-stat-lbl {
  font-size: calc(11px * var(--text-scale));
  margin-top: 1px;
  opacity: .6;
}

/* Stats-grid — kompakt 2-kol layout for stat-celler i Stats-modalen.
   Halverer høyden vs vertikal liste. Hver celle: stort tall + label + sub. */
.stats-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-bottom: 4px;
}
.stat-cell {
  background: #FBEFD9;
  border: 1px solid rgba(255, 210, 74, .25);
  border-radius: var(--radius-btn);
  padding: 12px 14px;
  text-align: left;
}
.stat-cell-val {
  font-family: var(--font-display);
  font-size: calc(28px * var(--text-scale));
  font-weight: 700;
  color: var(--text-on-card);
  line-height: 1;
  letter-spacing: -0.025em;
}
.stat-cell-lbl {
  font-size: calc(12px * var(--text-scale));
  font-weight: 600;
  color: var(--text-on-card);
  margin-top: 4px;
  line-height: 1.2;
}
.stat-cell-sub {
  font-size: calc(10.5px * var(--text-scale));
  color: var(--text-muted);
  margin-top: 2px;
  line-height: 1.2;
}

/* Achievements grid (i Stats-modal) */
.ach-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}
.ach-grid-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 10px 4px;
  border-radius: 10px;
  text-align: center;
  background: #f5ecd8;
  border: 0.5px solid var(--border);
  transition: transform .12s;
}
.ach-grid-item.unlocked {
  background: linear-gradient(135deg, #fff9e0, #fef3c7);
  border-color: var(--gold-deep);
}
.ach-grid-item.unlocked.rare {
  background: linear-gradient(135deg, #fde047, #fbbf24);
  border-color: #ca8a04;
  box-shadow: 0 0 0 2px rgba(251,191,36,.18);
}
.ach-grid-item.locked {
  opacity: 0.4;
  filter: grayscale(0.6);
}
.ach-grid-icon {
  font-size: calc(22px * var(--text-scale));
  line-height: 1;
}
.ach-grid-label {
  font-size: calc(9.5px * var(--text-scale));
  font-weight: 700;
  color: #2a1424;
  line-height: 1.2;
}

/* Achievement overlay — vises kort når en ny milestone unlockes.
   Bruker full-screen backdrop med dempet bakgrunn så hierarkiet er åpenbart:
   "her er noe spesielt, alt annet er nedtonet". Tap på backdrop = lukk. */
.ach-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-toast);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: calc(env(safe-area-inset-top) + 60px);
  background: rgba(26, 14, 31, 0.55);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  animation: achBackdropIn .25s ease-out both;
}
.ach-overlay > .ach-card {
  animation: achSlideIn .35s cubic-bezier(.34, 1.56, .64, 1) both;
}
@keyframes achBackdropIn {
  0%   { background: rgba(26, 14, 31, 0); backdrop-filter: blur(0); -webkit-backdrop-filter: blur(0); }
  100% { background: rgba(26, 14, 31, 0.55); backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px); }
}
.ach-overlay.ach-leaving {
  animation: achBackdropOut .3s ease-in forwards;
}
.ach-overlay.ach-leaving > .ach-card {
  animation: achSlideOut .3s ease-in forwards;
}
/* Bølge 2.20.7 (2026-05-09): the v2 overlay (Bølge 2.17 dispatcher) was
   missing leaving-animation rules — the dispatcher adds .ach-leaving but
   the existing rule only targeted .ach-overlay (v1). Without these rules
   the overlay disappears abruptly after the 350 ms removal delay; with
   them the fade-out reads correctly. Pure visual polish — no impact on
   the tap-blocking bug, but spotted while auditing the overlay path. */
.ach-overlay-v2.ach-leaving {
  animation: achBackdropOut .3s ease-in forwards;
}
.ach-overlay-v2.ach-leaving > .ach-toast-v2 {
  animation: achSlideOut .3s ease-in forwards;
}
@keyframes achSlideIn {
  0%   { transform: translateY(-30px); opacity: 0; }
  100% { transform: translateY(0); opacity: 1; }
}
@keyframes achSlideOut {
  0%   { transform: translateY(0); opacity: 1; }
  100% { transform: translateY(-30px); opacity: 0; }
}
@keyframes achBackdropOut {
  0%   { background: rgba(26, 14, 31, 0.55); }
  100% { background: rgba(26, 14, 31, 0); }
}
.ach-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  background: linear-gradient(135deg, #1a0e1f, #2d1832);
  border: 2px solid var(--gold);
  border-radius: 18px;
  padding: 14px 22px 16px;
  min-width: 240px;
  max-width: 320px;
  text-align: center;
  box-shadow: 0 12px 32px rgba(0,0,0,.4), 0 0 0 4px rgba(251,191,36,.15);
  pointer-events: auto;
}
.ach-card.ach-rare {
  border-color: #fde047;
  box-shadow: 0 12px 32px rgba(0,0,0,.4), 0 0 0 4px rgba(253,224,71,.25), 0 0 24px rgba(253,224,71,.4);
}
.ach-label {
  font-size: calc(10px * var(--text-scale));
  text-transform: uppercase;
  letter-spacing: 0.10em;
  font-weight: 800;
  color: var(--gold);
}
.ach-icon {
  font-size: calc(38px * var(--text-scale));
  line-height: 1;
  margin: 4px 0;
  filter: drop-shadow(0 2px 4px rgba(0,0,0,.3));
}
.ach-title {
  font-family: var(--font-display);
  font-size: calc(18px * var(--text-scale));
  font-weight: 900;
  color: white;
  letter-spacing: -0.01em;
}
.ach-desc {
  font-size: calc(12px * var(--text-scale));
  color: rgba(255,255,255,.75);
  line-height: 1.35;
  margin-top: 2px;
}
.ach-tap-hint {
  font-size: calc(10px * var(--text-scale));
  color: rgba(255,255,255,.4);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .08em;
  margin-top: 8px;
}
/* Combined achievement overlay — for 3+ unlocks samtidig */
.ach-card.ach-combined {
  min-width: 280px;
  max-width: 360px;
  padding: 16px 20px 14px;
}
.ach-combined-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  margin: 10px 0;
}
.ach-combined-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 10px 4px;
  background: rgba(255,255,255,.06);
  border: 0.5px solid rgba(251,191,36,.28);
  border-radius: 10px;
}
.ach-combined-item.ach-rare-item {
  background: rgba(253,224,71,.10);
  border-color: rgba(253,224,71,.45);
}
.ach-combined-icon {
  font-size: calc(26px * var(--text-scale));
  line-height: 1;
}
.ach-combined-title {
  font-size: calc(10px * var(--text-scale));
  font-weight: 700;
  color: rgba(255,255,255,.85);
  text-align: center;
  line-height: 1.15;
}

/* Joiner-strips — ULTRA-kompakt visning av kategori + settings for non-host.
   Joinere kan ikke endre noe — tar minst mulig vertikal plass. */
.joiner-cat-strip,
.joiner-settings-strip {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: rgba(0,0,0,.20);
  border: 0.5px solid rgba(255,255,255,.08);
  border-radius: 999px;
  color: rgba(255,255,255,.75);
  font-size: calc(12px * var(--text-scale));
  line-height: 1.2;
}
.joiner-cat-label,
.joiner-set-label {
  flex-shrink: 0;
  font-size: calc(14px * var(--text-scale));
  opacity: .7;
}
.joiner-cat-icons {
  flex: 1;
  font-size: calc(14px * var(--text-scale));
  letter-spacing: .12em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.joiner-cat-count,
.joiner-set-text {
  flex-shrink: 0;
  font-size: calc(11px * var(--text-scale));
  font-weight: 600;
  color: rgba(255,255,255,.55);
}
.joiner-set-text {
  flex: 1;
  text-align: left;
  font-size: calc(12px * var(--text-scale));
}

/* Player-join pulse — markerer en nylig joinet spiller i lobby (2s) */
.player.just-joined {
  animation: justJoinedPulse 1.8s ease-out;
  position: relative;
}
@keyframes justJoinedPulse {
  0%   { background: rgba(34,197,94,.20); transform: translateX(-4px); }
  20%  { background: rgba(34,197,94,.20); transform: translateX(0); }
  100% { background: transparent; }
}
.player.just-joined::after {
  content: "✨";
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  font-size: calc(14px * var(--text-scale));
  animation: justJoinedFade 1.8s ease-out forwards;
}
@keyframes justJoinedFade {
  0%, 60% { opacity: 1; }
  100%    { opacity: 0; }
}

/* Pass-gate — pass-the-phone overgang. Subtil pulse + actor-avatar */
.pass-gate { position: relative; }
.pass-gate .pass-phone-icon {
  font-size: calc(56px * var(--text-scale));
  animation: passGatePulse 1.6s ease-in-out infinite;
  display: inline-block;
}
.pass-gate .pass-actor-avatar {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: linear-gradient(135deg, #f97316, #ec4899);
  color: white;
  font-weight: 900;
  font-size: calc(24px * var(--text-scale));
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 12px auto 0;
  box-shadow: 0 6px 18px rgba(249,115,22,.35);
}
@keyframes passGatePulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50%      { transform: scale(1.08); opacity: 0.85; }
}

/* Vote-wait-progress — viser hvor mange som har stemt mens du venter */
.vote-wait-progress {
  width: 100%;
  height: 6px;
  background: rgba(0,0,0,.10);
  border-radius: 3px;
  margin-top: 10px;
  overflow: hidden;
}
.vote-wait-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--secondary), var(--secondary-2));
  border-radius: 3px;
  transition: width .4s ease;
}

/* B98.1 (2026-05-11): orphan `.vote-btn.dimmed` rule retired (legacy
   post-vote dimming; never re-wired after B64 P3 chassis swap to
   `.vote-row`). */

/* Code-mini — krympet code-block som vises når 2+ spillere er inne.
   Frigjør plass for Players + Start-knappen. Beholder kode synlig for senere joiners. */
.code-mini {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: rgba(0,0,0,.28);
  border: 0.5px solid rgba(255,255,255,.10);
  border-radius: 14px;
  flex-wrap: wrap;
}
.code-mini-label {
  font-size: calc(10px * var(--text-scale));
  text-transform: uppercase;
  letter-spacing: .08em;
  font-weight: 800;
  color: rgba(255,255,255,.55);
}
.code-mini-value {
  font-family: var(--font-display);
  font-size: calc(22px * var(--text-scale));
  font-weight: 900;
  color: white;
  letter-spacing: .12em;
  flex: 1;
}
.code-mini-btn {
  background: rgba(255,255,255,.10);
  border: 0.5px solid rgba(255,255,255,.18);
  color: white;
  border-radius: 8px;
  width: 36px;
  height: 36px;
  font-size: calc(16px * var(--text-scale));
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}
.code-mini-btn:hover { background: rgba(255,255,255,.18); }

/* Your clubs — kompakt liste-kort nederst på home med topp-3 klubber */
.clubs-card {
  background: linear-gradient(135deg, rgba(245,158,11,.10), rgba(225,29,72,.06));
  border: 0.5px solid rgba(245,158,11,.25);
  color: white;
  padding: 12px 14px;
}
.clubs-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
  gap: 8px;
}
.clubs-header-toggle {
  background: none;
  border: none;
  padding: 4px 0;
  width: 100%;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
}
.clubs-collapse-arrow {
  font-size: calc(14px * var(--text-scale));
  color: rgba(255,255,255,.5);
  font-weight: 700;
  margin-left: auto;
}
.clubs-label {
  font-size: calc(11px * var(--text-scale));
  text-transform: uppercase;
  letter-spacing: .08em;
  font-weight: 800;
  color: var(--gold);
}
.clubs-count {
  font-size: calc(11px * var(--text-scale));
  color: rgba(255,255,255,.55);
  font-weight: 600;
}
.clubs-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.clubs-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 0;
  background: none;
  border: none;
  width: 100%;
  text-align: left;
  cursor: pointer;
  font-family: inherit;
  color: inherit;
  transition: opacity .12s;
}
.clubs-row:hover { opacity: 0.85; }
.clubs-row:active { opacity: 0.75; }
.clubs-arrow {
  font-size: calc(18px * var(--text-scale));
  color: rgba(255,255,255,.4);
  font-weight: 700;
  flex-shrink: 0;
  margin-left: -2px;
}
.clubs-card-empty {
  background: rgba(255,255,255,.04);
  border-color: rgba(255,255,255,.10);
}

/* Club end-game stats — vises på end-screen hvis vi spiller med kjent klubb */
.club-end-stats {
  background: linear-gradient(135deg, rgba(245,158,11,.18), rgba(225,29,72,.10));
  border: 1px solid rgba(245,158,11,.4);
  border-radius: 14px;
  padding: 14px;
  margin: 16px 0 8px;
  color: white;
}
.club-end-stats-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}
.club-end-stats-label {
  font-size: calc(10px * var(--text-scale));
  text-transform: uppercase;
  letter-spacing: .08em;
  font-weight: 800;
  color: var(--gold);
}
.club-end-stats-name {
  font-family: var(--font-display);
  font-size: calc(18px * var(--text-scale));
  font-weight: 900;
  margin-top: 2px;
}
.club-end-stats-btn {
  background: rgba(255,255,255,.10);
  border: 0.5px solid rgba(255,255,255,.18);
  color: white;
  border-radius: 8px;
  width: 36px;
  height: 36px;
  font-size: calc(16px * var(--text-scale));
  font-weight: 700;
  cursor: pointer;
}
.club-end-stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
}
.club-end-stat { text-align: center; }
.club-end-stat-val {
  font-family: var(--font-display);
  font-size: calc(22px * var(--text-scale));
  font-weight: 900;
  color: white;
  line-height: 1;
}
.club-end-stat-lbl {
  font-size: calc(10px * var(--text-scale));
  font-weight: 600;
  color: rgba(255,255,255,.65);
  margin-top: 4px;
  line-height: 1.1;
}
.clubs-empty-explanation {
  margin-top: 6px;
  padding-top: 8px;
  border-top: 0.5px solid rgba(255,255,255,.08);
}
/* Klubb-tier badge — bronze/silver/gold/platinum basert på days played */
.club-tier-badge {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  padding: 6px 10px;
  background: rgba(0,0,0,.04);
  border: 0.5px solid rgba(0,0,0,.08);
  border-radius: 999px;
}
.club-tier-badge.club-tier-pre {
  background: rgba(0,0,0,.04);
  color: var(--text-muted);
}
.clubs-tier-icon {
  font-size: calc(14px * var(--text-scale));
  margin-left: 6px;
  opacity: .85;
  vertical-align: middle;
}
.reunite-tier {
  margin-left: 6px;
  font-size: calc(16px * var(--text-scale));
  vertical-align: middle;
}

/* Klubb-totaler grid (i klubb-modal) */
.club-totals {
  background: linear-gradient(135deg, #fff9e0, #faf3e0);
  border: 0.5px solid var(--gold-deep);
  border-radius: 12px;
  padding: 12px;
  margin-bottom: 14px;
}
.club-totals-label {
  font-size: calc(11px * var(--text-scale));
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--gold-deep);
  margin-bottom: 8px;
}
.club-totals-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
}
.club-total-item {
  text-align: center;
}
.club-total-val {
  font-family: var(--font-display);
  font-size: calc(22px * var(--text-scale));
  font-weight: 900;
  color: var(--text-on-card);
  line-height: 1;
}
.club-total-lbl {
  font-size: calc(10px * var(--text-scale));
  font-weight: 700;
  color: var(--text-muted);
  margin-top: 4px;
  line-height: 1.1;
}
.clubs-row + .clubs-row {
  border-top: 0.5px solid rgba(255,255,255,.08);
  padding-top: 8px;
}
.clubs-icon { font-size: calc(22px * var(--text-scale)); flex-shrink: 0; line-height: 1; }
.clubs-meta { flex: 1; min-width: 0; }
.clubs-name {
  font-size: calc(14px * var(--text-scale));
  font-weight: 800;
  line-height: 1.15;
  color: white;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.clubs-sub {
  font-size: calc(11px * var(--text-scale));
  color: rgba(255,255,255,.6);
  font-weight: 500;
  margin-top: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.clubs-time {
  font-size: calc(10.5px * var(--text-scale));
  color: rgba(255,255,255,.45);
  font-weight: 600;
  flex-shrink: 0;
}
.clubs-hint {
  font-size: calc(11px * var(--text-scale));
  color: rgba(255,255,255,.5);
  margin-top: 10px;
  padding-top: 8px;
  border-top: 0.5px solid rgba(255,255,255,.08);
  line-height: 1.4;
}

/* Title-pille på home — subtil, kompakt, ligger som en mild aksent på toppen
   av home-skjermen. Ikke konkurrerer med Lag/Bli med-knappene. */
.title-pill {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 14px;
  background: rgba(0, 0, 0, 0.28);
  border: 0.5px solid rgba(255, 255, 255, 0.10);
  border-radius: 999px;
  color: white;
  cursor: pointer;
  font-family: inherit;
  font-size: calc(13px * var(--text-scale));
  text-align: left;
  transition: background .15s, border-color .15s;
}
.title-pill:hover { background: rgba(0, 0, 0, 0.36); border-color: rgba(255,255,255,.18); }
.title-pill-icon {
  font-size: calc(20px * var(--text-scale));
  line-height: 1;
  flex-shrink: 0;
}
.title-pill-label {
  font-weight: 800;
  font-size: calc(14px * var(--text-scale));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
  min-width: 0;
}
.title-pill-ach {
  font-size: calc(11px * var(--text-scale));
  font-weight: 700;
  color: var(--gold);
  background: rgba(251, 191, 36, .12);
  padding: 2px 7px;
  border-radius: 999px;
  flex-shrink: 0;
}
.title-pill-next {
  font-size: calc(11px * var(--text-scale));
  color: rgba(255,255,255,.55);
  font-weight: 600;
  flex-shrink: 0;
  white-space: nowrap;
}
.title-pill-arrow {
  font-size: calc(16px * var(--text-scale));
  color: rgba(255,255,255,.4);
  font-weight: 700;
  flex-shrink: 0;
  margin-left: -2px;
}

/* Reunite-subseksjon i Players-kortet (gjengen er samlet igjen) */
.reunite-subsection {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  margin: 0 0 12px;
  background: linear-gradient(135deg, rgba(245,158,11,.18), rgba(236,72,153,.12));
  border: 1.5px solid rgba(245,158,11,.4);
  border-radius: 12px;
}
.reunite-icon {
  font-size: calc(28px * var(--text-scale));
  line-height: 1;
  flex-shrink: 0;
}
.reunite-meta {
  flex: 1;
  min-width: 0;
}
.reunite-label {
  font-size: calc(10px * var(--text-scale));
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 800;
  color: #b45309;
}
.reunite-title {
  font-size: calc(16px * var(--text-scale));
  font-weight: 900;
  line-height: 1.15;
  margin-top: 2px;
  color: #2a1424;
}
.reunite-sub {
  font-size: calc(12px * var(--text-scale));
  color: #78350f;
  opacity: .8;
  margin-top: 2px;
}
.reunite-tappable {
  cursor: pointer;
  transition: background .15s, transform .08s;
}
.reunite-tappable:active { transform: scale(.99); }
.reunite-arrow {
  font-size: calc(22px * var(--text-scale));
  color: #b45309;
  font-weight: 700;
  opacity: .55;
  flex-shrink: 0;
  margin-left: 4px;
}

.players-card {
  /* Litt mindre padding enn standard kort så reunite-banner og spillerliste føles tett */
}

/* Brand confirm modal — GAME SHOW redesign med SVG-glyphs (door/moon/flag/chili)
   White card, sentered glyph, big bricolage display title, side-by-side
   cancel/action buttons.
   Z-index: --z-confirm (top of stack) so brand-confirm always sits above
   achievement overlays. Without this, an achievement firing during a confirm
   would cover the cancel button. */
.brand-confirm {
  z-index: var(--z-confirm) !important;
}
.brand-confirm .brand-confirm-modal {
  max-width: 360px;
  padding: 26px 22px 18px;
  text-align: center;
  background: #FFFFFF;
  border-radius: 24px;
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.45);
}
.brand-confirm-glyph {
  display: flex;
  justify-content: center;
  margin-bottom: 14px;
  line-height: 0;
}
.brand-confirm-glyph svg { display: block; }
.brand-confirm-glyph.emoji-fallback {
  line-height: 1 !important;
}
.brand-confirm-icon {
  /* Legacy emoji support */
  font-size: calc(44px * var(--text-scale));
  line-height: 1;
  margin-bottom: 10px;
}
.brand-confirm-title {
  /* D-132, D-143 (user decision): reverted from 24px back to design source 26px. The
     verifier's "still too big" was a font-rendering pipeline quirk in the testing tool,
     not something users would notice on real devices. Trust the design source. */
  font-family: var(--font-display);
  font-size: calc(26px * var(--text-scale));
  font-weight: 700;
  color: #1A0820;
  margin: 0 0 10px;
  letter-spacing: -0.025em;
  line-height: 1.05;
}
.brand-confirm-msg {
  /* D-128 (Pantsy-8 Batch 2): drop horizontal padding 0 4px → 0 to give body 8px more
     usable width. Without this, "End game?" body wraps "scoreboard. You / can start"
     while design wraps "scoreboard. You can / start". 8px is enough to pull "can"
     onto line 1 and match the design break. */
  font-size: calc(15px * var(--text-scale));
  line-height: 1.45;
  color: #3F1A4A;
  margin: 0 0 22px;
  padding: 0;
}
.brand-confirm-actions {
  /* Match Pantsy-5 design ConfirmCard: cancel ~38%, primary ~62%
     så primary CTA dominerer visuelt. Tidligere 50/50 fikk Cancel
     til å se ut som likeverdig action. */
  display: grid;
  grid-template-columns: minmax(96px, 0.6fr) 1fr;
  gap: 10px;
}
/* Input-modal v2 (02c Add player) bruker samme rad — ingen override trengs */

.brand-confirm-actions .btn {
  /* Pantsy-8 D-CP-C: design confirm-modal buttons are ~46px, not the
     standard 52px. Tidligere arvet vi fra .btn min-height: 52px → for tunge
     i confirm-kontekst der modal selv er kompakt. */
  min-height: 46px;
  font-weight: 700;
  font-size: calc(16px * var(--text-scale));
  font-family: var(--font-display);
  letter-spacing: -0.01em;
  border-radius: 14px;
}
.brand-confirm-cancel {
  background: var(--surface-card) !important;
  color: var(--text-on-card) !important;
  border: none !important;
  box-shadow: none !important;
  animation: none !important;
}
.brand-confirm-action {
  /* Default = primary orange. Danger override styler nedenfor. */
}
.brand-confirm-action.danger,
.btn.brand-confirm-action.danger,
.btn-primary.brand-confirm-action.danger {
  /* Pantsy-pink CTA — match Add player / Leave / End now design.
     D-066: full flat — no shadow at all so verifier can't perceive any halo. */
  background: var(--pantsy) !important;
  border-color: var(--pantsy-hi) !important;
  color: #fff !important;
  box-shadow: none !important;
}
.brand-confirm-action.danger:hover,
.btn.brand-confirm-action.danger:hover {
  filter: brightness(1.06);
}
.brand-confirm-action.danger:active,
.btn.brand-confirm-action.danger:active {
  transform: translateY(1px);
}

/* ═══════════════════════════════════════════════════════════════════════
   Input modal v2 — match til Claude Designs ScreenAddPlayerPrompt
   Glyph + title side-by-side, helper-tekst, cream input med fire-border,
   side-by-side Cancel/Add med dynamisk label.
   ═══════════════════════════════════════════════════════════════════════ */
.input-modal-v2 {
  text-align: left;
}
.input-modal-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
}
.input-modal-glyph-wrap {
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: var(--surface-card);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.input-modal-glyph-wrap .brand-confirm-glyph {
  margin: 0;
}
.input-modal-glyph-wrap .brand-confirm-glyph svg {
  display: block;
}
.input-modal-header-text {
  flex: 1;
  min-width: 0;
}
.input-modal-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(18px * var(--text-scale));
  letter-spacing: -0.015em;
  line-height: 1.1;
  color: var(--ink);
}
.input-modal-subtitle {
  font-size: calc(12px * var(--text-scale));
  color: var(--ink-soft);
  margin-top: 2px;
}
.input-modal-description {
  font-size: calc(14px * var(--text-scale));
  color: var(--ink-soft);
  line-height: 1.45;
  margin: 0 0 8px;
  /* Match Pantsy-5 design 02c: helper er left-aligned (ikke sentrert) */
  text-align: left;
}
/* Cream input med fire-border (Claude Design pattern) */
.input-modal-v2 .input-modal-input-wrap {
  margin-bottom: 0;
}
.input-modal-v2 .input-modal-input {
  /* D-064 (Pantsy-8 Batch 21 round 2): tightened further — alpha 0.40→0.22, padding
     14→12, smaller font 18→16 so input matches design's slim hairline pill. */
  width: 100%;
  background: #F5F0E6;
  border: 1px solid rgba(255, 23, 68, 0.22);
  border-radius: 12px;
  padding: 12px 14px;
  font-family: var(--font-display);
  font-size: calc(16px * var(--text-scale));
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.01em;
  outline: none;
  box-shadow: none;
}
.input-modal-v2 .input-modal-input:focus {
  /* Faktisk focus-state — litt sterkere så det er tydelig hva som er aktivt.
     Explicit box-shadow none so no playwright auto-focus glow leaks through. */
  border-color: var(--pantsy);
  box-shadow: none;
}
.input-modal-v2 .input-modal-input::placeholder {
  color: rgba(63, 26, 74, 0.32);
  font-weight: 500;
  font-style: italic;
}
.input-modal-v2 .brand-confirm-actions {
  margin-top: 18px;
}

/* ═══════════════════════════════════════════════════════════════════════
   GAME SHOW: 13 Profile sheet — match Claude Designs ScreenProfile
   Identity card (avatar + name + tier-pill), 4-col Lifetime stat-strip,
   Achievements earned + next-up rows.
   ═══════════════════════════════════════════════════════════════════════ */
.profile-sheet-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.profile-section {
  padding: 0 4px;
}
.profile-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--text-faint);
  padding-left: 4px;
  margin-bottom: 10px;
}
.profile-eyebrow.next-up {
  margin-top: 14px;
}
.profile-row-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 10px;
}
.profile-row-header .profile-eyebrow {
  margin-bottom: 0;
}

/* Identity card */
.profile-identity-card {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 20px;
  background: linear-gradient(160deg, var(--surface-mid) 0%, var(--surface-deep) 100%);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-card);
}
.profile-avatar-big {
  width: 56px;
  height: 56px;
  border-radius: 999px;
  background: var(--primary);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(22px * var(--text-scale));
  letter-spacing: -0.01em;
  flex-shrink: 0;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
}
.profile-id-meta {
  flex: 1;
  min-width: 0;
}
.profile-id-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(22px * var(--text-scale));
  letter-spacing: -0.02em;
  line-height: 1.05;
  color: var(--text-on-deep);
  word-break: break-word;
}
.profile-tier-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 6px;
  padding: 3px 8px;
  background: rgba(255, 210, 74, 0.10);
  border: 1px solid rgba(255, 210, 74, 0.27);
  border-radius: 999px;
}
.profile-tier-pill .ptp-dot {
  width: 5px;
  height: 5px;
  border-radius: 999px;
  background: var(--gold);
}
.profile-tier-pill .ptp-text {
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  letter-spacing: 0.1em;
  font-weight: 700;
  color: var(--gold);
}

/* Bølge 128 (2026-05-11, ROADMAP #115) — cross-club connector pill.
   Subtle teal-tinted affordance distinct from the gold tier-pill above
   the identity name. Sits in its own .profile-section between identity
   card + the first content section, so it reads as a separate
   "you are a connector" beat without crowding the identity row. */
.profile-connector-section {
  padding: 0 4px;
}
.profile-connector-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  background: rgba(20, 184, 166, 0.10);
  border: 1px solid rgba(20, 184, 166, 0.30);
  border-radius: 999px;
  color: var(--text-soft, #d1d5db);
  font-family: inherit;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}
.profile-connector-pill:hover,
.profile-connector-pill:focus-visible {
  background: rgba(20, 184, 166, 0.16);
  border-color: rgba(20, 184, 166, 0.45);
  outline: none;
}
.profile-connector-pill .pcp-glyph {
  font-size: calc(13px * var(--text-scale));
  line-height: 1;
}
.profile-connector-pill .pcp-text {
  font-size: calc(13px * var(--text-scale));
  font-weight: 600;
  letter-spacing: 0;
}
.profile-connector-pill .pcp-chevron {
  font-size: calc(13px * var(--text-scale));
  color: var(--text-faint);
  margin-left: 2px;
}

/* 4-col stat-strip */
.profile-stats-strip {
  display: flex;
  background: var(--surface-mid);
  border-radius: var(--radius-btn);
  border: 1px solid rgba(255, 255, 255, 0.06);
  overflow: hidden;
}
.profile-stat {
  flex: 1;
  padding: 12px 8px;
  text-align: center;
  border-right: 1px solid rgba(255, 255, 255, 0.06);
}
.profile-stat:last-child { border-right: none; }
.profile-stat-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(26px * var(--text-scale));
  letter-spacing: -0.025em;
  line-height: 1;
  color: var(--text-on-deep);
}
.profile-stat.hi .profile-stat-num { color: var(--gold); }
.profile-stat-lbl {
  font-size: calc(10px * var(--text-scale));
  color: var(--text-faint);
  margin-top: 6px;
  text-transform: lowercase;
  letter-spacing: 0.04em;
}

/* Achievement rows — earned (gold gradient) + pending (subtle) */
.profile-ach-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  margin-bottom: 8px;
  border-radius: var(--radius-btn);
}
.profile-ach-row.earned {
  background: linear-gradient(135deg, rgba(255, 210, 74, 0.13) 0%, rgba(255, 210, 74, 0.03) 100%);
  border: 1px solid rgba(255, 210, 74, 0.33);
}
.profile-ach-row.pending {
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.06);
  opacity: 0.85;
}
.profile-ach-row .pa-icon {
  font-size: calc(22px * var(--text-scale));
  line-height: 1;
  flex-shrink: 0;
}
.profile-ach-row .pa-meta {
  flex: 1;
  min-width: 0;
}
.profile-ach-row .pa-title {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: calc(14px * var(--text-scale));
  letter-spacing: -0.01em;
  color: var(--text-on-deep);
  line-height: 1.2;
}
.profile-ach-row .pa-sub {
  font-size: calc(11px * var(--text-scale));
  color: var(--text-faint);
  margin-top: 3px;
  line-height: 1.3;
}
.profile-ach-row .pa-pill {
  font-size: calc(14px * var(--text-scale));
  font-weight: 700;
  color: var(--gold);
  flex-shrink: 0;
}
.profile-ach-row .pa-pill.mono {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.04em;
  color: var(--text-faint);
}
/* D-166 (Pantsy-8 user-decision): timestamp pill on earned achievements — small mono
   "Today" / "2d ago" instead of a generic ✓. Tells the user when they earned it. */
.profile-ach-row .pa-pill.pa-pill-time {
  font-family: var(--font-mono);
  font-size: calc(10.5px * var(--text-scale));
  font-weight: 600;
  color: var(--text-soft);
  letter-spacing: 0.02em;
}

/* Bølge 46 (2026-05-09): rich achievements rendering. Replaces the
   B28-N8 5-icon strip + B1.8 50-slot grid + B2.16-A panel-with-row +
   B30-N9 tile-fill lineage. New shape mirrors the design pack at
   _audit/_pantsy8/screens-2.jsx:1513–1546:
     • Earned cards   (gold gradient + glyph + name + percentile + date)
     • Next-up cards  (surface bg + tile-fill behind, glyph + name + hint)
     • "Next up" sub-eyebrow between the two groups
     • Empty-state hint (0 unlocks)
     • "See all ›" → full-screen .achievements-detail-sheet modal */

.profile-achievements-section {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.profile-achievements-section .profile-row-header {
  margin-bottom: 6px;
}

.ach-empty-hint {
  font-size: calc(12px * var(--text-scale));
  color: var(--text-faint);
  padding: 0 4px 4px;
  font-style: italic;
}

/* Earned card — gold gradient bg, gold border. Tap opens the existing
   showAchievementDetail explainer. Button chrome stripped so the card
   reads as a row, not a button-shaped object. */
.ach-earned-card,
.ach-nextup-card {
  appearance: none;
  -webkit-appearance: none;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  border-radius: var(--radius-btn);
  width: 100%;
  position: relative;
  overflow: hidden;
  transition: transform .08s, background .15s, border-color .15s;
}
.ach-earned-card {
  background: linear-gradient(135deg, rgba(255, 210, 74, 0.13) 0%, rgba(255, 210, 74, 0.04) 100%);
  border: 1px solid rgba(255, 210, 74, 0.35);
}
.ach-earned-card:active { transform: scale(0.99); }

/* Bølge 46.1 (2026-05-09): pulse-on-unlock animation. Surplus-link
   dispatcher (BADGES.md §2.2) writes _highlightAchievements when the
   user taps "+N andre låst opp" on a multi-unlock notification. The
   render side at app.js earnedCards adds .is-recently-unlocked to the
   matching cards; the keyframe here gold-pulses border + box-shadow
   for 3 cycles (matches the existing 3s setTimeout clear at
   app.js:11541). Animation is additive: idle border-color + shadow
   stay at the .ach-earned-card baseline, animation walks both up
   to a brighter gold + glow then back. */
@keyframes ach-pulse-on-unlock {
  0%   { border-color: rgba(255, 210, 74, 0.35); box-shadow: 0 0 0 0 rgba(255, 210, 74, 0.15); }
  50%  { border-color: rgba(255, 210, 74, 0.78); box-shadow: 0 0 18px 4px rgba(255, 210, 74, 0.32); }
  100% { border-color: rgba(255, 210, 74, 0.35); box-shadow: 0 0 0 0 rgba(255, 210, 74, 0.15); }
}
.ach-earned-card.is-recently-unlocked {
  animation: ach-pulse-on-unlock 1s ease-in-out 3;
}
.ach-earned-glyph {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: linear-gradient(135deg, var(--gold, #FFD24A) 0%, #FFC857 100%);
  color: var(--ink, #1A0820);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(20px * var(--text-scale));
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.ach-earned-meta {
  flex: 1;
  min-width: 0;
}
.ach-earned-name {
  font-weight: 600;
  font-size: calc(14px * var(--text-scale));
  color: var(--text-on-deep);
  letter-spacing: -0.005em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ach-earned-sub {
  font-size: calc(12px * var(--text-scale));
  color: var(--text-faint);
  margin-top: 2px;
}
.ach-earned-date {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  color: var(--text-faint);
  flex-shrink: 0;
  margin-left: 4px;
}

/* Next-up sub-eyebrow — sits between earned cards and next-up cards. */
.ach-section-eyebrow-nextup {
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-faint);
  padding: 8px 4px 4px;
}

/* Next-up card — surface bg with a gradient tile-fill behind the row
   driven by --tile-progress (set inline). Reuses the .ach-tile-bgfill
   gradient lineage from B30 N9 / B44 D-021 but anchored to the new
   row-shaped card instead of square tiles. */
.ach-nextup-card {
  background: var(--surface);
  border: 1px solid rgba(255, 255, 255, 0.06);
}
.ach-nextup-card:active { transform: scale(0.99); }
.ach-nextup-card .ach-tile-bgfill {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--tile-progress, 0%);
  background: linear-gradient(90deg,
    rgba(255, 210, 74, 0.18) 0%,
    rgba(255, 210, 74, 0.08) 100%);
  pointer-events: none;
  z-index: 0;
  transition: width 0.22s ease-out;
}
.ach-nextup-row {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 14px;
  flex: 1;
  min-width: 0;
}
.ach-nextup-glyph {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.05);
  color: var(--text-faint);
  font-size: calc(18px * var(--text-scale));
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.ach-nextup-meta {
  flex: 1;
  min-width: 0;
}
.ach-nextup-name {
  font-weight: 600;
  font-size: calc(13px * var(--text-scale));
  color: var(--text-soft);
  letter-spacing: -0.005em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ach-nextup-hint {
  font-size: calc(11px * var(--text-scale));
  color: var(--text-faint);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ach-see-all-link.profile-see-all-link {
  /* "See all ›" inherits .profile-see-all-link styling — keep the alias
     so future selectors can scope to either class without conflict. */
}

/* Bølge 59 (2026-05-09): Achievements section now sits inside the
   canonical .card.dark.profile-panel chassis (matches About You /
   Accessibility / Recovery / Lifetime). The default .profile-panel
   padding (6px 0) is built around .profile-panel-row's own 12-16px
   inner padding; the achievement cards already carry their own
   padding so we reset to a comfortable inner gutter and switch to
   flex-column with a row gap to keep cards visually separated
   without a hairline divider (the cards themselves carry borders
   + bg, so a divider would read as double-chrome). */
.profile-achievements-panel {
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.profile-achievements-panel .ach-empty-hint {
  padding: 4px 4px 0;
}
.profile-achievements-panel .ach-section-eyebrow-nextup {
  padding: 4px 4px 0;
}

/* ============================================================
   Achievements detail sheet — full-screen modal mounted via
   local.showAchievementsDetail. Listed earned + next-up + locked.
   ============================================================ */
.achievements-detail-overlay {
  position: fixed;
  inset: 0;
  /* Bølge 168 (2026-05-13): backdrop migrated rgba(0,0,0,0.78) → token
     --modal-backdrop. Aligns with .onboard-overlay family. */
  background: var(--modal-backdrop);
  display: flex;
  align-items: stretch;
  justify-content: center;
  z-index: 320;
  pointer-events: auto;
}
.achievements-detail-sheet {
  background: var(--bg, #0F0418);
  color: var(--text-on-deep);
  width: 100%;
  max-width: 460px;
  display: flex;
  flex-direction: column;
  padding: calc(env(safe-area-inset-top, 0) + 16px) 20px max(20px, env(safe-area-inset-bottom));
  overflow: hidden;
}
.achievements-detail-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 4px 14px;
}
.achievements-detail-done {
  flex: 0 0 auto;
  width: auto;
  min-width: 80px;
  padding: 8px 16px;
  min-height: 36px;
  font-size: calc(13px * var(--text-scale));
  font-weight: 600;
}
.achievements-detail-body {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  /* Bølge 60 (2026-05-09): bumped gap 6 → 10. Combined with the
     allow-wrapping override below, multi-line names + descriptions
     get visible breathing room between rows. Cowork smoke 2026-05-09
     reported "cards overlap each other" — investigation traced it to
     wrapped content butting up against neighbours at the tight 6px gap. */
  gap: 10px;
  padding-bottom: 16px;
}
.achievements-detail-row {
  display: flex;
  /* Bølge 60: align-items: flex-start (was center) so the glyph column
     pins to the top when name + description wraps to two or three
     lines. With center alignment + wrapping content the glyph
     visually "floats" at the row's vertical midpoint, which read as
     broken layout in the See-all sheet. */
  align-items: flex-start;
  gap: 14px;
  padding: 14px 16px;
  border-radius: var(--radius-btn);
  position: relative;
  overflow: hidden;
  background: var(--surface);
  border: 1px solid rgba(255, 255, 255, 0.06);
}
/* Bølge 60 (2026-05-09): allow text wrap inside See-all rows. The
   .ach-earned-name / .ach-earned-sub / .ach-nextup-name /
   .ach-nextup-hint base rules (lines ~3537+) lock white-space: nowrap
   + text-overflow: ellipsis so the home-screen profile cards stay
   one-line tall (those rows have a date column eating horizontal
   space). The See-all sheet has no date column and rows can be as
   tall as needed — clipping a 25-char award name with "..." reads as
   broken layout. Inside .achievements-detail-row, restore natural
   text flow + add hyphenation as a defensive fallback for very long
   single tokens (Norwegian compound words occasionally). */
.achievements-detail-row .ach-earned-name,
.achievements-detail-row .ach-earned-sub,
.achievements-detail-row .ach-nextup-name,
.achievements-detail-row .ach-nextup-hint,
.achievements-detail-row .ach-locked-name,
.achievements-detail-row .ach-locked-hint {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  word-break: break-word;
  hyphens: auto;
}
.achievements-detail-row-earned {
  background: linear-gradient(135deg, rgba(255, 210, 74, 0.13) 0%, rgba(255, 210, 74, 0.04) 100%);
  border-color: rgba(255, 210, 74, 0.35);
}
.achievements-detail-row-nextup .ach-tile-bgfill {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--tile-progress, 0%);
  background: linear-gradient(90deg,
    rgba(255, 210, 74, 0.18) 0%,
    rgba(255, 210, 74, 0.08) 100%);
  pointer-events: none;
  z-index: 0;
}
.achievements-detail-row-locked {
  background: rgba(255, 255, 255, 0.025);
  border: 1px dashed rgba(255, 255, 255, 0.14);
}
.achievements-detail-row-locked.legendary {
  background: rgba(255, 210, 74, 0.05);
  border-color: rgba(255, 210, 74, 0.30);
}
.ach-locked-glyph {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.04);
  color: rgba(255, 244, 222, 0.45);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(18px * var(--text-scale));
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.achievements-detail-row-locked.legendary .ach-locked-glyph {
  background: rgba(255, 210, 74, 0.06);
  color: rgba(255, 210, 74, 0.65);
}
.ach-locked-meta {
  flex: 1;
  min-width: 0;
}
.ach-locked-name {
  font-weight: 600;
  font-size: calc(13px * var(--text-scale));
  color: var(--text-faint);
  letter-spacing: -0.005em;
}
.ach-locked-hint {
  font-size: calc(11px * var(--text-scale));
  color: var(--text-faint);
  opacity: 0.75;
  margin-top: 2px;
}

/* Bølge 2.16 Item C (2026-05-07): a11y toggles wrapped in card.dark panel.
   The nested .gs-toggle-row would otherwise paint its own surface-mid
   background on top of the card's surface-mid, creating a flat-on-flat
   look. Strip the inner row chrome so toggles read as rows inside the
   card, separated only by a hairline divider. */
.profile-a11y-panel {
  padding: 6px 0;
}
.profile-a11y-panel .gs-toggle-row {
  background: transparent;
  border: 0;
  border-radius: 0;
  margin-bottom: 0;
  padding: 12px 16px;
}
.profile-a11y-panel .gs-toggle-row + .gs-toggle-row {
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.profile-a11y-panel .gs-toggle-row:hover {
  background: rgba(255, 255, 255, 0.03);
}
/* Bølge 28 N7 (2026-05-21): defensive guards. Stian reported the
   Accessibility panel "background changes a bit" on Larger-text toggle.
   Static CSS analysis didn't surface a deterministic root cause — no
   `.gs-toggle-row.on` rule exists, no non-font-size `--text-scale`
   dependency, `.card.dark` uses a solid colour (not a gradient that
   would visibly resize). The most-likely cause is a font-size-driven
   layout shift (calc(<px>*--text-scale) bumps text size, row grows
   ~2px taller, the panel's overall shape recomputes) that READS as
   "the bg changed" even though the colour token is invariant. The
   guards below pin (a) the panel's own bg/border/box-shadow against
   any future state-cascade and (b) the inner toggle-row to never
   inherit a `.on`-modifier bg shift. If the visual still drifts on
   real-device QA, the cause is layout reflow and we'll address it
   in a follow-up by capping row height. */
.profile-a11y-panel.card.dark,
body.a11y-larger-text .profile-a11y-panel.card.dark {
  background: var(--surface-mid);
  border-color: rgba(255, 255, 255, 0.06);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.32);
}
.profile-a11y-panel .gs-toggle-row,
.profile-a11y-panel .gs-toggle-row.on,
body.a11y-larger-text .profile-a11y-panel .gs-toggle-row,
body.a11y-larger-text .profile-a11y-panel .gs-toggle-row.on {
  background: transparent;
  border: 0;
}

/* Display name input + Avatar color rows — Pantsy-5 design 13.
   Subtile, low-emphasis form-felt nederst i sheet'et. */
.profile-field-label {
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin: 0 0 6px 4px;
}
.profile-name-input {
  width: 100%;
  padding: 12px 14px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: var(--radius-btn);
  font-family: var(--font-sans);
  font-size: calc(14px * var(--text-scale));
  font-weight: 600;
  color: var(--text-on-deep);
  letter-spacing: -0.01em;
  outline: none;
  transition: border-color .15s, background .15s;
}
.profile-name-input:focus {
  border-color: rgba(255, 87, 34, 0.42);
  background: rgba(255, 87, 34, 0.06);
}
.profile-color-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: var(--radius-btn);
}

/* ── Pantsy-9 follow-up #26 (2026-05-05): horizontal identity card ────
   Locked direction C1: drop the avatar-color row + language picker; show
   avatar + name only on a single horizontal card. Mirrors the design pack
   ScreenProfile (screens-2.jsx ~1402–1417). Avatar size 56px, color is
   passport-hashed (getLocalAvatarColor in app.js). */
.profile-identity-card-h {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 20px;
  background: linear-gradient(160deg, var(--surface-mid) 0%, var(--surface-deep) 100%);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-card);
}
.profile-identity-card-h .profile-avatar-big {
  /* Match design pack's 56px size — bigger than the old consolidated card's
     48px because there's no longer a stack of form fields competing for
     vertical real estate. */
  width: 56px;
  height: 56px;
  font-size: calc(22px * var(--text-scale));
  letter-spacing: -0.01em;
  flex-shrink: 0;
}
.profile-identity-card-h .profile-id-meta {
  flex: 1;
  min-width: 0;
}
/* Name input styled to look like a static display when unfocused. The input
   is always editable — it just doesn't shout "form field" until you tap it.
   Matches the design pack's "Stian Rognlid" big-display treatment. */
.profile-name-display.profile-name-input {
  width: 100%;
  padding: 0;
  background: transparent;
  border: none;
  border-bottom: 1px solid transparent;
  border-radius: 0;
  font-family: var(--font-display);
  font-size: calc(22px * var(--text-scale));
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.05;
  color: var(--text-on-deep);
  outline: none;
  transition: border-color .15s, background .15s;
}
.profile-name-display.profile-name-input:hover {
  border-bottom-color: rgba(255, 255, 255, 0.10);
}
.profile-name-display.profile-name-input:focus {
  border-bottom-color: rgba(255, 87, 34, 0.55);
  background: transparent;
}

/* ── Pantsy-9 consolidated identity-edit card (DEPRECATED 2026-05-05) ───
   Pre-Pantsy-9 vertical-stack card kept for older render paths during
   transition. New code uses .profile-identity-card-h above. */
.profile-identity-edit {
  max-width: 360px;
  margin: 0 auto;
  padding: 18px 18px 14px;
  background: linear-gradient(160deg, var(--surface-mid) 0%, var(--surface-deep) 100%);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-card);
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.profile-identity-edit .pie-avatar-row {
  display: flex;
  justify-content: center;
  margin-bottom: 2px;
}
.profile-identity-edit .pie-avatar-row .profile-avatar-big {
  /* Mindre enn den gamle 56px standalone-versjonen — den var visuelt for tung
     når den nå deler card med tre form-felt. */
  width: 48px;
  height: 48px;
  font-size: calc(18px * var(--text-scale));
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.22);
}
.profile-identity-edit .pie-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.profile-identity-edit .profile-field-label {
  margin: 0 0 0 2px;
}
/* Tetter form-control padding inne i card så cardet ikke blir for høyt. */
.profile-identity-edit .profile-name-input,
.profile-identity-edit .profile-color-row,
.profile-identity-edit .profile-lang-select {
  padding: 10px 12px;
  font-size: calc(13.5px * var(--text-scale));
}

/* Language <select> styled to match name-input + color-row tone. */
.profile-lang-select {
  width: 100%;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: var(--radius-btn);
  font-family: var(--font-sans);
  font-weight: 600;
  color: var(--text-on-deep);
  letter-spacing: -0.01em;
  outline: none;
  /* Native chevron styling — keeps dropdown UX consistent across platforms */
  -webkit-appearance: none;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--text-soft) 50%),
                    linear-gradient(135deg, var(--text-soft) 50%, transparent 50%);
  background-position: calc(100% - 18px) center, calc(100% - 13px) center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 32px !important;
  cursor: pointer;
}
.profile-lang-select:focus {
  border-color: rgba(255, 87, 34, 0.42);
  background-color: rgba(255, 87, 34, 0.06);
}
.profile-lang-select option {
  /* Native dropdown — dark surface for contrast on iOS/Android */
  background: #1A0820;
  color: var(--text-on-deep);
}
.pcr-swatch {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--primary);
  flex-shrink: 0;
  border: 1.5px solid rgba(255,255,255,0.18);
}
.pcr-name {
  font-size: calc(14px * var(--text-scale));
  font-weight: 600;
  color: var(--text-on-deep);
}

/* Detailed stats accordion */
.profile-collapse-toggle {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-btn);
  color: var(--text-soft);
  font-family: inherit;
  font-size: calc(13px * var(--text-scale));
  font-weight: 600;
  cursor: pointer;
}
.profile-detailed-stats {
  margin-top: 8px;
  padding: 12px 16px;
  background: rgba(255, 255, 255, 0.03);
  border-radius: var(--radius-btn);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.pds-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: calc(13px * var(--text-scale));
  color: var(--text-soft);
}
.pds-row .pds-val {
  font-family: var(--font-mono);
  font-weight: 700;
  color: var(--text-on-deep);
}

/* ═══════════════════════════════════════════════════════════════════════
   GAME SHOW: 13b Club sheet — match Claude Designs ScreenClub
   Identity hero (gold tier), totals strip, leaderboard, members + invite.
   ═══════════════════════════════════════════════════════════════════════ */
.club-sheet-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.club-section {
  padding: 0 4px;
}
.club-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--text-faint);
  padding-left: 4px;
  margin-bottom: 8px;
}
.club-eyebrow-mono {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  color: var(--text-faint);
  letter-spacing: 0.05em;
}
.club-row-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
  padding: 0 4px;
}

/* Identity hero — gold tinted card */
.club-identity-hero {
  position: relative;
  background: linear-gradient(160deg, rgba(255, 210, 74, 0.13) 0%, rgba(255, 87, 34, 0.06) 60%, var(--surface-deep) 100%);
  border: 1px solid rgba(255, 210, 74, 0.27);
  border-radius: var(--radius-card);
  padding: 20px 20px 18px;
  overflow: hidden;
}
.club-identity-hero .cih-watermark {
  position: absolute;
  right: -28px;
  bottom: -36px;
  font-size: calc(180px * var(--text-scale));
  opacity: 0.05;
  line-height: 1;
  pointer-events: none;
  color: var(--gold);
  font-family: var(--font-display);
  font-weight: 700;
}
.club-identity-hero .cih-content {
  position: relative;
}
.club-identity-hero .cih-tier-row {
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  letter-spacing: 0.1em;
  font-weight: 700;
  color: var(--gold);
  text-transform: uppercase;
}
.club-identity-hero .cih-name-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
}
.club-identity-hero .cih-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(26px * var(--text-scale));
  letter-spacing: -0.025em;
  line-height: 1.1;
  color: var(--text-on-deep);
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.club-identity-hero .cih-edit {
  background: none;
  border: none;
  color: var(--text-faint);
  opacity: 0.7;
  font-size: calc(14px * var(--text-scale));
  cursor: pointer;
  flex-shrink: 0;
  padding: 4px 6px;
}
.club-identity-hero .cih-sub {
  font-size: calc(12px * var(--text-scale));
  color: var(--text-soft);
  margin-top: 4px;
}
.club-identity-hero .cih-tier-progress {
  margin-top: 16px;
}
.club-identity-hero .ctp-labels {
  display: flex;
  justify-content: space-between;
  margin-bottom: 6px;
  font-size: calc(11px * var(--text-scale));
  color: var(--text-soft);
}
.club-identity-hero .ctp-next {
  color: var(--gold);
  font-family: var(--font-mono);
  letter-spacing: 0.05em;
}
.club-identity-hero .ctp-bar {
  width: 100%;
  height: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  overflow: hidden;
}
.club-identity-hero .ctp-bar-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--gold) 0%, var(--ember) 100%);
  border-radius: 999px;
  transition: width 0.4s ease;
}

/* Totals strip — 4 cells */
.club-totals-strip {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-card);
  padding: 14px 12px;
}
.club-totals-strip .cts-cell {
  text-align: center;
  padding: 4px;
  border-left: 1px solid rgba(255, 255, 255, 0.06);
}
.club-totals-strip .cts-cell:first-child { border-left: none; }
.club-totals-strip .cts-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(26px * var(--text-scale));
  letter-spacing: -0.02em;
  color: var(--text-on-deep);
  line-height: 1;
}
.club-totals-strip .cts-lbl {
  font-size: calc(10px * var(--text-scale));
  color: var(--text-faint);
  margin-top: 4px;
  text-transform: lowercase;
  letter-spacing: 0.02em;
}

/* Leaderboard — top spotlight + rest */
.club-leader-top {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  margin-bottom: 8px;
  background: linear-gradient(135deg, rgba(255, 210, 74, 0.13) 0%, rgba(255, 210, 74, 0.03) 100%);
  border: 1px solid rgba(255, 210, 74, 0.33);
  border-radius: var(--radius-card);
}
.club-leader-top .clt-rank {
  width: 22px;
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  font-weight: 700;
  color: var(--gold);
  flex-shrink: 0;
}
.club-leader-top .clt-avatar {
  width: 44px;
  height: 44px;
  border-radius: 999px;
  background: var(--gold);
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(16px * var(--text-scale));
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.club-leader-top .clt-meta {
  flex: 1;
  min-width: 0;
}
.club-leader-top .clt-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(18px * var(--text-scale));
  letter-spacing: -0.02em;
  line-height: 1.1;
}
.club-leader-top .clt-stats {
  font-size: calc(11px * var(--text-scale));
  color: var(--gold);
  font-family: var(--font-mono);
  letter-spacing: 0.05em;
  margin-top: 3px;
}
.club-leader-top .clt-score {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(20px * var(--text-scale));
  color: var(--gold);
  letter-spacing: -0.01em;
}

.club-leader-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  margin-bottom: 6px;
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-btn);
}
.club-leader-row.is-me {
  background: rgba(255, 87, 34, 0.08);
  border-color: rgba(255, 87, 34, 0.33);
}
.club-leader-row .clr-rank {
  width: 22px;
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  font-weight: 700;
  color: var(--text-faint);
  flex-shrink: 0;
}
.club-leader-row .clr-avatar {
  width: 32px;
  height: 32px;
  border-radius: 999px;
  background: var(--surface-hi);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(12px * var(--text-scale));
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.club-leader-row .clr-avatar.me { background: var(--primary); }
.club-leader-row .clr-meta {
  flex: 1;
  min-width: 0;
}
.club-leader-row .clr-name {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: calc(14px * var(--text-scale));
  color: var(--text-on-deep);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.club-leader-row .clr-you {
  color: var(--text-faint);
  font-weight: 500;
}
.club-leader-row .clr-stats {
  font-size: calc(10.5px * var(--text-scale));
  color: var(--text-faint);
  font-family: var(--font-mono);
  letter-spacing: 0.05em;
  margin-top: 2px;
}
.club-leader-row .clr-score {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(16px * var(--text-scale));
  color: var(--text-on-deep);
}

/* Invite card */
.club-invite-card {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: transparent;
  border: 1.5px dashed rgba(255, 87, 34, 0.4);
  border-radius: var(--radius-btn);
  padding: 12px 14px;
  margin-bottom: 8px;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
}
.club-invite-card .ci-icon {
  width: 28px;
  height: 28px;
  border-radius: 999px;
  background: rgba(255, 87, 34, 0.13);
  color: var(--primary);
  font-weight: 700;
  font-size: calc(14px * var(--text-scale));
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.club-invite-card .ci-meta {
  flex: 1;
  min-width: 0;
}
.club-invite-card .ci-title {
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: calc(13.5px * var(--text-scale));
  color: var(--primary);
}
.club-invite-card .ci-link {
  font-size: calc(11px * var(--text-scale));
  color: var(--text-faint);
  margin-top: 1px;
  font-family: var(--font-mono);
  letter-spacing: 0.04em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.club-invite-card .ci-cta {
  color: var(--primary);
  font-size: calc(13px * var(--text-scale));
  font-weight: 600;
  flex-shrink: 0;
}

/* Member rows */
.club-member-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  margin-bottom: 6px;
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-btn);
}
.club-member-row .cmr-avatar {
  width: 32px;
  height: 32px;
  border-radius: 999px;
  background: var(--surface-hi);
  color: #fff;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(12px * var(--text-scale));
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.club-member-row .cmr-avatar.me { background: var(--primary); }
.club-member-row .cmr-meta {
  flex: 1;
  min-width: 0;
}
.club-member-row .cmr-name {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: calc(14px * var(--text-scale));
  color: var(--text-on-deep);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.club-member-row .cmr-you {
  color: var(--text-faint);
  font-weight: 500;
}
.club-member-row .cmr-sub {
  font-size: calc(11px * var(--text-scale));
  color: var(--text-faint);
  margin-top: 1px;
}
.club-member-row .cmr-pill {
  display: inline-flex;
  align-items: center;
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(255, 210, 74, 0.13);
  color: var(--gold);
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  flex-shrink: 0;
}

/* Leave club button (footer) */
.club-leave-btn {
  width: 100%;
  padding: 12px 16px;
  background: transparent;
  color: var(--pantsy-hi);
  border: 1px solid rgba(255, 23, 68, 0.20);
  border-radius: var(--radius-btn);
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: calc(13px * var(--text-scale));
  cursor: pointer;
}
.club-leave-btn:hover {
  background: rgba(255, 23, 68, 0.06);
}

/* ═══════════════════════════════════════════════════════════════════════
   01c Loading screen — pulserende brand-glyph + label + 3 animerte dots.
   Erstatter gammel 📡-card under WebSocket connect/reconnect.
   ═══════════════════════════════════════════════════════════════════════ */
.loading-screen {
  display: flex;
  flex-direction: column;
}
.loading-center {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 24px;
  padding: 0 40px;
}
@keyframes pantsy-load-pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50%      { transform: scale(0.96); opacity: 0.85; }
}
@keyframes pantsy-load-dot {
  0%, 80%, 100% { opacity: 0.2; transform: translateY(0); }
  40%           { opacity: 1; transform: translateY(-3px); }
}
.loading-mascot {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  line-height: 0;
  animation: pantsy-load-pulse 1.6s ease-in-out infinite;
}
/* Cream-square app-icon tile (matcher 01c design) — 120px rounded square
   med polert PNG-ikon centered, soft warm shadow, gentle pulse. */
.loading-app-tile {
  width: 120px;
  height: 120px;
  border-radius: 24px;
  background: var(--surface-card, #FFF6E0);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 16px 36px rgba(0, 0, 0, 0.45),
              0 0 0 1px rgba(255, 244, 222, 0.06);
  animation: pantsy-load-pulse 1.8s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .loading-mascot, .loading-app-tile { animation: none; }
}
/* Mens app er i loading-mode: skjul topbar slik at splash-screen står
   ren mot full bakgrunn (matcher design 01c som ikke har topbar). */
body.loading-mode .app-topbar,
body.loading-mode .topbar { display: none !important; }
.loading-label-row {
  display: flex;
  align-items: baseline;
  gap: 4px;
  margin-top: 8px;
}
.loading-label {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-soft);
}
.loading-dots {
  display: inline-flex;
  gap: 3px;
  margin-left: 2px;
}
.loading-dot {
  width: 4px;
  height: 4px;
  border-radius: 999px;
  background: var(--text-soft);
  animation: pantsy-load-dot 1.2s ease-in-out infinite;
}
.loading-dot:nth-child(2) { animation-delay: 0.18s; }
.loading-dot:nth-child(3) { animation-delay: 0.36s; }
@media (prefers-reduced-motion: reduce) {
  .loading-dot { animation: none; opacity: 1; }
}
.loading-warn-hint {
  font-size: calc(13px * var(--text-scale));
  color: var(--warning, #FFD24A);
  font-weight: 600;
  margin-top: 8px;
  text-align: center;
}
.loading-leave-btn {
  margin-bottom: max(20px, env(safe-area-inset-bottom));
}

/* ═══════════════════════════════════════════════════════════════════════
   11 Final-screen — Pantsy-3 redesign med Final standings → Awards → Club totals.
   Pinned bottom CTAs: "Play again" primary + "Exit" ghost (ingen emoji, ingen panel).
   ═══════════════════════════════════════════════════════════════════════ */
.final-screen {
  display: flex;
  flex-direction: column;
}
.final-scroll-body {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding-bottom: 8px;
}
.final-section {
  padding: 0 4px;
}
.final-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--text-faint);
  padding-left: 4px;
  margin-bottom: 8px;
}
/* Final standings row */
.final-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 14px;
  margin-bottom: 4px;
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-btn);
  animation: pantsy-final-row-in 0.45s cubic-bezier(.2,.9,.3,1.2) both;
}
.final-row.final-row-winner {
  background: var(--surface-hi);
  border-color: rgba(255, 210, 74, 0.33);
  animation:
    pantsy-final-row-in 0.45s cubic-bezier(.2,.9,.3,1.2) both,
    pantsy-final-winner-halo 2.4s ease-in-out 0.45s infinite;
}
@keyframes pantsy-final-row-in {
  0%   { transform: translateY(8px); opacity: 0; }
  100% { transform: translateY(0); opacity: 1; }
}
@keyframes pantsy-final-winner-halo {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 210, 74, 0.33), 0 0 18px rgba(255, 210, 74, 0.13); }
  50%      { box-shadow: 0 0 0 4px rgba(255, 210, 74, 0), 0 0 28px rgba(255, 210, 74, 0.27); }
}
@media (prefers-reduced-motion: reduce) {
  .final-row, .final-row-winner { animation: none !important; }
}
.final-rank {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(16px * var(--text-scale));
  color: var(--text-faint);
  min-width: 18px;
  letter-spacing: -0.02em;
}
.final-row-winner .final-rank { color: var(--gold); }
.final-avatar {
  width: 24px;
  height: 24px;
  border-radius: 999px;
  background: var(--primary);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(11px * var(--text-scale));
  flex-shrink: 0;
}
.final-name {
  flex: 1;
  font-weight: 600;
  font-size: calc(14px * var(--text-scale));
  color: var(--text-on-deep);
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.final-score {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(16px * var(--text-scale));
  color: var(--text-soft);
  letter-spacing: -0.02em;
}
.final-row-winner .final-score { color: var(--text-on-deep); }

/* Award card */
.final-award-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px;
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-card);
}
.final-award-card .faw-icon {
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: rgba(255, 210, 74, 0.13);
  border: 1px solid rgba(255, 210, 74, 0.33);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(18px * var(--text-scale));
  line-height: 1;
  flex-shrink: 0;
}
.final-award-card .faw-meta { flex: 1; min-width: 0; }
.final-award-card .faw-tag {
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--gold);
}
.final-award-card .faw-name {
  font-weight: 600;
  font-size: calc(14px * var(--text-scale));
  margin-top: 2px;
  color: var(--text-on-deep);
}
.final-award-card .faw-sub {
  font-size: calc(12px * var(--text-scale));
  color: var(--text-faint);
  margin-top: 1px;
}

/* Club totals card (final-screen) */
.final-club-card {
  position: relative;
  background: linear-gradient(180deg, var(--surface-mid) 0%, var(--surface-deep) 100%);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-card);
  padding: 16px 18px;
  overflow: hidden;
}
.final-club-card .fcc-watermark {
  position: absolute;
  right: -24px;
  bottom: -28px;
  font-size: calc(140px * var(--text-scale));
  opacity: 0.04;
  line-height: 1;
  pointer-events: none;
  color: var(--gold);
  font-family: var(--font-display);
  font-weight: 700;
}
.final-club-card .fcc-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: relative;
  gap: 8px;
}
.final-club-card .fcc-meta { flex: 1; min-width: 0; }
.final-club-card .fcc-tag {
  display: block;
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--gold);
}
.final-club-card .fcc-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(22px * var(--text-scale));
  letter-spacing: -0.02em;
  margin-top: 2px;
  line-height: 1.1;
  color: var(--text-on-deep);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.final-club-card .fcc-btn {
  width: 32px;
  height: 32px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.1);
  color: var(--text-on-deep);
  cursor: pointer;
  font-size: calc(14px * var(--text-scale));
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.final-club-card .fcc-stats {
  margin-top: 14px;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 4px;
  position: relative;
}
.final-club-card .fcc-stat {
  text-align: center;
  padding: 8px 4px;
  border-left: 1px solid rgba(255, 255, 255, 0.06);
}
.final-club-card .fcc-stat:first-child { border-left: none; }
.final-club-card .fcc-stat-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(24px * var(--text-scale));
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--text-on-deep);
}
.final-club-card .fcc-stat-lbl {
  font-size: calc(10px * var(--text-scale));
  color: var(--text-faint);
  letter-spacing: 0.05em;
  margin-top: 4px;
  text-transform: lowercase;
}

/* Bottom CTAs — pinned, ingen panel rundt Exit-knappen */
.final-bottom-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 0 max(20px, env(safe-area-inset-bottom));
  flex-shrink: 0;
}

/* ═══════════════════════════════════════════════════════════════════════
   13a Clubs overview sheet — liste over alle klubber som tappbare cards.
   Match Claude Designs ScreenClubs.
   ═══════════════════════════════════════════════════════════════════════ */
.clubs-overview-body {
  display: flex;
  flex-direction: column;
  gap: 20px;
  padding: 0 4px;
}
.clubs-overview-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 0 16px;
}
.club-card {
  width: 100%;
  border-radius: var(--radius-card);
  padding: 16px 18px;
  position: relative;
  overflow: hidden;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  color: var(--text-on-deep);
  transition: transform 0.12s ease, box-shadow 0.12s ease;
}
.club-card:hover { transform: translateY(-1px); }
.club-card:active { transform: scale(0.99); }
.club-card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 6px;
}
.club-card-tag {
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.club-card-chevron {
  /* D-175 (Pantsy-8 user-decision): hide explicit chevron on club cards — design relies
     on whole-card tappability without the visual ›, which felt redundant against the
     tier label and rich card content. */
  display: none;
}
.club-card-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(22px * var(--text-scale));
  letter-spacing: -0.02em;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 12px;
  color: var(--text-on-deep);
}
.club-card-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  background: rgba(0, 0, 0, 0.18);
  border-radius: 12px;
  padding: 10px 12px;
  margin-bottom: 10px;
}
.club-card-stats .ccs-cell {
  min-width: 0;
}
.club-card-stats .ccs-cell-right {
  border-left: 1px solid rgba(255, 255, 255, 0.08);
  padding-left: 12px;
}
.club-card-stats .ccs-label {
  font-family: var(--font-mono);
  font-size: calc(9px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 3px;
}
.club-card-stats .ccs-value {
  font-family: var(--font-sans);
  display: flex;
  align-items: baseline;
  gap: 6px;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.club-card-stats .ccs-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(18px * var(--text-scale));
  color: var(--text-on-deep);
  letter-spacing: -0.01em;
}
.club-card-stats .ccs-name {
  font-weight: 700;
  font-size: calc(14px * var(--text-scale));
  color: var(--text-on-deep);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.club-card-stats .ccs-sub {
  font-weight: 600;
  font-size: calc(12px * var(--text-scale));
  color: var(--text-faint);
}
.club-card-moment {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: calc(12px * var(--text-scale));
  color: var(--text-soft);
}
.club-card-moment .ccm-dot {
  width: 6px;
  height: 6px;
  border-radius: 999px;
  flex-shrink: 0;
}
.club-card-moment .ccm-text {
  flex: 1;
  min-width: 0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.club-card-moment .ccm-when {
  color: var(--text-faint);
  font-size: calc(11px * var(--text-scale));
  flex-shrink: 0;
}

/* Empty state */
.clubs-overview-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 40px 24px;
  gap: 8px;
}

/* Info-card "Clubs are made for you" */
.clubs-info-card {
  margin: 0 16px;
  padding: 14px 16px;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-btn);
  display: flex;
  gap: 12px;
  align-items: flex-start;
}
.clubs-info-card .ci-icon-circle {
  flex-shrink: 0;
  margin-top: 1px;
  width: 22px;
  height: 22px;
  border-radius: 999px;
  background: rgba(255, 87, 34, 0.10);
  color: var(--primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: calc(12px * var(--text-scale));
}
.clubs-info-card .ci-content {
  flex: 1;
  min-width: 0;
}
.clubs-info-card .ci-title {
  font-size: calc(13px * var(--text-scale));
  font-weight: 600;
  color: var(--text-on-deep);
  margin-bottom: 3px;
}
.clubs-info-card .ci-body {
  font-size: calc(12px * var(--text-scale));
  color: var(--text-soft);
  line-height: 1.5;
}

/* ═══════════════════════════════════════════════════════════════════════
   GAME SHOW: Game settings (12) — Section / Seg / ToggleRow primitives
   Match Claude Designs ScreenSettings: title + hint + (Seg | ToggleRow).
   Dark surface cards, segmented controls med cream-on-active, native-look-switch.
   ═══════════════════════════════════════════════════════════════════════ */
.gs-panel {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.gs-section {
  padding: 0 4px;
}
.gs-eyebrow {
  /* D-159 (Pantsy-8 Batch 15 round 2): first pass at 0.06em/11px still read wider than
     design. Tightened further to 0.04em and 10.5px, weight 600 (less heavy). */
  font-family: var(--font-mono);
  font-size: calc(10.5px * var(--text-scale));
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--text-soft);
  padding-left: 2px;
  margin-bottom: 8px;
}
.gs-hint {
  /* D-160 (Pantsy-8 Batch 15 round 2): 11.5 still too heavy; 10.5 + 400 weight. */
  font-size: calc(10.5px * var(--text-scale));
  color: var(--text-soft);
  font-weight: 400;
  line-height: 1.35;
  padding-left: 2px;
  margin-top: -6px;
  margin-bottom: 10px;
}
/* Segmented control */
.gs-seg {
  /* D-158, D-162 (Pantsy-8 Batch 6): app's segmented control rendered taller than design
     (~50 vs ~36px logical). Tightening padding 4 → 3 and cell height 36 → 32 brings the
     overall control to ~38px which matches design's ~36-40px range. Track also gets a
     slightly stronger ambient tint so the unselected state reads more clearly. */
  display: flex;
  gap: 4px;
  padding: 3px;
  /* Bølge 61 (2026-05-09): chassis harmonization. Pre-B61 the seg
     used `--surface-deep` (the same token as the settings-sheet
     canvas), so segmented controls visually disappeared into the bg
     — Stian's "the bleed I see is on settings" observation traced
     to here. The toggle rows below use `--surface-mid` (elevation
     1) and read clearly as cards; segmented controls now match.
     Active cell still uses --surface-card (cream) which has plenty
     of contrast against --surface-mid (#1F0E2C). Border bumped
     0.10 → 0.06 to match the toggle-row outline weight. */
  background: var(--surface-mid);
  border-radius: var(--radius-btn);
  border: 1px solid rgba(255, 255, 255, 0.06);
}
.gs-seg-cell {
  flex: 1;
  height: 32px;
  border-radius: calc(var(--radius-btn) - 4px);
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--text-soft);
  font-family: var(--font-sans);
  font-size: calc(13px * var(--text-scale));
  font-weight: 600;
  cursor: pointer;
  border: none;
  padding: 0 8px;
  /* #29 #10 (playtest 2026-05-05): "smoother but quick" segment transitions.
     Linear 120ms read as flat — replaced with an iOS-style spring-out curve
     for background (fast departure, soft arrival, no overshoot) paired with
     a slightly faster ease-out on color so the text settles before the
     background fully lands. Total perceived motion stays under 200ms. */
  transition:
    background 180ms cubic-bezier(0.32, 0.72, 0, 1),
    color 140ms ease-out,
    transform 160ms cubic-bezier(0.32, 0.72, 0, 1);
}
.gs-seg-cell.active {
  background: var(--surface-card);
  color: var(--ink);
  /* Subtle "lift" so the active cell registers as a select-snap rather than
     a flat fill. 1.02 is small enough to read as a cue without crowding
     neighbors. */
  transform: scale(1.02);
}
.gs-seg-cell:active { transform: scale(0.97); }
.gs-seg-cell.active:active { transform: scale(0.99); }
/* Bølge 2.2 Item G (2026-05-06): per-option disabled state. Stress turn-
   order cell greys out when shared players exist. Pointer-events:none so
   the underlying button behaves like a static pill. */
.gs-seg-cell.disabled,
.gs-seg-cell:disabled {
  opacity: 0.40;
  cursor: not-allowed;
  pointer-events: none;
  filter: saturate(0.4);
}

/* F4 / F1-D (2026-05-06): sub-segmented row inside a section — used by Sudden Death
   round-count picker that nests under the Endless/Sudden-Death seg. Slightly indented
   so the visual hierarchy reads "this depends on the choice above". */
.gs-subseg {
  margin-top: 8px;
  padding-left: 4px;
}
.gs-subseg .gs-subseg-label {
  font-size: calc(11px * var(--text-scale));
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 6px;
}

/* Bølge 2.8 Item D (2026-05-07): free-input number field for round/point
   limit. Replaces the +/- stepper (H / Bølge 1.7) — cleaner interaction,
   debounced commit while typing. */
.gs-number-input {
  background: var(--surface-mid, rgba(255, 255, 255, 0.04));
  border: 1px solid rgba(255, 244, 222, 0.18);
  border-radius: 10px;
  padding: 10px 14px;
  color: var(--text-on-deep);
  font-family: var(--font-display);
  font-size: calc(18px * var(--text-scale));
  font-weight: 700;
  outline: none;
  width: 100px;
  text-align: center;
  -moz-appearance: textfield;
}
.gs-number-input:focus { border-color: var(--primary); }
.gs-number-input::-webkit-outer-spin-button,
.gs-number-input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* ToggleRow */
.gs-toggle-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 14px 16px;
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-btn);
  margin-bottom: 8px;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  transition: background 0.12s;
}
.gs-toggle-row:hover { background: var(--surface-hi); }
.gs-toggle-row.disabled {
  /* Pantsy-9 (bug-fix 2026-05-05): user reported the sub-text under "Two Pantsys"
     was invisible. Whole-row opacity 0.5 stacked on `--text-soft` (already low-
     contrast) made the sub disappear on dark surface. Bumped to 0.78 so the
     "needs 5+ players" hint reads clearly while still signaling unavailable. */
  opacity: 0.78;
  cursor: not-allowed;
}
/* Sub-text gets an extra brightness lift on disabled rows — the label is the
   visual anchor (white/cream), but the SUB is the actionable info ("needs 5+
   players"), so it has to be readable. */
.gs-toggle-row.disabled .gs-toggle-sub {
  color: var(--text-on-deep);
  opacity: 0.85;
}
.gs-toggle-meta {
  flex: 1;
  min-width: 0;
}
.gs-toggle-label {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: calc(14px * var(--text-scale));
  color: var(--text-on-deep);
  letter-spacing: -0.01em;
}
.gs-toggle-sub {
  font-size: calc(12px * var(--text-scale));
  color: var(--text-soft);
  /* I (Bølge 1.7 / 2026-05-07): override iOS Safari Data Detectors blue.
     `-webkit-text-fill-color` wins over color when iOS auto-wraps text in
     an implicit <a> for phone/date pattern matching. */
  -webkit-text-fill-color: var(--text-soft);
  margin-top: 2px;
  line-height: 1.4;
}
.gs-toggle-switch {
  /* D-163 (user decision): 38×22 with 16px knob — closer to design intent than original
     44×26 but preserves accessibility (small enough is hard to tap reliably on real
     devices, especially with imprecise tapping or motion). Visual match without breaking
     usability. */
  width: 38px;
  height: 22px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.10);
  position: relative;
  flex-shrink: 0;
  transition: background 0.15s;
}
.gs-toggle-switch.on { background: var(--primary); }
.gs-toggle-knob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 16px;
  height: 16px;
  border-radius: 999px;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
  transition: left 0.15s;
}
.gs-toggle-switch.on .gs-toggle-knob { left: 19px; }

/* Pass-and-play shared list */
.gs-shared-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 8px;
}
.gs-shared-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-btn);
}
.gs-shared-icon {
  font-size: calc(14px * var(--text-scale));
}
.gs-shared-name {
  flex: 1;
  font-weight: 600;
  font-size: calc(14px * var(--text-scale));
  color: var(--text-on-deep);
}
.gs-shared-remove {
  background: none;
  border: none;
  color: var(--pantsy-hi);
  cursor: pointer;
  font-size: calc(13px * var(--text-scale));
  font-weight: 700;
  padding: 4px 8px;
}
.gs-add-shared {
  width: 100%;
  padding: 12px 14px;
  background: transparent;
  border: 1.5px dashed rgba(255, 87, 34, 0.45);
  border-radius: var(--radius-btn);
  color: var(--primary);
  font-family: inherit;
  font-weight: 700;
  font-size: calc(13px * var(--text-scale));
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 10px;
  text-align: left;
}
.gs-add-shared-icon {
  width: 22px;
  height: 22px;
  border-radius: 999px;
  background: rgba(255, 87, 34, 0.22);
  color: var(--primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: calc(14px * var(--text-scale));
  line-height: 1;
  flex-shrink: 0;
}

/* Recap */
.recap-card {
  background: linear-gradient(135deg, #fef3c7, #fde68a);
  color: #2a1424;
  border-radius: 18px;
  padding: 18px;
  text-align: center;
}
.recap-card .label {
  font-size: calc(12px * var(--text-scale));
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 800;
  color: #92400e;
}
.recap-card .player-name {
  font-size: calc(22px * var(--text-scale));
  font-weight: 900;
  margin: 6px 0 2px;
}
.recap-card .stat {
  font-size: calc(13px * var(--text-scale));
  color: #78350f;
  font-weight: 600;
}
.recap-card .emoji {
  font-size: calc(36px * var(--text-scale));
  margin-bottom: 4px;
}
.recap-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

.history-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.history-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 12px;
  background: rgba(255,255,255,.08);
  border-radius: 10px;
  font-size: calc(13px * var(--text-scale));
}
.history-row .word { font-weight: 800; color: white; }
.history-row .pantsy { color: var(--gold); font-weight: 600; }
.history-row .badge-tiny {
  font-size: calc(10px * var(--text-scale));
  padding: 2px 6px;
  border-radius: 6px;
  font-weight: 700;
  text-transform: uppercase;
}
.history-row .badge-tiny.caught { background: rgba(22,163,74,.3); color: #86efac; }
.history-row .badge-tiny.escaped { background: rgba(225,29,72,.3); color: #fda4af; }

/* ---------------- Share card (end-of-night) ---------------- */
.share-card {
  background: linear-gradient(160deg, #0f172a 0%, #1e1b4b 50%, #2a0613 100%);
  color: white;
  border-radius: 24px;
  padding: 24px 20px 20px;
  position: relative;
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}
.share-card::before {
  content: "";
  position: absolute;
  top: -40px; right: -40px;
  width: 180px; height: 180px;
  background: radial-gradient(circle, rgba(249,115,22,.4), transparent 70%);
  pointer-events: none;
}
.share-card .share-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 14px;
  position: relative;
}
.share-card .share-brand {
  font-size: calc(20px * var(--text-scale)); font-weight: 900;
  display: flex; align-items: center; gap: 6px;
}
.share-card .share-date {
  font-size: calc(11px * var(--text-scale)); opacity: .65;
  text-transform: uppercase; letter-spacing: .08em; font-weight: 700;
}
.share-card .share-winner {
  text-align: center;
  padding: 18px 0 10px;
  position: relative;
}
.share-card .share-winner .crown { font-size: calc(42px * var(--text-scale)); }
.share-card .share-winner .name {
  font-size: calc(32px * var(--text-scale)); font-weight: 900; line-height: 1.1;
  margin: 4px 0;
  background: linear-gradient(180deg, #fff, #fed7aa);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.share-card .share-winner .pts {
  font-size: calc(14px * var(--text-scale)); opacity: .8;
  font-weight: 600;
}
.share-card .share-stats-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
  margin-top: 14px;
}
.share-card .share-stat {
  background: rgba(255,255,255,.08);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 12px;
  padding: 10px 12px;
  text-align: center;
}
.share-card .share-stat .icon { font-size: calc(20px * var(--text-scale)); line-height: 1; }
.share-card .share-stat .lbl {
  font-size: calc(9px * var(--text-scale)); text-transform: uppercase; letter-spacing: .08em;
  font-weight: 800; opacity: .7; margin: 4px 0 2px;
}
.share-card .share-stat .val {
  font-size: calc(14px * var(--text-scale)); font-weight: 800;
}
.share-card .share-stat .sub {
  font-size: calc(10px * var(--text-scale)); opacity: .65; font-weight: 600;
}
.share-card .share-rounds {
  margin-top: 14px;
  background: rgba(0,0,0,.20);
  border-radius: 12px;
  padding: 10px 12px;
  font-size: calc(11px * var(--text-scale));
}
.share-card .share-rounds .lbl {
  text-transform: uppercase; letter-spacing: .08em;
  font-weight: 800; opacity: .65;
  margin-bottom: 6px;
  font-size: calc(10px * var(--text-scale));
}
.share-card .share-rounds .row {
  display: flex; justify-content: space-between;
  padding: 3px 0;
  border-top: 0.5px solid rgba(255,255,255,.08);
}
.share-card .share-rounds .row:first-of-type { border-top: none; }
.share-card .share-footer {
  text-align: center;
  margin-top: 14px;
  font-size: calc(10px * var(--text-scale));
  opacity: .55;
  text-transform: uppercase; letter-spacing: .08em;
  font-weight: 700;
}

/* ═══════════════════════════════════════════════════════════════════════
   GAME SHOW additions — utility classes for the redesign
   ═══════════════════════════════════════════════════════════════════════ */

/* Eyebrow — small uppercase label above big content */
.eyebrow {
  font-size: calc(11px * var(--text-scale));
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 800;
  color: var(--text-faint);
  margin: 0 0 4px;
}
.eyebrow.on-card { color: var(--ink-soft); }

/* ═══════════════════════════════════════════════════════════════════════
   PANTSY9 PRIMITIVES — Bølge 70.5 (2026-05-10)
   Namespaced (`p9-*`) chassis classes for the design-pack atoms
   (Eyebrow / AppBar / PhoneScreen). Used opt-in by reskin waves B65+;
   B64 ships unchanged (no retro-apply per spec Decision 3 default).
   Existing `.eyebrow` rule above stays as-is to avoid touching ~40 in-app
   call sites; `.p9-eyebrow` is the design-pack-aligned variant.
   ═══════════════════════════════════════════════════════════════════════ */

.p9-eyebrow {
  font-family: var(--pantsy-mono);
  font-size: calc(11px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--pantsy-fg-faint);
  line-height: 1;
}

.p9-appbar {
  position: sticky;
  top: 0;
  height: 56px;
  padding: 0 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: var(--pantsy-bg);
  z-index: 10;
}

.p9-phone-screen {
  min-height: 100vh;
  max-width: 480px;
  margin: 0 auto;
  background: var(--pantsy-bg-grad);
  display: flex;
  flex-direction: column;
}

/* Stage label — used inside reveal cards to introduce big display copy */
.stage-label {
  font-size: calc(11px * var(--text-scale));
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 700;
  opacity: 0.7;
  margin: 0;
}

/* Big display — Bricolage Grotesque, tight tracking, used on reveal/handover */
.big-display {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(clamp(40px, 12vw, 56px) * var(--text-scale));
  line-height: 0.95;
  letter-spacing: -0.035em;
}

/* Cream code-card on lobby — soft warmth pulse */
.lobby-code-card {
  background: var(--surface-card);
  color: var(--text-on-card);
  border-radius: var(--radius-card);
  padding: 18px 18px 14px;
  text-align: center;
  position: relative;
  overflow: hidden;
}
.lobby-code-card::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 0%, rgba(255, 87, 34, 0.08) 0%, transparent 55%);
  animation: lobbyCodeGlow 3.6s ease-in-out infinite;
  pointer-events: none;
}
@keyframes lobbyCodeGlow {
  0%, 100% { opacity: 0; transform: scale(0.95); }
  50%      { opacity: 0.5; transform: scale(1.02); }
}
.lobby-code-card .code-display {
  position: relative;
}
.lobby-code-card .share-row {
  display: flex;
  gap: 6px;
  position: relative;
  margin-top: 4px;
}
.lobby-code-card .share-row .share-btn {
  flex: 1;
  height: 34px;
  border-radius: var(--radius-btn);
  background: transparent;
  color: var(--text-on-card);
  border: 1px solid rgba(63, 26, 74, 0.20);
  font-family: inherit;
  font-weight: 600;
  font-size: calc(12px * var(--text-scale));
  cursor: pointer;
}
.lobby-code-card .share-row .share-btn:active { transform: scale(0.97); }
/* v4: eyebrow OVER koden (egen rad), kode sentrert, share-buttons under.
   Match Pantsy-3 design-screenshot: tre stacks i samme cream code-card. */
.lobby-code-card-v4 {
  /* D-024 (Pantsy-8 Batch 18): design has more breathing room around the SRXC code than
     app's 16/14 vertical padding. Bump to 22/20 + 4px top eyebrow margin so code sits
     with comfortable air on cream tile. */
  padding: 22px 18px 20px;
  text-align: center;
}
.code-eyebrow-top {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.10em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--ink-soft);
  line-height: 1.3;
  margin-bottom: 4px;
  position: relative;
}
/* D (Bølge 1.8 / 2026-05-08): meta strip above the code-eyebrow.
   Two pills (player-count + host) sit centered, dark-tinted on the cream
   code-card so they read as a status row without competing with the big code. */
.code-meta-strip {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-bottom: 10px;
}
.cms-pill {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  background: rgba(15, 4, 24, 0.06);
  border: 1px solid rgba(15, 4, 24, 0.10);
  border-radius: 999px;
  font-family: var(--font-body);
  font-size: calc(11.5px * var(--text-scale));
  font-weight: 700;
  color: var(--ink);
  letter-spacing: -0.005em;
  line-height: 1.1;
}
.cms-pill .cms-pill-icon {
  font-size: calc(12px * var(--text-scale));
  line-height: 1;
}
.cms-pill.cms-host {
  background: rgba(255, 210, 74, 0.18);
  border-color: rgba(255, 210, 74, 0.40);
  color: #5A2818;
}
.code-display-row {
  margin-bottom: 12px;
  position: relative;
}

/* Lobby code-card har ekstra top-margin så det får luft fra topbar/profile-bubble */
.screen.lobby-screen .lobby-code-card {
  margin-top: 12px;
}

/* DEPRECATED v3-style — fjernet i v4, men beholdt for evt. bakkompat */
.lobby-code-card-v3 { padding: 14px 16px 14px; }

/* v2: code-row med share-buttons inline til høyre — DEPRECATED, kept for bakkompat */
.lobby-code-card-v2 {
  padding: 14px 16px 14px;
}
.code-row-with-share {
  display: flex;
  align-items: center;
  gap: 10px;
  position: relative;
}
.code-share-stack {
  display: flex;
  flex-direction: column;
  gap: 6px;
  flex-shrink: 0;
}
.share-btn-icon {
  width: 32px;
  height: 32px;
  border-radius: 999px;
  background: rgba(63, 26, 74, 0.06);
  border: 1px solid rgba(63, 26, 74, 0.12);
  color: var(--text-on-card);
  font-size: calc(14px * var(--text-scale));
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: inherit;
  padding: 0;
  transition: background 0.12s, transform 0.12s;
}
.share-btn-icon:hover { background: rgba(63, 26, 74, 0.12); }
.share-btn-icon:active { transform: scale(0.95); }

/* Pass-the-phone (handover) sliding card animation */
@keyframes passSlide {
  0%   { transform: translateX(-44px) rotate(-12deg); opacity: 0.4; }
  45%  { transform: translateX(0)     rotate(0deg);   opacity: 1; }
  55%  { transform: translateX(0)     rotate(0deg);   opacity: 1; }
  100% { transform: translateX(44px)  rotate(12deg);  opacity: 0.4; }
}
@keyframes passArrow {
  0%, 100% { opacity: 0.2; transform: translateX(-6px); }
  50%      { opacity: 0.85; transform: translateX(6px); }
}
@keyframes handoverPulse {
  0%, 100% { transform: scale(1); opacity: 0.4; }
  50%      { transform: scale(1.12); opacity: 0.8; }
}

.handover-diagram {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  max-width: 240px;
  margin: 0 auto 22px;
}
/* Bølge 2.20.12: single-actor variant — sole avatar centered (no from-chip,
   no arrow, no slide-card animation) for the "you again" handover case. */
.handover-diagram-single {
  justify-content: center;
}
.handover-diagram .ho-side {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}
/* CRITICAL: handover-avatar er nå sirkel (var firkantet pga manglende border-radius
   på inline-style fra JS). Centrer initialer + tving font. */
.handover-diagram .ho-side .avatar {
  border-radius: 999px !important;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(18px * var(--text-scale));
  color: #fff;
  line-height: 1;
  letter-spacing: -0.01em;
  flex-shrink: 0;
}
.handover-diagram .ho-name {
  font-size: calc(12px * var(--text-scale));
  letter-spacing: 0;
  font-weight: 600;
  text-align: center;
  line-height: 1.2;
}
.handover-diagram .ho-from .ho-name { color: var(--text-faint); font-weight: 500; }
.handover-diagram .ho-from img,
.handover-diagram .ho-from .avatar { opacity: 0.55; }
.handover-diagram .ho-mid {
  position: relative;
  flex: 1;
  height: 70px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.handover-diagram .ho-arrow {
  position: absolute;
  left: 50%;
  top: 70%;
  transform: translate(-50%, -50%);
  opacity: 0.5;
}
.handover-diagram .ho-arrow path {
  animation: passArrow 1.6s ease-in-out infinite;
}
.handover-diagram .ho-card {
  width: 26px;
  height: 46px;
  border-radius: 6px;
  background: linear-gradient(180deg, var(--surface-hi), var(--surface-lo));
  border: 1px solid rgba(255, 255, 255, 0.16);
  padding: 3px;
  animation: passSlide 2.4s ease-in-out infinite;
  box-shadow: 0 6px 14px rgba(0, 0, 0, 0.45);
}
.handover-diagram .ho-card .ho-card-inner {
  width: 100%;
  height: 100%;
  border-radius: 3px;
  background: linear-gradient(165deg, var(--pantsy), var(--primary));
  opacity: 0.85;
}
.handover-diagram .ho-to {
  position: relative;
}
.handover-diagram .ho-to .ho-pulse {
  /* D-072 (Pantsy-8 Batch 24 round 2): expanding to inset -24px + alpha 0.95 with
     wider falloff so the warm gold halo is unmistakable around Stella's avatar. */
  position: absolute;
  inset: -24px;
  border-radius: 999px;
  background: radial-gradient(circle, rgba(255, 210, 74, 0.95) 0%, rgba(255, 210, 74, 0.35) 45%, rgba(255, 210, 74, 0.08) 70%, transparent 85%);
  animation: handoverPulse 2.4s ease-in-out infinite;
  pointer-events: none;
}

/* Hint banner on home screen — gold-tinted, dismissible
   D-009 (Pantsy-8 user-decision): bumped bottom margin 12 → 18 so there's clear
   breathing room between the hint card and the Create CTA below.
   D-010: padding 12/14 → 14/16 so body copy doesn't sit cramped against the edges. */
.home-hint-banner {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  background: linear-gradient(135deg, rgba(255, 210, 74, 0.10) 0%, rgba(255, 210, 74, 0.03) 100%);
  border: 1px solid rgba(255, 210, 74, 0.33);
  border-radius: var(--radius-btn);
  /* F (Bølge 1.8 / 2026-05-08): drop the trailing 18px margin — parent
     .screen.home-screen already supplies a 12px flex gap between siblings, so
     stacking margin+gap was producing a 30px void between the tip banner and
     "Create game" button. The 16px home-stack rhythm now reads consistent. */
  margin: 0;
}
/* Bølge 16 (2026-05-10, ROADMAP #90): incognito soft-warning variant.
   Uses neutral grey-tone instead of gold so it reads as "informational"
   rather than "celebratory" (which the gold gradient implies). */
.home-hint-banner.home-hint-incognito {
  background: linear-gradient(135deg, rgba(180, 180, 180, 0.08) 0%, rgba(180, 180, 180, 0.03) 100%);
  border-color: rgba(180, 180, 180, 0.28);
}
.home-hint-banner.home-hint-incognito .hb-icon {
  background: rgba(180, 180, 180, 0.13);
  color: var(--text-on-deep);
}
/* Bølge 16: lobby banner shown when ANY player is incognito. Distinct
   from .dirty-lobby-banner (which uses card.dark gold-trim for spicy mode);
   .incognito-lobby-banner uses neutral muted style — informational, not
   celebratory or punitive. */
.incognito-lobby-banner {
  padding: 12px 14px;
  background: rgba(255, 244, 222, 0.04);
  border: 1px solid rgba(255, 244, 222, 0.16);
}
.incognito-lobby-banner .ilb-row {
  display: flex; align-items: center; gap: 10px;
}
.incognito-lobby-banner .ilb-icon {
  font-size: calc(18px * var(--text-scale)); flex-shrink: 0;
}
.incognito-lobby-banner .ilb-label {
  font-size: calc(13px * var(--text-scale));
  color: var(--text-on-deep-muted, var(--text-faint));
  line-height: 1.35;
}
.home-hint-banner .hb-icon {
  width: 32px; height: 32px;
  border-radius: 10px;
  background: rgba(255, 210, 74, 0.13);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--gold);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(16px * var(--text-scale));
  flex-shrink: 0;
}
.home-hint-banner .hb-body { flex: 1; min-width: 0; }
.home-hint-banner .hb-title {
  font-size: calc(13px * var(--text-scale)); font-weight: 700; color: var(--text-on-deep);
  line-height: 1.2;
}
.home-hint-banner .hb-text {
  font-size: calc(11.5px * var(--text-scale)); color: var(--text-muted); margin-top: 2px;
  line-height: 1.4;
}
.home-hint-banner .hb-close {
  font-size: calc(16px * var(--text-scale)); color: var(--text-faint);
  cursor: pointer; flex-shrink: 0;
  background: transparent; border: none;
  /* Audit 2026-05-04 (C.7 a11y): hit-target ≥ 44×44 (iOS guideline) — tidligere
     2px padding gjorde X-en stort sett 16×16, hard å treffe på touch. */
  min-width: 44px; min-height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
}
/* #32 (Phase 6) — Android tap-to-install button inside hint banner. Sits
   between hb-body and hb-close; primary-tinted to read as a CTA. */
.home-hint-banner .hb-install-btn {
  flex-shrink: 0;
  padding: 8px 14px;
  background: var(--primary);
  color: #fff;
  border: none;
  border-radius: var(--radius-pill);
  font-family: inherit;
  font-weight: 700;
  font-size: calc(13px * var(--text-scale));
  letter-spacing: -0.01em;
  cursor: pointer;
  align-self: center;
}
.home-hint-banner .hb-install-btn:active { transform: scale(0.97); }
.home-hint-banner.home-hint-install {
  background: linear-gradient(135deg, rgba(255, 87, 34, 0.10) 0%, rgba(255, 87, 34, 0.03) 100%);
  border-color: rgba(255, 87, 34, 0.33);
}
.home-hint-banner.home-hint-install .hb-icon {
  background: rgba(255, 87, 34, 0.13);
  color: var(--primary);
}
/* #20 (Phase 6) — first-lobby gold-tinted soft-nudge inherits the same
   hint-banner chrome; no overrides needed. Tagged with .first-lobby-hint
   for telemetry/styling hooks if needed later. */

/* Compact club strip on home — single line summary */
.club-strip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: var(--surface-lo);
  border-radius: var(--radius-btn);
  border: 1px solid rgba(255, 255, 255, 0.08);
  cursor: pointer;
}
.club-strip .cs-tiles {
  display: flex; position: relative;
  width: 36px; height: 28px; flex-shrink: 0;
}
.club-strip .cs-tile {
  width: 26px; height: 26px; border-radius: 7px;
  display: flex; align-items: center; justify-content: center;
  color: var(--text-on-card);
  font-family: var(--font-display);
  font-weight: 700; font-size: calc(12px * var(--text-scale));
  border: 2px solid var(--surface-lo);
  position: absolute;
}
.club-strip .cs-tile.t1 {
  left: 0; top: 0;
  background: linear-gradient(135deg, var(--gold), var(--ember));
}
.club-strip .cs-tile.t2 {
  left: 12px; top: 2px;
  background: rgba(255, 255, 255, 0.08);
  color: var(--text-faint);
}
.club-strip .cs-body { flex: 1; min-width: 0; text-align: left; }
.club-strip .cs-title {
  font-size: calc(13px * var(--text-scale)); font-weight: 600;
  line-height: 1.2; color: var(--text-on-deep);
  text-align: left;
}
.club-strip .cs-title .cs-count {
  color: var(--text-faint); font-weight: 500;
}
.club-strip .cs-sub {
  font-size: calc(11px * var(--text-scale)); color: var(--text-faint); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  text-align: left;
}
.club-strip .cs-see-all {
  font-size: calc(12px * var(--text-scale));
  color: var(--text-faint);
  font-weight: 500;
  flex-shrink: 0;
}
.club-strip .cs-arrow {
  font-size: calc(12px * var(--text-scale)); color: var(--text-faint);
}

/* Vote-row "waiting on" pill — transparent dark variant.
   Pantsy-3 design: sitter på dark vote-screen, ikke standalone overlay → cream
   pill stakk visuelt ut. Nå transparent + 1px hvit-rgba border + fgSoft text. */
.vote-waiting {
  width: 100%;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: var(--radius-btn);
  padding: 12px 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  color: var(--text-soft);
  font-family: inherit;
  font-size: calc(13px * var(--text-scale));
  font-weight: 500;
  margin-top: 4px;
}
.vote-waiting .vw-dots {
  display: inline-flex; gap: 3px;
}
.vote-waiting .vw-dot {
  width: 4px; height: 4px; border-radius: 999px;
  background: var(--text-soft);
  animation: voteDots 1.4s ease-in-out infinite;
}
.vote-waiting .vw-dot:nth-child(2) { animation-delay: 0.18s; }
.vote-waiting .vw-dot:nth-child(3) { animation-delay: 0.36s; }
@keyframes voteDots {
  0%, 100% { opacity: 0.3; }
  50%      { opacity: 1; }
}
.vote-waiting strong {
  color: var(--text-on-deep);
  font-weight: 700;
}

/* ═══════════════════════════════════════════════════════════════════════
   GAME SHOW: End-game winner hero
   Gold-gradient kort med roterende solstråler, pulserende glow,
   konfetti-regn, og crown-på-jeans trofee i hjørnet.
   ═══════════════════════════════════════════════════════════════════════ */
.winner-hero {
  background: linear-gradient(160deg, var(--gold) 0%, var(--ember) 60%, var(--primary) 100%);
  border-radius: var(--radius-card);
  /* Slankere padding — match Claude Design (24x22). Tidligere 24x22x28 var litt høyt. */
  padding: 20px 22px 22px;
  color: var(--text-on-card);
  position: relative;
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}
.winner-hero .winner-rays {
  position: absolute;
  inset: -50%;
  opacity: 0.22;
  pointer-events: none;
  background: repeating-conic-gradient(from 0deg at 50% 50%, transparent 0deg, rgba(0, 0, 0, 0.10) 1deg, transparent 5deg, transparent 30deg);
  animation: winnerRays 40s linear infinite;
}
.winner-hero .winner-glow {
  position: absolute;
  top: 20%;
  left: 30%;
  width: 180px;
  height: 180px;
  border-radius: 999px;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.35) 0%, transparent 60%);
  animation: winnerGlow 3s ease-in-out infinite;
  pointer-events: none;
}
.winner-hero .winner-trophy {
  position: absolute;
  top: 12px;
  right: 14px;
  animation: winnerTrophyRock 2.6s ease-in-out infinite;
  transform-origin: 50% 100%;
  pointer-events: none;
}
.winner-hero .winner-trophy svg {
  filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.4));
}
.winner-hero .winner-trophy .winner-crown {
  animation: winnerCrownShimmer 2s ease-in-out infinite;
  transform-origin: 50% 100%;
}
.winner-hero .winner-name {
  /* D-151 (Pantsy-8 Batch 16): design uses heavier display weight on winner name.
     Bumped 700 → 800 for the bolder feel. */
  font-family: var(--font-display);
  font-weight: 800;
  font-size: calc(clamp(56px, 16vw, 76px) * var(--text-scale));
  letter-spacing: -0.045em;
  line-height: 0.9;
  margin-top: 4px;
  color: var(--text-on-card);
}
@keyframes winnerRays {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
@keyframes winnerGlow {
  0%, 100% { opacity: 0.5; transform: scale(1); }
  50%      { opacity: 0.85; transform: scale(1.08); }
}
@keyframes winnerTrophyRock {
  0%, 100% { transform: rotate(-4deg) translateY(0); }
  50%      { transform: rotate(4deg) translateY(-2px); }
}
@keyframes winnerCrownShimmer {
  0%, 100% { filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.5)); }
  50%      { filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.9)); }
}
@keyframes winnerConfetti {
  0%   { transform: translateY(-20px) rotate(0deg); opacity: 0; }
  15%  { opacity: 1; }
  100% { transform: translateY(140px) rotate(540deg); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .winner-hero .winner-rays,
  .winner-hero .winner-glow,
  .winner-hero .winner-trophy,
  .winner-hero .winner-trophy .winner-crown,
  .winner-confetti { animation: none !important; }
}

/* GAME SHOW input modal — for "Add player on this phone" og lignende */
.input-modal-input-wrap {
  margin: 12px 0 18px;
  position: relative;
}
.input-modal-input {
  width: 100%;
  padding: 16px 18px;
  background: var(--surface-card-bright);
  border: 2px solid var(--border);
  border-radius: var(--radius-btn);
  font-family: var(--font-body);
  font-size: calc(17px * var(--text-scale));
  font-weight: 600;
  color: var(--text-on-card);
  outline: none;
  transition: border-color .15s, box-shadow .15s;
  caret-color: var(--primary);
}
.input-modal-input:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 4px var(--primary-glow);
}
.input-modal-input::placeholder {
  color: var(--text-muted);
  font-weight: 500;
}
/* Audit 2026-05-04: shake + glow-rød når brukeren tapper "Add"/confirm med tom input.
   Viser visuell feedback istedenfor silent dismiss. Klassen fjernes etter 700ms. */
.input-modal-input-error,
.input-modal-input.input-modal-input-error {
  border-color: #dc2626 !important;
  box-shadow: 0 0 0 4px rgba(220, 38, 38, 0.18) !important;
  animation: inputModalShake 0.4s cubic-bezier(.36,.07,.19,.97);
}
@keyframes inputModalShake {
  10%, 90% { transform: translateX(-1px); }
  20%, 80% { transform: translateX(2px); }
  30%, 50%, 70% { transform: translateX(-3px); }
  40%, 60% { transform: translateX(3px); }
}

/* ═══════════════════════════════════════════════════════════════════════
   GAME SHOW HOME v2 — pinned bottom CTAs, flex-spacers around hero
   ═══════════════════════════════════════════════════════════════════════ */
.screen.home-screen {
  /* F (Bølge 1.8 / 2026-05-08): bumped 12 → 16px standard rhythm for tip↔Create
     game and other home siblings. Earlier 12px gap + the banner's own 18px
     margin compounded to 30px before/22px after, which read inconsistent. */
  gap: 16px;
  /* Sørg for at home tar full vh så flex-spacers virker.

     Bølge 25 N8 (2026-05-19): the prior calc subtracted only 80px (topbar
     allowance) from 100dvh, but the parent `.app` already eats
     `env(safe-area-inset-bottom)` as padding-bottom. On iOS devices with a
     home indicator (~34px) the demanded screen height was ~34px too tall,
     pushing the bottom-CTA stack below the visible viewport. Subtracting
     the inset here keeps the home flex container inside the available
     content box so `home-bottom-ctas` (margin-top:auto, pinned bottom)
     lands at the safe-area edge instead of past it.

     env() resolves to 0 when no inset is present (desktop, older iOS), so
     the calc collapses gracefully to the prior value on those surfaces. */
  min-height: calc(100vh - 80px - env(safe-area-inset-bottom, 0px));
  min-height: calc(100dvh - 80px - env(safe-area-inset-bottom, 0px));
}

/* Bottom CTA zone — pinned. Internal gap matcher outer gap for konsistens.
   Bølge 2.3 Item B (2026-05-06): bumped internal gap 12 → 16px so the
   spacing between hint-banner ↔ Create game ↔ Enter Code is uniform.
   Previous 12px inner + 16px outer-flex-gap produced an asymmetric ladder
   (16px between hint and Create, 12px between Create and join). With
   margin-top:auto this stack pins to the bottom; safe-area inset is
   handled at .screen padding level. */
.home-bottom-ctas {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 0;
  /* Margin-top pusher denne sektionen til bunn av flex-screen */
  margin-top: auto;
}

/* Join-row: surfaceLo container med code-input + Join button */
.home-join-row {
  display: flex;
  gap: 8px;
  padding: 6px;
  background: var(--surface-lo);
  border-radius: var(--radius-btn);
  border: 1px solid rgba(255, 255, 255, 0.08);
  align-items: center;
}
.home-join-row input.code-input {
  /* Override default code-input styling for inline pill-format */
  flex: 1;
  height: 44px;
  padding: 0 14px;
  background: transparent;
  border: none;
  outline: none;
  font-family: var(--font-mono);
  font-size: calc(16px * var(--text-scale));
  font-weight: 600;
  color: var(--text-on-deep);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  text-align: left;
  min-width: 0;
}
.home-join-row input.code-input:focus {
  /* Disable default input focus glow inside the join-row container —
     container already gives visual context, focus glow ville overflowed. */
  box-shadow: none;
}
.home-join-row input.code-input::placeholder {
  color: var(--text-faint);
  font-weight: 600;
  letter-spacing: 0.18em;
}

/* "New here? How it works →" — tiny text link */
.home-howitworks-link {
  text-align: center;
  margin-top: 4px;
  padding: 6px 0;
  font-size: calc(12px * var(--text-scale));
  background: transparent;
  border: none;
  font-family: inherit;
  cursor: pointer;
}
.home-howitworks-link .hwl-mute { color: var(--text-faint); }
.home-howitworks-link .hwl-strong {
  color: var(--text-on-deep);
  font-weight: 600;
}

/* "Playing as X · change ›" — tiny tekst-link på home for å endre navn uten bloat */
.playing-as-link {
  display: block;
  width: 100%;
  text-align: center;
  background: transparent;
  border: none;
  padding: 4px 0;
  font-family: inherit;
  font-size: calc(12px * var(--text-scale));
  cursor: pointer;
  color: var(--text-faint);
}
.playing-as-link .pal-mute { color: var(--text-faint); }
.playing-as-link .pal-name {
  color: var(--text-on-deep);
  font-weight: 600;
}
.playing-as-link .pal-cta {
  color: var(--text-faint);
  margin-left: 2px;
}

/* ═══════════════════════════════════════════════════════════════════════
   GAME SHOW LOBBY v2 — compact players row + bottom actions
   ═══════════════════════════════════════════════════════════════════════ */

/* Lobby-screen tar full vertical space så bottom-actions kan pinnes */
.screen.lobby-screen {
  /* (100vh fallback also removed — same reason as above) */
  /* min-height removed 2026-05-11 (Stian round 7) — `flex: 1` from `.screen` base is sufficient; min-height was making the screen overflow `#screen` and pushing CTAs under the home-indicator on iOS PWA */
}

/* Compact avatar-row — 32px sirkler i flex-wrap */
.lobby-players-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.lobby-player-tile {
  position: relative;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.lobby-player-tile.disconnected {
  opacity: 0.4;
}
.lobby-player-tile .host-dot {
  position: absolute;
  bottom: -2px;
  right: -2px;
  width: 11px;
  height: 11px;
  border-radius: 999px;
  background: var(--primary);
  border: 2px solid var(--surface-card);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15);
}
@keyframes lobbyPlayerJoin {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 87, 34, 0.55); }
  50%      { box-shadow: 0 0 0 5px rgba(255, 87, 34, 0); }
}
.lobby-player-tile.just-joined-pulse {
  animation: lobbyPlayerJoin 2.4s ease-in-out infinite;
}

/* D-017 (Pantsy-8 user decision): reverted from name-pill chips to design's letter-only
   initials chips. Compact horizontal row of 32px colored circles. Each circle holds the
   player's initials in white display-font. Host circle has a subtle outer ring; new joiners
   get the join-pulse animation. */
.lobby-players-row.initial-chips {
  gap: 8px;
}
.lobby-player-chip.lpc-initials-only {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  padding: 0;
  border-radius: 999px;
  line-height: 1;
}
.lobby-player-chip.lpc-initials-only .lpc-avatar {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 800;
  font-size: calc(12px * var(--text-scale));
  font-family: var(--font-display);
  letter-spacing: -0.01em;
}
.lobby-player-chip.lpc-initials-only.host .lpc-avatar {
  box-shadow: 0 0 0 2px rgba(255, 87, 34, 0.55);
}
.lobby-player-chip.disconnected {
  opacity: 0.4;
}
.lobby-player-chip.just-joined-pulse {
  animation: lobbyPlayerJoin 2.4s ease-in-out infinite;
}

/* Add-shared-player inline-knapp inni players-card — dashed orange.
   På dark card: label = primary (orange), hint = text-faint (lys grå-cream). */
.add-shared-inline {
  margin-top: 12px;
  width: 100%;
  padding: 10px 14px;
  background: transparent;
  color: var(--primary);
  border: 1.5px dashed rgba(255, 87, 34, 0.45);
  border-radius: var(--radius-btn);
  font-family: inherit;
  font-weight: 700;
  font-size: calc(13px * var(--text-scale));
  cursor: pointer;
  text-align: left;
  display: flex;
  align-items: center;
  gap: 10px;
}
.add-shared-inline:hover {
  background: rgba(255, 87, 34, 0.08);
}
.add-shared-inline .asi-icon {
  width: 22px; height: 22px;
  border-radius: 999px;
  background: rgba(255, 87, 34, 0.22);
  color: var(--primary);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: calc(14px * var(--text-scale));
  line-height: 1;
  flex-shrink: 0;
}
.add-shared-inline .asi-label {
  font-weight: 700;
  color: var(--primary);
}
.add-shared-inline .asi-hint {
  font-size: calc(11px * var(--text-scale));
  font-weight: 500;
  color: var(--text-faint);
  opacity: 0.85;
}

/* Bottom actions: Start primary + Settings/Leave row */
.lobby-bottom-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: auto;
}
.lobby-action-row {
  display: flex;
  gap: 10px;
}
.lobby-action-row .btn {
  flex: 1;
  /* Disable pulse on ghost buttons in this row */
  animation: none;
}
/* Inline tekst-action-rad (Game settings · Leave) — minimal, ingen panel */
.lobby-text-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  margin-top: 4px;
  padding: 8px 0 0;
}
.lobby-text-link {
  background: none;
  border: none;
  color: var(--text-faint);
  font-family: inherit;
  font-size: calc(13px * var(--text-scale));
  font-weight: 600;
  letter-spacing: -0.01em;
  cursor: pointer;
  padding: 6px 8px;
  border-radius: 6px;
  transition: color 0.12s, background 0.12s;
}
.lobby-text-link:hover {
  color: var(--text-soft);
  background: rgba(255, 255, 255, 0.04);
}
.lobby-text-sep {
  color: var(--text-faint);
  opacity: 0.5;
  font-size: calc(13px * var(--text-scale));
}

/* Lobby bottom text-row — Game settings | Leave som tekst-links.
   #29 #9 (playtest 2026-05-05): switched from `flex + center + gap:48px`
   (which centered the two items as a group, leaving asymmetric whitespace
   around them) to a 2-column grid where each menu choice is centered within
   its own column. With unequal label lengths ("Game settings" vs "Leave",
   or NO "Innstillinger" vs "Forlat"), the column-grid gives each sub-CTA a
   fair share of horizontal real estate and the row reads as balanced
   regardless of label width. Match Pantsy-3 design: dempet tekst-soft farge,
   ingen border, ingen bg. */
.lobby-text-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  padding: 8px 0 0;
}
/* #20 (Phase 6): when "How it works ↘" is added as the middle item, expand
   to 3 columns so each menu choice still gets a fair-share column. */
.lobby-text-row.lobby-text-row-3 {
  grid-template-columns: 1fr 1fr 1fr;
}
.lobby-text-action.lobby-text-action-howitworks {
  color: var(--text-on-deep);
  font-weight: 600;
}
.lobby-text-action {
  background: none;
  border: none;
  color: var(--text-soft);
  font-family: inherit;
  font-size: calc(14px * var(--text-scale));
  font-weight: 500;
  letter-spacing: -0.01em;
  cursor: pointer;
  padding: 8px 6px;
  border-radius: 6px;
  text-align: center;
  transition: color 0.12s;
}
.lobby-text-action:hover { color: var(--text-on-deep); }
.lobby-text-action:active { opacity: 0.6; }

/* ═══════════════════════════════════════════════════════════════════════
   Lobby Categories — round icon-circles + inline dice for auto-pick.
   Match Pantsy-3 design-screenshot: 5 valgte kategorier som 44px circles
   med fire-border, og 6. slot er en dotted grå dice-circle for auto-pick.
   ═══════════════════════════════════════════════════════════════════════ */
/* Item 16 (Bølge 1.9 / 2026-05-08): single-line horizontal scroll for the
   selected-categories row. Earlier `flex-wrap: wrap` produced a 2-line layout
   when 6+ cats were selected (44px icon + gap exceeds viewport). Touch users
   swipe; scrollbar hidden. Edge mask hints at scrollability without chrome. */
.cat-icon-row {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
  overflow-y: hidden;
  gap: 8px;
  align-items: center;
  margin: 0;
  scrollbar-width: none;
  -ms-overflow-style: none;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
  /* Bølge 2.3 Item H (2026-05-06): spread evenly across the panel when
     content fits the viewport. When the row overflows (6+ cats on narrow
     screens), browser falls back to flex-start automatically — scrolling
     mechanic preserved. Verified at 4-cat (fits, spaced) vs 8-cat (scrolls). */
  justify-content: space-between;
  /* Bølge 2.4 Item F (2026-05-06): dropped the 12px edge-mask. With
     justify-content: space-between the first/last cats sit flush against
     the row edges, and a 12px fade was clipping their outer rim — visually
     reading as "clipped icon" rather than "scroll hint". The horizontal
     overflow + hidden scrollbar still communicates scrollability via the
     touch interaction itself. */
}
.cat-icon-row::-webkit-scrollbar { display: none; }
.cat-icon-circle { scroll-snap-align: start; }
.cat-icon-circle {
  width: 44px;
  height: 44px;
  border-radius: 999px;
  border: 1.5px solid var(--primary);
  background: rgba(255, 87, 34, 0.08);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(20px * var(--text-scale));
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
  padding: 0;
  font-family: inherit;
  color: inherit;
  transition: transform 0.12s, background 0.12s;
}
.cat-icon-circle:hover { transform: translateY(-1px); }
.cat-icon-circle:active { transform: scale(0.95); }
.cat-icon-circle .cic-emoji {
  filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.2));
}
/* Item 9 (Bølge 1.9 / 2026-05-08): vibe-driven cats anchor a tiny "·  vibe"
   tag absolute-positioned beneath the icon-circle. Hint affordance only —
   doesn't block hit-area. */
.cat-icon-circle.is-via-vibe { position: relative; overflow: visible; }
.cat-icon-circle.is-via-vibe .cic-emoji { transform: translateY(-2px); }
.cat-vibe-tag {
  position: absolute;
  bottom: -10px;
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-mono);
  font-size: calc(8.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.10em;
  color: var(--primary);
  text-transform: uppercase;
  white-space: nowrap;
  pointer-events: none;
}
/* Dotted dice-circle (auto-pick) — grå, dotted border */
.cat-auto-dice {
  border: 1.5px dotted rgba(255, 255, 255, 0.36);
  background: transparent;
  color: var(--text-soft);
  filter: grayscale(0.4);
  font-size: calc(18px * var(--text-scale));
}
.cat-auto-dice:hover {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.5);
}
/* Auto-pick stagger animasjon — pills fader inn én etter én */
.cat-icon-row.auto-pick-anim .cat-icon-circle:not(.cat-auto-dice) {
  animation: catIconFadeIn 0.4s ease-out both;
  animation-delay: calc(var(--i, 0) * 0.08s);
}
@keyframes catIconFadeIn {
  0%   { opacity: 0; transform: scale(0.6); }
  100% { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .cat-icon-row.auto-pick-anim .cat-icon-circle { animation: none !important; }
}

/* Install-prompt card — tappbar (trigger PWA install eller iOS-instruks-modal) */
.install-prompt-card {
  display: flex;
  align-items: stretch;
  width: 100%;
  background: linear-gradient(135deg, #FED7AA, #FEF3C7);
  color: #7C2D12;
  border: 1px solid rgba(124, 45, 18, 0.10);
  border-radius: var(--radius-card);
  padding: 14px;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  transition: transform 0.12s, box-shadow 0.12s;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18);
}
.install-prompt-card:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.22);
}
.install-prompt-card:active {
  transform: scale(0.98);
}

/* Item 10 (Bølge 1.9 / 2026-05-08): Recovery Code styles. The display block
   is monospace, large, copy-target. The restore link sits below the welcome
   modal's a11y row as a small mono pill.
   Bølge 2.3 Item D (2026-05-06): cream-on-faint-cream made the code
   unreadable in the live build. Flip to dark ink on solid cream so the
   12-character recovery code is actually legible. */
.recovery-code-display {
  font-family: var(--font-mono);
  font-size: calc(20px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.12em;
  color: #1A0820;
  background: #FFF4DE;
  border: 1px solid rgba(0, 0, 0, 0.12);
  border-radius: 12px;
  padding: 18px 16px;
  text-align: center;
  word-break: break-all;
  user-select: all;
}
/* Bølge 2.3 Item D (2026-05-06): bump recovery-code modal above the profile
   sheet (.sheet-overlay z=260). Without this the modal mounted at z=200
   from .onboard-overlay sat hidden behind the profile sheet until the user
   dismissed it via Done. */
.recovery-code-modal-overlay {
  z-index: 350 !important;
}
.recovery-restore-link {
  display: inline-block;
  margin-top: 12px;
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.10em;
  color: var(--primary);
  text-transform: uppercase;
  background: none;
  border: none;
  cursor: pointer;
  text-align: center;
  width: 100%;
}
/* Bølge 2.15 (2026-05-07): passkey-auth link in welcome modal. Same visual
   chrome as recovery-restore-link, just shorter top margin since it stacks
   directly under it. */
.name-modal-passkey-link {
  display: inline-block;
  margin-top: 6px;
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.10em;
  color: var(--primary);
  text-transform: uppercase;
  background: none;
  border: none;
  cursor: pointer;
  text-align: center;
  width: 100%;
}

/* Item 7 (Bølge 1.9 / 2026-05-08): tip-banner — extracted from inline styles
   so addToHome can be tappable. Body wraps in <button>; chevron signals
   tappability. Other tips render with the same chrome but no button wrapper. */
.tip-banner {
  background: rgba(245, 158, 11, .12);
  border: 1px solid rgba(245, 158, 11, .3);
  border-radius: 10px;
  /* Bølge 19 Phase 3 (IMPLEMENTATION.md Stage 2 bundled fixes, 2026-05-13):
     D-010 padding 10/12 → 14/16 so body copy doesn't sit cramped against the
     edges when the banner carries a longer tip body. D-009 margin-bottom
     bumped 10 → 16 to give clearer breathing room between the tip and the
     Create CTA below. (Parent .home-bottom-ctas supplies its own gap, but
     the tip surface earns the extra visual weight as a tappable nudge.) */
  padding: 14px 16px;
  margin: 4px 0 16px;
  color: rgba(255, 255, 255, .9);
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.tip-banner.is-tappable {
  cursor: pointer;
  transition: background .12s, border-color .12s;
}
.tip-banner.is-tappable:hover {
  background: rgba(245, 158, 11, .18);
  border-color: rgba(245, 158, 11, .45);
}
.tip-banner-body {
  flex: 1;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  background: none;
  border: none;
  color: inherit;
  text-align: left;
  font: inherit;
  padding: 0;
  cursor: inherit;
}
.tip-banner-icon { font-size: calc(18px * var(--text-scale)); line-height: 1; flex-shrink: 0; }
.tip-banner-text { flex: 1; font-size: calc(13px * var(--text-scale)); line-height: 1.4; }
.tip-banner-chevron {
  font-size: calc(16px * var(--text-scale));
  color: rgba(255, 255, 255, .6);
  flex-shrink: 0;
  align-self: center;
}
.tip-banner-dismiss {
  background: none;
  border: none;
  color: rgba(255, 255, 255, .5);
  cursor: pointer;
  font-size: calc(16px * var(--text-scale));
  /* Bølge 19 Phase 3 (a11y bundle, 2026-05-13): iOS hit-target ≥ 44×44.
     padding moved from 0 4px to a min-* pair so the touch surface meets
     the guideline without changing visual size of the glyph. Visible focus
     ring matches the gold accent so keyboard users see when it's focused.
     align: center keeps the ✕ centered against the taller banner padding. */
  min-width: 44px;
  min-height: 44px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  border-radius: 8px;
}
.tip-banner-dismiss:focus-visible {
  outline: 2px solid rgba(245, 158, 11, .6);
  outline-offset: 2px;
  color: rgba(255, 255, 255, .9);
}

/* Bølge 24 (2026-05-18): tip-banner v2 — eyebrow + body + CTA pill.
   Activated by `.tip-banner--v2` modifier when tip carries title+body.
   Layout: stacked content column (eyebrow row, body, CTA row) + the
   floating dismiss ✕ that the legacy banner already places top-right.
   Visual language matches Pantsy-8 hint cards: gold-tinted eyebrow
   (--primary), accent CTA pill that mirrors the .btn-primary primitive
   at smaller scale. Banner stays inside ~80–96px height to keep the
   home + lobby rhythm. */
.tip-banner.tip-banner--v2 {
  /* Override flex direction — v2 stacks the content column + dismiss
     side-by-side, but the column itself stacks vertically. */
  align-items: stretch;
  gap: 8px;
  padding: 12px 14px;
}
.tip-banner-v2-stack {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.tip-banner-v2-head {
  display: flex;
  align-items: center;
  gap: 8px;
}
.tip-banner-v2-head .tip-banner-icon {
  font-size: calc(16px * var(--text-scale));
}
.tip-banner-title {
  font-size: calc(11px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--primary);
  line-height: 1.2;
}
.tip-banner-body-v2 {
  font-size: calc(14px * var(--text-scale));
  line-height: 1.4;
  color: rgba(255, 255, 255, .92);
}
.tip-banner-cta-row {
  display: flex;
  justify-content: flex-start;
  margin-top: 2px;
}
.tip-banner-cta-btn {
  /* Pill-style accent button. Smaller than .btn-primary (44px target via
     padding + min-height) but visually in the same family — flat
     primary fill, primary-on text, subtle drop shadow. */
  background: var(--primary);
  color: var(--primary-on);
  border: none;
  border-radius: 999px;
  padding: 8px 16px;
  min-height: 44px;
  font-size: calc(13px * var(--text-scale));
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12);
  transition: transform .08s, background .15s;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.tip-banner-cta-btn:active {
  transform: scale(0.97);
}
.tip-banner-cta-btn:focus-visible {
  outline: 2px solid rgba(245, 158, 11, .6);
  outline-offset: 2px;
}
.tip-banner.tip-banner--v2 .tip-banner-dismiss {
  /* Dismiss ✕ aligns to the top edge in v2 so it doesn't crowd the
     CTA pill that lives lower in the column. */
  align-self: flex-start;
}

/* ═══════════════════════════════════════════════════════════════════════
   GAME SHOW Sheet — full-screen overlay for Settings / Categories
   ═══════════════════════════════════════════════════════════════════════ */

.sheet-overlay {
  /* Full-screen takeover — bullet-proof: alltid full viewport, ingen sliver av
     underliggende screen som lekker ut i kantene. position/inset sikrer
     dekning av safe-area, background-color sikrer opacity, z-index over alt
     annet (inkludert install-prompt z:240, confirm-modal z:250). */
  position: fixed !important;
  inset: 0 !important;
  width: 100vw !important;
  height: 100vh !important;
  height: 100dvh !important;
  align-items: stretch !important;
  justify-content: stretch !important;
  padding: 0 !important;
  background-color: var(--surface-deep) !important;
  background-image: none !important;
  /* Override default onboard-overlay backdrop blur (gir flyttig kant) */
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  z-index: var(--z-build-cat) !important;
}
/* Body lock når sheet er åpen — forhindrer scroll-bleed av underliggende skjerm */
body.sheet-open {
  overflow: hidden;
}
.sheet-modal {
  width: 100%;
  height: 100%;
  max-width: 480px;
  /* Bevisst INGEN max-height — la innholdet bestemme høyden, og la sheet-body
     scrolle hvis det blir for langt. Tidligere `max-height:100%` kunne kollapse
     på iOS Safari når 100dvh varierte med Safari-URL-baren. */
  margin: 0 auto;
  background: transparent;
  border-radius: 0;
  display: flex;
  flex-direction: column;
  box-shadow: none;
  /* Padding-top respekterer iOS dynamic island. Padding-bottom satt til 0 —
     .sheet-body har egen safe-area-bottom-padding så scroll-content extender
     hele veien til bunnen av skjermen. */
  padding:
    calc(env(safe-area-inset-top, 0px) + 8px)
    max(12px, env(safe-area-inset-left))
    0
    max(12px, env(safe-area-inset-right));
}
.sheet-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 8px 18px;
  flex-shrink: 0;
}
.sheet-header-text {
  min-width: 0;
}
.sheet-eyebrow {
  font-size: calc(11px * var(--text-scale));
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 800;
  color: var(--text-faint);
  margin-bottom: 4px;
}
.sheet-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(28px * var(--text-scale));
  letter-spacing: -0.025em;
  line-height: 1;
  color: var(--text-on-deep);
}
.sheet-done-btn {
  /* D-155 (Pantsy-8 Batch 6): design uses a FILLED dark pill with white text on Settings;
     app had a transparent outlined ghost-style. Switching to filled --surface-card with ink-
     toned text (matches the Done buttons across other Pantsy-8 sheet headers). */
  height: 36px;
  padding: 0 18px;
  background: var(--surface-card);
  color: var(--text-on-card);
  border: none;
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(14px * var(--text-scale));
  letter-spacing: -0.01em;
  cursor: pointer;
  flex-shrink: 0;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04);
}
.sheet-done-btn:hover {
  filter: brightness(0.97);
}
.sheet-body {
  flex: 1;
  overflow-y: auto;
  /* Padding-bottom inkluderer safe-area-inset-bottom så siste innholdet er
     ikke skjult bak iOS home-indicator. */
  padding-bottom: max(20px, env(safe-area-inset-bottom));
  -webkit-overflow-scrolling: touch;
}

/* Categories-sheet specific */
.cat-sheet-body {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.cat-sheet-summary {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  background: rgba(255, 87, 34, 0.06);
  border: 1px solid rgba(255, 87, 34, 0.16);
  border-radius: var(--radius-btn);
}
.cat-sheet-summary .css-num {
  width: 32px; height: 32px; border-radius: 8px;
  background: rgba(255, 87, 34, 0.20);
  color: var(--primary);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(16px * var(--text-scale));
  flex-shrink: 0;
}
.cat-sheet-summary .css-meta {
  flex: 1;
  min-width: 0;
}
.cat-sheet-summary .css-meta-line {
  font-size: calc(13px * var(--text-scale));
  font-weight: 600;
  color: var(--text-on-deep);
  line-height: 1.2;
}
.cat-sheet-summary .css-meta-sub {
  font-size: calc(11px * var(--text-scale));
  color: var(--text-muted);
  margin-top: 3px;
}
.cat-sheet-summary .css-clear-btn {
  height: 28px;
  padding: 0 12px;
  background: transparent;
  color: var(--text-muted);
  border: 1px solid rgba(255, 244, 222, 0.14);
  border-radius: var(--radius-pill);
  font-family: inherit;
  font-weight: 500;
  font-size: calc(11px * var(--text-scale));
  cursor: pointer;
  flex-shrink: 0;
}

/* Smart auto-pick card */
.cat-sheet-autopick {
  width: 100%;
  padding: 14px 16px;
  background: linear-gradient(135deg, rgba(255, 210, 74, 0.10) 0%, rgba(255, 87, 34, 0.06) 100%);
  border: 1.5px dashed rgba(255, 210, 74, 0.45);
  border-radius: var(--radius-btn);
  color: var(--text-on-deep);
  cursor: pointer;
  text-align: left;
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: inherit;
}
.cat-sheet-autopick .csa-icon {
  /* D-039 (Pantsy-8 user-decision): bumped icon tile 32→44px and brightened the
     cream-tinted background so the auto-pick row matches design's generous icon. */
  width: 44px; height: 44px;
  border-radius: 12px;
  background: rgba(255, 244, 222, 0.10);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: calc(22px * var(--text-scale));
  line-height: 1;
  flex-shrink: 0;
}
.cat-sheet-autopick .csa-body {
  flex: 1;
  min-width: 0;
}
.cat-sheet-autopick .csa-title {
  font-weight: 700;
  font-size: calc(13.5px * var(--text-scale));
  color: var(--text-on-deep);
}
.cat-sheet-autopick .csa-sub {
  font-size: calc(11px * var(--text-scale));
  color: var(--text-muted);
  margin-top: 2px;
  line-height: 1.4;
}
.cat-sheet-autopick .csa-arrow {
  color: var(--gold);
  font-size: calc(18px * var(--text-scale));
  font-weight: 600;
  flex-shrink: 0;
}

.cat-sheet-section {
  /* Section divider/wrapper */
}

/* ═══════════════════════════════════════════════════════════════════════
   GAME SHOW screen 03/04/05/06 — separat outer-eyebrow + card + CTA
   ═══════════════════════════════════════════════════════════════════════ */

/* Reveal-screen layout: eyebrow over card, card fills middle, CTA pinned bottom.
   Matcher Claude Designs PhoneScreen-rytme: padding 8px 20px på eyebrow,
   14px 20px på card-wrap, 0 20px 24px på CTA. */
.screen.reveal-screen {
  gap: 14px;
  /* (100vh fallback also removed — same reason as above) */
  /* min-height removed 2026-05-11 (Stian round 7) — `flex: 1` from `.screen` base is sufficient; min-height was making the screen overflow `#screen` and pushing CTAs under the home-indicator on iOS PWA */
}
.reveal-outer-eyebrow {
  /* D-085 (Pantsy-8 Batch 17): "STIAN IS LOOKING…" eyebrow letter-spacing on reveal
     screens (04/05/06) — design uses tighter ~0.05em vs .eyebrow's default 0.08em.
     Override at this level so other eyebrow uses keep their wider tracking. */
  text-align: center;
  padding: 4px 4px 0;
}
.reveal-outer-eyebrow .eyebrow {
  letter-spacing: 0.05em;
}

/* Handover wrapper: outer-eyebrow + card + CTA. Card NOT tappable. */
.handover-wrap {
  display: flex;
  flex-direction: column;
  gap: 14px;
  flex: 1;
}
.handover-outer-eyebrow {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 4px 0;
}
.handover-card {
  flex: 1;
  display: flex;
  flex-direction: column;
}
.handover-diagram-wrap {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
}

/* Pantsy-name flicker — text-shadow pulse på "You're Pantsy"-displayet */
@keyframes pantsyNameFlicker {
  0%, 100% { text-shadow: 0 0 0px rgba(255, 255, 255, 0); }
  50%      { text-shadow: 0 0 18px rgba(255, 255, 255, 0.18); }
}
.reveal-card.pantsy .word.pantsy-name-flicker,
.reveal-card.pantsy .pantsy-name-flicker {
  animation: pantsyNameFlicker 3.4s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .pantsy-name-flicker { animation: none !important; }
}

/* Pantsy reveal-card: solid pantsy-rød, override default gradient + glow */
.reveal-card.pantsy {
  background: var(--pantsy);
  color: #fff;
  border-color: var(--pantsy-hi);
}
/* Pantsy-8 D-CP-A root cause: heat-glow ::before extended 80px BELOW the card
   (`bottom: -80px`) og blødde inn på "I'm ready to bluff" CTA-en, ga det
   et burnt-orange utseende selv om btn-primary er flat. Pantsy-8-designet
   har ingen slik glow — fjern. (Tidligere lagret hvis vi vil prøve mykere
   variant inni kortet i fremtiden.) */
.reveal-card.pantsy::before {
  display: none;
}

/* Smarty reveal-card glow position (top-right, gold) — already in earlier CSS */

/* ═══════════════════════════════════════════════════════════════════════
   GAME SHOW: Clue turn (07) — floor card med mic + turn-order strip
   Match til Claude Design ScreenClueTurn:
     • Round indicator pill: "ROUND 1 / 2 · 🌍 Places" (mono + cat)
     • Floor card: spotlight-glow, breathing mic, "Has the floor" eyebrow,
       big display name (56px Bricolage), coaching, NEXT-strip
     • Peek-card affordance: ghost-button med 👁 + HOLD-badge
     • Bottom CTA: "Done — pass on" (primary, full width)
   ═══════════════════════════════════════════════════════════════════════ */
.clue-screen {
  display: flex;
  flex-direction: column;
  gap: 14px;
  /* min-height removed 2026-05-11 (Stian round 7) — `flex: 1` from `.screen` base is sufficient; min-height was making the screen overflow `#screen` and pushing CTAs under the home-indicator on iOS PWA */
}
.clue-round-indicator {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 4px 4px 0;
  font-family: var(--font-mono);
  font-size: calc(12px * var(--text-scale));
  color: var(--text-soft);
  letter-spacing: 0.12em;
}
.clue-round-indicator .cri-bullet {
  width: 4px; height: 4px; border-radius: 999px;
  background: var(--text-faint);
}
.clue-round-indicator .cri-cat {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: inherit;
  font-size: calc(12px * var(--text-scale));
  letter-spacing: 0;
  color: var(--text-soft);
}
.clue-floor-card {
  background: linear-gradient(160deg, var(--surface-hi) 0%, var(--surface-lo) 100%);
  color: var(--text-on-deep);
  border: 1px solid rgba(255, 87, 34, 0.20);
  border-radius: var(--radius-card);
  padding: 32px 24px 28px;
  text-align: center;
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  min-height: 280px;
}
.clue-floor-card::before {
  content: "";
  position: absolute;
  top: -120px;
  left: 50%;
  transform: translateX(-50%);
  width: 320px;
  height: 320px;
  border-radius: 999px;
  background: radial-gradient(circle, rgba(255, 87, 34, 0.27) 0%, rgba(255, 87, 34, 0.07) 35%, transparent 65%);
  pointer-events: none;
}
.clue-mic {
  position: relative;
  width: 56px; height: 56px;
  margin: 0 auto 18px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
  display: flex; align-items: center; justify-content: center;
  font-size: calc(26px * var(--text-scale)); line-height: 1;
  animation: pantsy-mic-breathe 2.4s ease-in-out infinite;
  z-index: 1;
}
.clue-mic .mic-glyph {
  display: inline-flex;
  animation: pantsy-mic-glyph-bob 2.4s ease-in-out infinite;
}
@keyframes pantsy-mic-breathe {
  0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(255, 87, 34, 0.20); }
  50%      { transform: scale(1.05); box-shadow: 0 0 0 8px rgba(255, 87, 34, 0); }
}
@keyframes pantsy-mic-glyph-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-1.5px); }
}
@media (prefers-reduced-motion: reduce) {
  .clue-mic, .clue-mic .mic-glyph { animation: none !important; }
}
.clue-floor-eyebrow {
  /* D-092 (Pantsy-8 Batch 4 round 2): --text-soft (~62%) still read as faded; verifier wanted
     more contrast. Pushing to a literal rgba so we get clear ~75% white-on-dark legibility. */
  position: relative;
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.12em;
  color: rgba(255, 244, 222, 0.78);
  text-transform: uppercase;
  font-weight: 700;
}
.clue-floor-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(56px * var(--text-scale));
  line-height: 1;
  letter-spacing: -0.035em;
  margin-top: 10px;
  position: relative;
  color: var(--text-on-deep);
  word-break: break-word;
}
.clue-floor-coach {
  position: relative;
  margin: 14px auto 0;
  max-width: 280px;
  font-size: calc(14px * var(--text-scale));
  line-height: 1.5;
  color: var(--text-soft);
}
.clue-floor-coach strong {
  color: var(--text-on-deep);
  font-weight: 600;
}
.clue-next-strip {
  position: relative;
  margin-top: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
}
.clue-next-strip .cns-label {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  color: var(--text-faint);
  letter-spacing: 0.1em;
  margin-right: 4px;
}
.clue-next-strip .cns-item {
  display: flex;
  align-items: center;
  gap: 6px;
}
.clue-next-strip .cns-item.pos-0 { opacity: 1; }
.clue-next-strip .cns-item.pos-1 { opacity: 0.75; }
.clue-next-strip .cns-item.pos-2 { opacity: 0.5; }
.clue-next-strip .cns-item.pos-3 { opacity: 0.32; }
.clue-next-strip .cns-avatar {
  width: 24px; height: 24px;
  border-radius: 999px;
  background: var(--primary);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: calc(11px * var(--text-scale)); font-weight: 700;
  letter-spacing: 0;
}
.clue-next-strip .cns-name {
  font-size: calc(12px * var(--text-scale));
  font-weight: 600;
  color: var(--text-on-deep);
}
.clue-floor-clockwise-help {
  position: relative;
  margin: 14px auto 0;
  max-width: 280px;
  font-size: calc(13px * var(--text-scale));
  line-height: 1.45;
  color: var(--text-faint);
}
.clue-peek-affordance {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 52px;
  padding: 0 18px;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--radius-btn);
  color: var(--text-on-deep);
  font-family: inherit;
  font-size: calc(14px * var(--text-scale));
  font-weight: 500;
  cursor: pointer;
  width: 100%;
  /* 2026-05-11 (Stian): removed leftover `margin-top: 4px` that stacked
     on top of the `.discuss-screen` column gap (12px), producing a
     ~16px card→peek distance that was asymmetric with the now-12px
     peek→CTA gap below. Column gap alone is the single source of
     truth for spacing. */
}
.clue-peek-affordance .cpa-left {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--text-soft);
}
.clue-peek-affordance .cpa-left svg {
  display: block;
}
/* Bølge 56 fix #2 (2026-05-09): peek-blocked-btn renders during
   pass-and-play when Peek would leak the card to other players.
   Pre-fix: the row looked like a regular CTA — users tapped to
   discover it was disabled. Post-fix: lower opacity + strikethrough
   on the label communicates the disabled-pre-tap state. The 🚫
   emoji + brandConfirm explainer on tap stay (so the disabled
   reason is still surfaced if they try). */
.peek-blocked-btn {
  opacity: 0.55;
}
.peek-blocked-btn .cpa-left > span:last-child {
  text-decoration: line-through;
}
.clue-peek-affordance .cpa-hold {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  padding: 4px 8px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-soft);
  letter-spacing: 0.05em;
  font-weight: 600;
}
/* Audit 2026-05-04: hold-progress indicator on peek button.
   Adds a subtle filling-bar effect during the 600ms hold period before peek triggers.
   Position: absolute overlay inside the button, slides from 0% → 100% width during hold. */
.clue-peek-affordance {
  position: relative;
  overflow: hidden;
}
.clue-peek-affordance::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 0;
  background: linear-gradient(90deg, rgba(255, 87, 34, 0.18), rgba(255, 87, 34, 0.32));
  transition: width 0s linear;
  pointer-events: none;
  z-index: 0;
}
.clue-peek-affordance.clue-peek-holding::before {
  width: 100%;
  transition: width 0.6s linear;
}
.clue-peek-affordance > * {
  position: relative;
  z-index: 1;
}

/* ═══════════════════════════════════════════════════════════════════════
   GAME SHOW: Vote screens (07b / 07c) — sentral spørsmål med ikon
   ═══════════════════════════════════════════════════════════════════════ */
.vote-screen {
  display: flex;
  flex-direction: column;
  gap: 0;
  /* min-height removed 2026-05-11 (Stian round 7) — `flex: 1` from `.screen` base is sufficient; min-height was making the screen overflow `#screen` and pushing CTAs under the home-indicator on iOS PWA */
  /* B64 P4 (2026-05-10): radial bg-grad applied at the vote-screen level
     per `_pantsy9/07c.5-point-at-pantsy/screens-vote.jsx` PhoneScreen
     wrapper. Subtle pantsyRed→aubergine wash gives the "point at the
     Pantsy" moment its own atmosphere without repainting the parent
     `.app-shell` (ambient gradient is already on body via `--pantsy-bg-grad`
     — this layers an extra fire-tinted glow at the top). */
  background:
    radial-gradient(ellipse at 50% 0%, rgba(255, 23, 68, 0.10) 0%, transparent 55%),
    var(--pantsy-bg-grad, transparent);
}
.vote-question-block {
  text-align: center;
  padding: 14px 4px 8px;
}
/* B64 P4: small uppercase mono "Round N" eyebrow above the headline. */
.vote-question-eyebrow {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: calc(11px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--text-faint, rgba(255,244,222,0.4));
  text-transform: uppercase;
  margin-bottom: 6px;
}
.vote-question-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  animation: pantsy-vote-qpop 0.45s cubic-bezier(.2,.9,.3,1.2) both;
}
@keyframes pantsy-vote-qpop {
  0%   { transform: scale(0.96); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .vote-question-row { animation: none !important; }
}
.vote-question-icon {
  display: inline-block;
  flex: 0 0 auto;
  line-height: 0;
}
.vote-question-icon.ballot {
  animation: pantsy-vote-icon-tilt 2.2s ease-in-out infinite;
  transform-origin: 50% 80%;
}
.vote-question-icon.star {
  animation: pantsy-vote-star-shine 2.2s ease-in-out infinite;
}
.vote-question-icon.star > span {
  display: inline-block;
  animation: pantsy-vote-star-spin 3.2s ease-in-out infinite;
  transform-origin: 50% 50%;
}
@keyframes pantsy-vote-icon-tilt {
  0%, 100% { transform: rotate(-4deg); }
  50%      { transform: rotate(4deg); }
}
@keyframes pantsy-vote-star-shine {
  0%, 100% { filter: drop-shadow(0 0 0 rgba(255, 210, 74, 0.5)); }
  50%      { filter: drop-shadow(0 0 8px rgba(255, 210, 74, 1)); }
}
@keyframes pantsy-vote-star-spin {
  0%   { transform: rotate(-12deg) scale(0.9); }
  50%  { transform: rotate(12deg) scale(1.05); }
  100% { transform: rotate(-12deg) scale(0.9); }
}
@media (prefers-reduced-motion: reduce) {
  .vote-question-icon.ballot,
  .vote-question-icon.star,
  .vote-question-icon.star > span { animation: none !important; }
}
.vote-question-h1 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(30px * var(--text-scale));
  letter-spacing: -0.03em;
  line-height: 1.05;
  color: var(--text-on-deep);
}
.vote-question-h1.smarty {
  font-size: calc(28px * var(--text-scale));
}
.vote-question-help {
  margin: 8px auto 0;
  max-width: 320px;
  font-size: calc(13px * var(--text-scale));
  line-height: 1.4;
  color: var(--text-soft);
}
/* Stagger pop-in for vote rows */
.vote-list .vote-row-anim {
  animation: pantsy-vote-qpop 0.4s cubic-bezier(.2,.9,.3,1.2) both;
}
.vote-list .vote-row-anim:nth-child(1) { animation-delay: 0s; }
.vote-list .vote-row-anim:nth-child(2) { animation-delay: 0.05s; }
.vote-list .vote-row-anim:nth-child(3) { animation-delay: 0.10s; }
.vote-list .vote-row-anim:nth-child(4) { animation-delay: 0.15s; }
.vote-list .vote-row-anim:nth-child(5) { animation-delay: 0.20s; }
.vote-list .vote-row-anim:nth-child(6) { animation-delay: 0.25s; }
.vote-list .vote-row-anim:nth-child(7) { animation-delay: 0.30s; }
.vote-list .vote-row-anim:nth-child(8) { animation-delay: 0.35s; }
@media (prefers-reduced-motion: reduce) {
  .vote-list .vote-row-anim { animation: none !important; }
}
/* Push waiting-row til bunnen av skjermen */
.vote-screen-spacer {
  flex: 1;
  min-height: 8px;
}

/* ═══════════════════════════════════════════════════════════════════════
   GAME SHOW: Result screens (08 Pantsed / 09 Escaped) — theatrical card
   med blazing flame (caught) eller strutting jeans (escaped), stamp-overlay,
   "Real word was X" footer, best-clue gold pill, vote breakdown.
   ═══════════════════════════════════════════════════════════════════════ */
.result-screen {
  display: flex;
  flex-direction: column;
  gap: 14px;
  /* min-height removed 2026-05-11 (Stian round 7) — `flex: 1` from `.screen` base is sufficient; min-height was making the screen overflow `#screen` and pushing CTAs under the home-indicator on iOS PWA */
}
.result-card {
  position: relative;
  background: linear-gradient(135deg, var(--surface-mid) 0%, var(--surface-deep) 100%);
  border: 1px solid rgba(255, 23, 68, 0.27);
  border-radius: var(--radius-card);
  padding: 28px 24px;
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  min-height: 160px;
}
/* Radial fire glow — top-right hjørne */
.result-card::before {
  content: "";
  position: absolute;
  top: -60px;
  right: -60px;
  width: 240px;
  height: 240px;
  border-radius: 999px;
  background: radial-gradient(circle, rgba(255, 23, 68, 0.47) 0%, rgba(255, 87, 34, 0.20) 35%, transparent 70%);
  pointer-events: none;
}
.result-card.escaped::before {
  background: radial-gradient(circle, rgba(255, 23, 68, 0.33) 0%, rgba(255, 87, 34, 0.13) 35%, transparent 70%);
}
.result-card-eyebrow {
  position: relative;
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--pantsy-hi);
  font-weight: 700;
}
.result-card-headline {
  position: relative;
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-top: 6px;
  flex-wrap: wrap;
}
.result-card-name {
  font-family: var(--font-display);
  font-weight: 700;
  /* B44 D-020 (2026-05-09): clamp scales the headline down at narrow
     viewports before forcing a wrap. Pre-B44 the static 52px broke
     names like "RoundHandover" (12 chars) into "RoundHando" + "ver"
     on iPhone-narrow. 9vw at 390px ≈ 35px; 9vw at 580px ≈ 52px. The
     upper bound matches the design pack value at screens-2.jsx:286. */
  font-size: calc(clamp(28px, 9vw, 52px) * var(--text-scale));
  letter-spacing: -0.04em;
  line-height: 0.95;
  color: var(--text-on-deep);
  /* `text-wrap: balance` distributes any wrap evenly across lines if
     the clamp can't fit. `overflow-wrap: anywhere` is the last-resort
     break for truly pathological names; pre-B44 used `word-break:
     break-word` which is the legacy property name. */
  text-wrap: balance;
  overflow-wrap: anywhere;
}
.result-stamp {
  font-family: var(--font-sans);
  font-weight: 800;
  font-size: calc(14px * var(--text-scale));
  letter-spacing: 0.18em;
  color: var(--pantsy-hi);
  border: 2.5px solid var(--pantsy-hi);
  border-radius: 4px;
  padding: 4px 10px;
  align-self: flex-start;
  margin-top: 6px;
  box-shadow: inset 0 0 0 1px rgba(255, 23, 68, 0.13);
  animation: pantsy-stamp-thump 0.45s cubic-bezier(.2,.9,.3,1.4) both;
}
.result-stamp.caught {
  transform: rotate(-8deg);
}
.result-stamp.escaped {
  transform: rotate(6deg);
  letter-spacing: 0.14em;
  font-size: calc(13px * var(--text-scale));
  background: rgba(255, 23, 68, 0.07);
  box-shadow: inset 0 0 0 1px rgba(255, 23, 68, 0.13), 0 0 14px rgba(255, 23, 68, 0.33);
}
@keyframes pantsy-stamp-thump {
  0%   { transform: rotate(-8deg) scale(1.3); opacity: 0; }
  55%  { transform: rotate(-12deg) scale(0.92); opacity: 1; }
  100% { transform: rotate(-8deg) scale(1); opacity: 1; }
}
.result-stamp.escaped {
  animation: pantsy-stamp-thump-2 0.45s cubic-bezier(.2,.9,.3,1.4) both;
}
@keyframes pantsy-stamp-thump-2 {
  0%   { transform: rotate(6deg) scale(1.3); opacity: 0; }
  55%  { transform: rotate(2deg) scale(0.92); opacity: 1; }
  100% { transform: rotate(6deg) scale(1); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .result-stamp { animation: none !important; }
}
.result-card-footer {
  margin-top: 14px;
  position: relative;
  font-size: calc(13px * var(--text-scale));
  color: var(--text-soft);
  display: flex;
  gap: 6px;
  align-items: center;
  flex-wrap: wrap;
}
.result-card-footer .rcf-word {
  color: var(--cream, #FFF4DE);
  font-weight: 700;
  font-size: calc(15px * var(--text-scale));
  font-family: var(--font-display);
  letter-spacing: -0.01em;
}
.result-card-footer .rcf-faint {
  color: var(--text-faint);
}
/* Caught: blazing flame som strutter på toppen-høyre */
.result-flame-strut {
  position: absolute;
  top: 14px;
  right: 18px;
  width: 70px;
  height: 96px;
  pointer-events: none;
  transform-origin: 50% 100%;
  animation: pantsy-flame-strut 1.6s ease-in-out infinite;
}
.result-flame-strut svg {
  filter: drop-shadow(0 0 14px rgba(255, 87, 34, 1));
  animation: pantsy-flame-blaze 0.6s ease-in-out infinite;
  transform-origin: 50% 100%;
}
@keyframes pantsy-flame-strut {
  0%, 100% { transform: translateY(0) rotate(-3deg); }
  50%      { transform: translateY(-6px) rotate(4deg); }
}
@keyframes pantsy-flame-blaze {
  0%, 100% { transform: scaleY(1) scaleX(1); opacity: 1; }
  33%      { transform: scaleY(1.08) scaleX(0.96); opacity: 0.92; }
  66%      { transform: scaleY(0.95) scaleX(1.04); opacity: 1; }
}
@keyframes pantsy-ember-rise {
  0%   { transform: translateY(20px) scale(0.6); opacity: 0; }
  20%  { opacity: 1; }
  100% { transform: translateY(-120px) scale(1); opacity: 0; }
}
.result-ember {
  position: absolute;
  width: 3px; height: 5px; border-radius: 2px;
  pointer-events: none;
  animation-name: pantsy-ember-rise;
  animation-timing-function: ease-out;
  animation-iteration-count: infinite;
  opacity: 0;
}
/* Escaped: strutting jeans + dust puffs
   D-138 (Pantsy-8 user-decision): jeans icon was sitting too high — design has its
   center aligned with the hero name baseline. Bumping top 14→22 + right 18→16 so
   the icon sits visually on the name's row instead of floating above. */
.result-jeans-strut {
  position: absolute;
  top: 22px;
  right: 16px;
  width: 70px;
  height: 96px;
  pointer-events: none;
  transform-origin: 50% 100%;
  animation: pantsy-jeans-walk 0.9s ease-in-out infinite;
}
.result-jeans-strut > div {
  width: 100%; height: 100%;
  transform-origin: 50% 100%;
  animation: pantsy-jeans-squash 0.9s ease-in-out infinite;
  filter: drop-shadow(0 6px 12px rgba(0, 0, 0, 0.5));
}
@keyframes pantsy-jeans-walk {
  0%   { transform: rotate(-3deg); }
  50%  { transform: rotate(3deg); }
  100% { transform: rotate(-3deg); }
}
@keyframes pantsy-jeans-squash {
  0%, 100% { transform: translateY(0) scaleY(1) scaleX(1); }
  25%      { transform: translateY(-3px) scaleY(1.03) scaleX(0.98); }
  50%      { transform: translateY(0) scaleY(0.97) scaleX(1.02); }
  75%      { transform: translateY(-3px) scaleY(1.03) scaleX(0.98); }
}
@keyframes pantsy-dust-puff {
  0%   { transform: translate(0, 0) scale(0.4); opacity: 0; }
  15%  { opacity: 0.7; }
  100% { transform: translate(-32px, -10px) scale(1.4); opacity: 0; }
}
.result-dust {
  position: absolute;
  width: 10px; height: 10px;
  border-radius: 999px;
  background: radial-gradient(circle, rgba(255, 244, 222, 0.4) 0%, rgba(255, 244, 222, 0.13) 50%, transparent 75%);
  pointer-events: none;
  filter: blur(0.5px);
  opacity: 0;
  animation-name: pantsy-dust-puff;
  animation-timing-function: ease-out;
  animation-iteration-count: infinite;
}
@media (prefers-reduced-motion: reduce) {
  .result-flame-strut, .result-flame-strut svg,
  .result-jeans-strut, .result-jeans-strut > div,
  .result-ember, .result-dust { animation: none !important; }
}

/* +30 Pantsy reward pill (escaped only) — gold gradient
   D-134 (Pantsy-8 user-decision): design uses a stronger orange-yellow gradient bar.
   Reordered fire→gold to gold→fire so the brighter end leads, added a deeper shadow
   so edges read as crisp. */
.result-pantsy-reward {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 18px;
  background: linear-gradient(90deg, var(--gold) 0%, var(--ember, #E8A93A) 50%, var(--primary) 100%);
  color: var(--ink);
  border-radius: var(--radius-card);
  position: relative;
  overflow: hidden;
  box-shadow: 0 6px 18px rgba(255, 140, 50, 0.25);
}
.result-pantsy-reward .rpr-emoji {
  font-size: calc(30px * var(--text-scale));
  line-height: 1;
}
.result-pantsy-reward .rpr-meta {
  flex: 1;
  min-width: 0;
}
.result-pantsy-reward .rpr-label {
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
  opacity: 0.7;
  font-weight: 700;
}
.result-pantsy-reward .rpr-text {
  font-weight: 700;
  font-size: calc(15px * var(--text-scale));
  margin-top: 3px;
  color: var(--ink);
}
.result-pantsy-reward .rpr-delta {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(26px * var(--text-scale));
  color: var(--ink);
}

/* Best-clue gold pill (compact) — vises både for caught og escaped */
.result-best-clue-pill {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: linear-gradient(135deg, var(--gold) 0%, var(--ember) 100%);
  color: var(--ink);
  border-radius: var(--radius-card);
}
.result-best-clue-pill .rbc-star {
  font-size: calc(20px * var(--text-scale));
  line-height: 1;
}
.result-best-clue-pill .rbc-meta {
  flex: 1;
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}
.result-best-clue-pill .rbc-label {
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
  opacity: 0.75;
  font-weight: 700;
}
.result-best-clue-pill .rbc-name {
  font-weight: 700;
  font-size: calc(14px * var(--text-scale));
  color: var(--ink);
}
.result-best-clue-pill .rbc-delta {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(18px * var(--text-scale));
  color: var(--ink);
}

/* Pantsy-7 ROUND SUMMARY — merged votes + standings into one sorted table.
   Each row: rank | avatar | name | action (→target / PANTSY tag / BEST CLUE) |
   round-delta (mono ±N green/red) | cumulative total (display 16px). Sorted
   by total desc; rank #1 gets gold tint. Pantsy row tinted red (caught) or
   orange (escaped). */
.result-votes-block {
  display: flex;
  flex-direction: column;
  gap: 0;
}
.result-summary-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
  padding: 0 4px;
}
.result-summary-tag {
  /* D-117 (Pantsy-8 Batch 15): pushed to bright cream at 92% alpha. Holds its own
     against the gradient + bottom shadow. */
  font-family: var(--font-mono);
  font-size: calc(10.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.08em;
  color: rgba(255, 244, 222, 0.92);
}
.result-votes-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  font-weight: 700;
}
.result-summary-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.result-summary-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid rgba(255, 255, 255, 0.04);
  border-radius: var(--radius-btn);
  min-width: 0;
}
/* Pantsy-7: pantsy-rad bruker --pantsy (#FF1744 pink-red) i stedet for fire-orange,
   for å skille pantsy-rolle visuelt fra escaped-state. Lavere alpha (8%) gir
   mer transparent, "lighter" føelse som matcher designet. */
.result-summary-row.is-pantsy {
  background: rgba(255, 23, 68, 0.10);
  border-color: rgba(255, 23, 68, 0.22);
}
.result-summary-row.is-escaped-pantsy {
  background: rgba(255, 87, 34, 0.10);
  border-color: rgba(255, 138, 80, 0.27);
}
.result-summary-row .rsr-rank {
  width: 16px;
  font-family: var(--font-mono);
  font-size: calc(10.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--text-faint);
  text-align: right;
  flex-shrink: 0;
}
.result-summary-row.is-leader .rsr-rank {
  color: var(--gold);
}
.result-summary-row .rsr-avatar {
  width: 24px; height: 24px;
  border-radius: 999px;
  background: var(--primary);   /* fallback — overridden inline by playerColor() */
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: calc(10px * var(--text-scale)); font-weight: 800;
  font-family: var(--font-display);
  flex-shrink: 0;
}
.result-summary-row .rsr-name {
  font-weight: 600;
  font-size: calc(13px * var(--text-scale));
  color: var(--text-on-deep);
  flex-shrink: 0;
}
.result-summary-row .rsr-action {
  flex: 1;
  min-width: 0;
  font-size: calc(11.5px * var(--text-scale));
  color: var(--text-soft);
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: flex;
  align-items: center;
  gap: 6px;
}
.result-summary-row .rsr-arrow {
  color: var(--text-faint);
}
.result-summary-row .rsr-target-name {
  color: var(--text-on-deep);
  font-weight: 600;
}
.result-summary-row .rsr-action-faint {
  opacity: 0.5;
}
/* Pantsy mono tag — "PANTSY · CAUGHT" or "PANTSY · ESCAPED" */
.result-summary-row .rsr-pantsy-tag {
  font-family: var(--font-mono);
  font-size: calc(9px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--pantsy-hi);
  padding: 2px 5px;
  background: rgba(255, 23, 68, 0.15);
  border: 1px solid rgba(255, 23, 68, 0.34);
  border-radius: 3px;
  line-height: 1;
}
.result-summary-row .rsr-pantsy-tag.escaped {
  color: var(--primary);
  background: rgba(255, 110, 64, 0.15);
  border-color: rgba(255, 138, 80, 0.4);
}
/* BEST CLUE tag — gold pill, sits next to "→ Target" */
.result-summary-row .rsr-best-tag {
  font-family: var(--font-mono);
  font-size: calc(8.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.1em;
  color: var(--gold);
  padding: 1.5px 4px;
  background: rgba(255, 210, 74, 0.10);
  border: 1px solid rgba(255, 210, 74, 0.34);
  border-radius: 3px;
  line-height: 1;
  flex-shrink: 0;
}
/* Round delta — mono, sign-aware color */
.result-summary-row .rsr-delta {
  /* D-121 (Pantsy-8 user-decision): fix column alignment — fixed 40px width and
     tabular-nums so +10 / -10 / +5 / -5 all line up at the same x-position
     (left-edge of column) for a clean numeric grid. */
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: calc(11.5px * var(--text-scale));
  text-align: right;
  flex-shrink: 0;
  width: 40px;
  font-variant-numeric: tabular-nums;
}
/* D-137 (Pantsy-8 Batch 12): design uses bright lime; #7CD992 read as too dark/dim. */
.result-summary-row .rsr-delta.positive { color: #B4FA6E; }
.result-summary-row .rsr-delta.negative { color: var(--pantsy-hi); }
.result-summary-row .rsr-delta.neutral { color: var(--text-faint); }
.result-summary-row .rsr-delta.caught-pantsy { color: var(--pantsy-hi); }
.result-summary-row .rsr-delta.escaped-pantsy { color: var(--primary); }
/* Bølge 10 (2026-05-07) — tappable score-delta cell. The cell renders as
   a <button> when interactive; strip default button chrome and add a
   subtle hover/press affordance so the affordance is discoverable
   without screaming for attention. */
.result-summary-row button.rsr-delta-tappable {
  background: transparent;
  border: none;
  padding: 4px 6px;
  margin: -4px -6px;
  cursor: pointer;
  border-radius: 6px;
  transition: background-color 120ms ease;
}
.result-summary-row button.rsr-delta-tappable:hover,
.result-summary-row button.rsr-delta-tappable:focus-visible {
  background: rgba(255, 255, 255, 0.06);
}
.result-summary-row button.rsr-delta-tappable:active {
  background: rgba(255, 255, 255, 0.10);
}
/* Bølge 10 (2026-05-07) — #20 sub-item 2: result-screen "How it works ↘"
   row. Sits between Smart-Roast ticker and bottom CTAs. Centered, low-
   visual-weight — ambient affordance, not a primary action. */
.result-howitworks-row {
  display: flex;
  justify-content: center;
  padding: 8px 0 4px;
}
.result-howitworks-link {
  color: var(--text-muted);
  font-size: calc(13px * var(--text-scale));
  background: transparent;
  border: none;
  padding: 6px 12px;
  cursor: pointer;
}
.result-howitworks-link:hover,
.result-howitworks-link:focus-visible {
  color: var(--text-soft);
}
/* Bølge 10 (2026-05-07) — AI builder loading hint line. Sits below the
   echoed prompt; reassures the user that work is happening. */
.build-ai-pending-hint {
  margin-top: 8px;
  font-size: calc(13px * var(--text-scale));
  color: var(--text-faint);
  text-align: center;
  font-style: italic;
}
/* Cumulative total — display font, larger */
.result-summary-row .rsr-total {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(16px * var(--text-scale));
  letter-spacing: -0.02em;
  color: var(--text-soft);
  text-align: right;
  flex-shrink: 0;
  min-width: 24px;
}
.result-summary-row.is-leader .rsr-total {
  color: var(--text-on-deep);
}
.result-votes-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}
.result-vote-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 9px;
  background: rgba(255, 255, 255, 0.025);
  border: 1px solid rgba(255, 255, 255, 0.04);
  border-radius: var(--radius-btn);
  min-width: 0;
}
.result-vote-row.is-pantsy {
  background: rgba(255, 23, 68, 0.10);
}
.result-vote-row.is-pantsy.is-escaped-pantsy {
  background: rgba(255, 87, 34, 0.10);
}
.result-vote-row .rvr-avatar {
  width: 22px; height: 22px;
  border-radius: 999px;
  background: var(--primary);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: calc(10px * var(--text-scale)); font-weight: 800;
  font-family: var(--font-display);
  flex-shrink: 0;
}
.result-vote-row .rvr-meta {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.result-vote-row .rvr-name {
  font-weight: 600;
  font-size: calc(12px * var(--text-scale));
  line-height: 1.1;
  color: var(--text-on-deep);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.result-vote-row .rvr-target {
  font-size: calc(10.5px * var(--text-scale));
  color: var(--text-soft);
  line-height: 1.2;
  margin-top: 1px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.result-vote-row .rvr-target strong {
  color: var(--text-on-deep);
  font-weight: 600;
}
.result-vote-row .rvr-pantsy-tag {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: calc(9.5px * var(--text-scale));
  letter-spacing: 0.06em;
  line-height: 1.2;
  margin-top: 1px;
  color: var(--pantsy-hi);
}
.result-vote-row.is-escaped-pantsy .rvr-pantsy-tag {
  color: var(--primary);
}
.result-vote-row .rvr-delta {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: calc(11.5px * var(--text-scale));
  text-align: right;
  color: var(--pantsy-hi);
  flex-shrink: 0;
}
.result-vote-row .rvr-delta.correct { color: #B4FA6E; }
.result-vote-row .rvr-delta.escaped-correct { color: var(--gold); }
.result-vote-row .rvr-delta.is-pantsy { color: var(--pantsy-hi); }
.result-vote-row.is-escaped-pantsy .rvr-delta.is-pantsy { color: var(--primary); }

/* ─── Result standings strip (between rounds) ──────────────────────
   Match Pantsy-5 ScreenResult.RunningTotalsStrip: horisontal scroll-strip
   med liten avatar + score + navn per spiller. Leader får gold-tint + crown. */
.result-standings-strip {
  margin-top: 6px;
  padding: 6px 10px 8px;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-btn);
}
.rss-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(9px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--text-faint);
  text-transform: uppercase;
  margin: 0 0 4px 4px;
}
.rss-row {
  display: flex;
  gap: 4px;
  overflow-x: auto;
  padding: 0 2px;
  -webkit-overflow-scrolling: touch;
}
.rss-cell {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 5px 3px 4px;
  border-radius: 8px;
  border: 1px solid transparent;
}
.rss-cell.is-leader {
  background: rgba(255, 210, 74, 0.08);
  border-color: rgba(255, 210, 74, 0.34);
}
.rss-avatar-wrap {
  position: relative;
}
.rss-avatar {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: rgba(255, 87, 34, 0.18);
  border: 1.5px solid rgba(255, 87, 34, 0.32);
  color: var(--text-on-deep);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: calc(9px * var(--text-scale));
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.rss-cell.is-leader .rss-avatar {
  background: rgba(255, 210, 74, 0.18);
  border-color: rgba(255, 210, 74, 0.55);
  color: #5A3810;
}
.rss-crown {
  position: absolute;
  top: -6px;
  left: 50%;
  transform: translateX(-50%);
  font-size: calc(8px * var(--text-scale));
  line-height: 1;
  filter: drop-shadow(0 1px 1px rgba(0,0,0,0.4));
}
.rss-score {
  font-family: var(--font-mono);
  font-weight: 700;
  font-size: calc(11px * var(--text-scale));
  letter-spacing: -0.01em;
  line-height: 1;
  color: var(--text-on-deep);
}
.rss-cell.is-leader .rss-score {
  color: var(--gold);
}
.rss-name {
  font-size: calc(8.5px * var(--text-scale));
  color: var(--text-faint);
  font-weight: 600;
  letter-spacing: 0.02em;
  max-width: 48px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Bottom CTA-row — Next round + End game.
   .app parent already applies max(20px, env(safe-area-inset-bottom));
   adding it here AGAIN doubled the bottom-gap so CTA looked floating ~40px
   above viewport bottom on iOS instead of flush. Drop the redundant rule. */
.result-bottom-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
/* End game som subtle text-link i bottom (ikke ghost-button) — match Pantsy-5
   som viser primary CTA + sekundær handling som ren underlinet tekst. */
.result-end-game-link {
  /* Pantsy-8 D-CP-E + D-118/D-135 (Batch 16): tightening once more — verifier wanted
     better contrast against the strong bottom-shadow gradient. Lifted from --text-soft
     (62%) to rgba 0.85 with bolder underline alpha 0.5 so the link holds up against
     the orange CTA glow above it. */
  background: none;
  border: none;
  color: rgba(255, 244, 222, 0.85);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: calc(13px * var(--text-scale));
  letter-spacing: 0.02em;
  padding: 8px 12px;
  margin: 0 auto;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-color: rgba(255, 244, 222, 0.50);
  text-underline-offset: 3px;
  align-self: center;
}
.result-end-game-link:hover { color: var(--text-on-deep); }
.result-end-game-link:active { transform: translateY(1px); }

/* ═══════════════════════════════════════════════════════════════════════
   GAME SHOW: Achievement toast (10) — gold-bordered medal toast
   Drops from top, sparkles, medal SVG pop-in, +XP/next-tier hint.
   ═══════════════════════════════════════════════════════════════════════ */
.ach-overlay-v2 {
  /* D-144, D-145 (Pantsy-8 Batch 5 — settled):
     Round 1 (0.88 alpha, center) → too transparent + wrong position.
     Round 2 (0.97 alpha, upper-third) → fully obscured backdrop, but design actually shows
     a FAINT lobby behind. Settling on 0.78 alpha + 10px blur (lobby faint, not gone) and
     toast at ~12% top padding (upper portion, not pinned to top, not strict center).
     Verifier disagreed twice → flagged AMBIGUOUS in gate doc. */
  position: fixed;
  inset: 0;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 12vh 20px 20px;
  z-index: var(--z-achievement);
  pointer-events: auto;
  background: rgba(15, 4, 24, 0.78);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  animation: pantsy-ach-overlay-fade 0.3s ease-out;
}
@keyframes pantsy-ach-overlay-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.ach-toast-v2 {
  /* D-148 (Pantsy-8 Batch 27): toast had 20/18 vertical padding; design uses tighter
     16/14 so the medal + title + caption sit closer together. */
  position: relative;
  width: 100%;
  max-width: 380px;
  background: linear-gradient(160deg, #2A1F38 0%, #1A0F23 100%);
  border-radius: 22px;
  border: 1.5px solid var(--gold);
  padding: 16px 22px 14px;
  box-shadow:
    0 24px 60px rgba(0, 0, 0, 0.55),
    0 0 40px rgba(255, 210, 74, 0.20),
    inset 0 1px 0 rgba(255, 255, 255, 0.08);
  overflow: hidden;
  color: var(--text-on-deep);
  animation: pantsy-toast-drop 0.5s cubic-bezier(.2,.9,.3,1.4) both;
}
@keyframes pantsy-toast-drop {
  /* D-145 (Pantsy-8 Batch 5): drop-from-top animation looked off when overlay is now
     centered — the toast would slide from above the viewport center which felt awkward.
     Switching to a scale + fade-in entrance, matching design's centered presentation. */
  0%   { transform: scale(0.94); opacity: 0; }
  60%  { transform: scale(1.02); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
@keyframes pantsy-medal-pop {
  0%   { transform: scale(0) rotate(-30deg); }
  55%  { transform: scale(1.15) rotate(8deg); }
  100% { transform: scale(1) rotate(0deg); }
}
@keyframes pantsy-spark {
  0%, 100% { opacity: 0; transform: scale(0.5); }
  50%      { opacity: 1; transform: scale(1); }
}
/* Bølge 139 (2026-05-12, ROADMAP #122): variable sparkle animation per
   rarity. Common keeps the 1.4s base (.ach-spark default). Rare fades
   faster + brighter for an "earned this" feel. Legendary adds rotate
   + shimmer + longer dwell so the burst lands cinematically — paired
   with the medal-wrap glow on .ach-toast-v2.ach-legendary below. */
@keyframes pantsy-spark-rare {
  0%, 100% { opacity: 0; transform: scale(0.4); }
  40%      { opacity: 1; transform: scale(1.1); }
}
@keyframes pantsy-spark-legendary {
  0%, 100% { opacity: 0; transform: scale(0.3) rotate(0deg); }
  30%      { opacity: 0.95; transform: scale(1.05) rotate(30deg); }
  60%      { opacity: 0.85; transform: scale(1.2) rotate(-20deg); }
}
@keyframes pantsy-legendary-glow {
  0%, 100% { box-shadow: 0 0 12px rgba(255, 215, 100, 0.35), 0 0 28px rgba(255, 215, 100, 0.18); }
  50%      { box-shadow: 0 0 22px rgba(255, 215, 100, 0.60), 0 0 48px rgba(255, 215, 100, 0.32); }
}
/* Selectors include `.ach-toast-v2` to outweigh the base
   `.ach-toast-v2 .ach-spark` rule below (which sets the default 1.4s
   pantsy-spark animation). Without the parent qualifier the base rule
   wins by source order — variant must be more specific. */
.ach-toast-v2 .ach-spark.ach-spark-rare {
  animation: pantsy-spark-rare 0.9s ease-in-out infinite;
  box-shadow: 0 0 10px var(--gold), 0 0 18px rgba(255, 215, 100, 0.4);
}
.ach-toast-v2 .ach-spark.ach-spark-legendary {
  animation: pantsy-spark-legendary 1.8s ease-in-out infinite;
  box-shadow: 0 0 12px var(--gold), 0 0 22px rgba(255, 215, 100, 0.55);
}
/* Legendary medal-wrap glow: pulses a soft gold halo around the icon
   so the burst reads as "this is a rare thing". Synced rhythm with the
   sparkle dwell (1.8s) so the whole composition breathes together. */
.ach-toast-v2.ach-legendary .ach-medal-wrap {
  border-radius: 50%;
  animation: pantsy-legendary-glow 1.8s ease-in-out infinite;
  animation-delay: 0.2s;
}
@media (prefers-reduced-motion: reduce) {
  .ach-toast-v2,
  .ach-toast-v2 .ach-medal,
  .ach-toast-v2 .ach-spark,
  .ach-toast-v2.ach-legendary .ach-medal-wrap { animation: none !important; }
}
.ach-toast-v2 .ach-eyebrow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  margin-bottom: 12px;
  position: relative;
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--gold);
}
.ach-toast-v2 .ach-medal-wrap {
  position: relative;
  display: flex;
  justify-content: center;
  margin: 6px 0 14px;
}
.ach-toast-v2 .ach-medal {
  animation: pantsy-medal-pop 0.6s cubic-bezier(.2,.9,.3,1.4) both;
  animation-delay: 0.15s;
  line-height: 0;
}
/* Bølge 56 fix #8 (2026-05-09): per-achievement icon emoji
   replaces the generic gold-medal SVG. Sized to match the medal's
   visual weight; same pop animation so existing brand chrome holds. */
.ach-toast-v2 .ach-icon-emoji {
  font-size: calc(56px * var(--text-scale));
  line-height: 1;
  animation: pantsy-medal-pop 0.6s cubic-bezier(.2,.9,.3,1.4) both;
  animation-delay: 0.15s;
  text-align: center;
  display: block;
}
.ach-toast-v2 .ach-spark {
  position: absolute;
  border-radius: 999px;
  background: var(--gold);
  box-shadow: 0 0 8px var(--gold);
  animation: pantsy-spark 1.4s ease-in-out infinite;
}
.ach-toast-v2 .ach-title-v2 {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(26px * var(--text-scale));
  letter-spacing: -0.025em;
  color: var(--text-on-deep);
  line-height: 1.1;
  text-align: center;
  position: relative;
}
.ach-toast-v2 .ach-nickname {
  margin: 4px auto 0;
  font-size: calc(13px * var(--text-scale));
  font-style: italic;
  letter-spacing: 0.01em;
  color: var(--text-soft);
  opacity: 0.78;
  line-height: 1.2;
  text-align: center;
  position: relative;
}
.ach-toast-v2 .ach-desc-v2 {
  margin: 8px auto 0;
  max-width: 240px;
  font-size: calc(13px * var(--text-scale));
  color: var(--text-soft);
  line-height: 1.4;
  text-align: center;
  position: relative;
}
.ach-toast-v2 .ach-progress {
  margin-top: 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: rgba(255, 255, 255, 0.04);
  border-radius: 10px;
  position: relative;
}
.ach-toast-v2 .ach-progress .ap-meta {
  flex: 1;
  font-size: calc(11px * var(--text-scale));
  color: var(--text-faint);
  letter-spacing: 0.04em;
}
.ach-toast-v2 .ach-progress .ap-meta .ap-xp {
  color: var(--gold);
  font-weight: 600;
}
.ach-toast-v2 .ach-progress .ap-tap {
  font-size: calc(10px * var(--text-scale));
  color: var(--text-faint);
  font-family: var(--font-mono);
  letter-spacing: 0.08em;
}

/* Per-badge share button (R4) — sits between description and progress block.
   Brand-coherent gold outline; tap stops propagation so overlay doesn't dismiss. */
.ach-toast-v2 .ach-share-btn {
  margin: 14px auto 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px;
  background: rgba(255, 244, 222, 0.08);
  color: var(--text);
  border: 1px solid rgba(255, 215, 100, 0.4);
  border-radius: 14px;
  font-family: var(--font-display, 'Bricolage Grotesque', system-ui);
  font-size: calc(13px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, transform 0.1s;
}
.ach-toast-v2 .ach-share-btn:hover {
  background: rgba(255, 244, 222, 0.18);
  border-color: rgba(255, 215, 100, 0.6);
}
.ach-toast-v2 .ach-share-btn:active {
  transform: scale(0.97);
}
.ach-toast-v2.ach-rare .ach-share-btn {
  border-color: rgba(255, 215, 100, 0.55);
  background: rgba(255, 244, 222, 0.12);
}

/* Bølge 2.17 (2026-05-07): surplus-link inside achievement overlay.
   Discreet — sits below the share button, mono-letter-spaced, no card
   chrome. Tapping it consumes the queue surplus into _highlightAchievements
   and opens Profile → Achievements with a brief pulse on each newly-
   unlocked slot. */
.ach-toast-v2 .ach-surplus-link {
  display: block;
  margin: 12px auto 0;
  padding: 6px 10px;
  background: transparent;
  color: var(--text-soft);
  border: 0;
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  text-decoration: underline;
  text-decoration-color: rgba(255, 215, 100, 0.4);
  text-underline-offset: 3px;
  transition: color 0.12s, text-decoration-color 0.12s;
}
.ach-toast-v2 .ach-surplus-link:hover {
  color: var(--text-on-deep);
  text-decoration-color: rgba(255, 215, 100, 0.75);
}

/* Pulse-highlight on Profile → Achievements grid slots when surplus link
   was just tapped. Auto-clears via JS after 3s. Subtle gold glow loop. */
.ach-slot.recently-unlocked {
  animation: achSlotPulse 1.2s ease-in-out infinite;
}
@keyframes achSlotPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 210, 74, 0.45); }
  50%      { box-shadow: 0 0 0 6px rgba(255, 210, 74, 0); }
}
@media (prefers-reduced-motion: reduce) {
  .ach-slot.recently-unlocked {
    animation: none;
    box-shadow: 0 0 0 2px rgba(255, 210, 74, 0.55);
  }
}

/* ═══════════════════════════════════════════════════════════════════════
   #20 Name-only modal — obligatory entry surface (1 tap, accept-or-edit).
   Replaces the dual-purpose rulesModal+name-prompt for first-time entry.
   Borrows the cream-card chrome from rules-modal but is a tighter, single-
   purpose surface with reroll button + auto-suggested handle.
   ═══════════════════════════════════════════════════════════════════════ */
.name-modal-card {
  background: #FFFFFF !important;
  color: var(--ink) !important;
  border-radius: 20px !important;
  padding: 24px 22px 18px !important;
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.45) !important;
  max-width: 360px !important;
  display: flex;
  flex-direction: column;
  gap: 10px;
  text-align: left;
}
.name-modal-eyebrow {
  text-align: center;
  /* Bølge 2.3 Item A (2026-05-06): hardcoded px → var(--text-scale).
     The Larger-text toggle wasn't visibly affecting the welcome modal
     because every child surface had hardcoded font-sizes that ignored
     the body class --text-scale token. Now they participate. */
  font-size: calc(12px * var(--text-scale));
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--primary);
}
.name-modal-title {
  text-align: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(24px * var(--text-scale));
  letter-spacing: -0.02em;
  color: var(--ink);
  line-height: 1.05;
  margin-bottom: 4px;
}
.name-modal-input-wrap {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
}
.name-modal-input {
  flex: 1;
  min-width: 0;
  padding: 12px 14px;
  background: #FFF8E6;
  border: 1px solid rgba(255, 87, 34, 0.16);
  border-radius: 12px;
  font-family: var(--font-sans);
  font-size: calc(16px * var(--text-scale));
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.01em;
  outline: none;
  transition: border-color 0.15s, background 0.15s;
}
.name-modal-input:focus {
  border-color: var(--primary);
  background: #FFF1D8;
}
.name-modal-input::placeholder {
  color: rgba(15, 8, 20, 0.32);
  font-style: italic;
  font-weight: 500;
}
.name-modal-reroll {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  border: 1px solid rgba(255, 87, 34, 0.20);
  background: #FFF8E6;
  color: var(--primary);
  font-size: calc(20px * var(--text-scale));
  font-weight: 700;
  cursor: pointer;
  flex-shrink: 0;
  transition: background 0.12s, transform 0.12s;
}
.name-modal-reroll:hover { background: #FFF1D8; }
.name-modal-reroll:active { transform: rotate(180deg); }

/* #62 polish (2026-05-05): reroll button INSIDE the textbox. The wrap goes
   relative-positioned, the input gets right-padding to clear the button, and
   the button absolutely-positions to the right edge. Button is borderless and
   transparent so it reads as a textbox affordance, not a separate control. */
.name-modal-input-wrap-inner-reroll {
  position: relative;
  display: block;
}
.name-modal-input-wrap-inner-reroll .name-modal-input {
  width: 100%;
  padding-right: 48px;
}
.name-modal-reroll-inner {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  width: 36px;
  height: 36px;
  border-radius: 10px;
  border: none;
  background: transparent;
  color: var(--primary);
  font-size: calc(18px * var(--text-scale));
  font-weight: 700;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.12s, transform 0.18s;
}
.name-modal-reroll-inner:hover { background: rgba(255, 87, 34, 0.10); }
.name-modal-reroll-inner:active { transform: translateY(-50%) rotate(180deg); }
.name-modal-microcopy {
  text-align: center;
  font-size: calc(11.5px * var(--text-scale));
  font-style: italic;
  color: var(--ink-soft);
  margin: 4px 0 8px;
}
.name-modal-cta {
  margin-top: 4px;
  min-height: 48px;
  width: 100%;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(16px * var(--text-scale));
  letter-spacing: -0.01em;
  border-radius: 14px;
}

/* ═══════════════════════════════════════════════════════════════════════
   GAME SHOW: Rules-modal (02a) — first-time onboarding + how-it-works
   Cream card med app-ikon, tittel, optional name-input, body, scoring,
   primær CTA. Match til Claude Design ScreenRules.
   ═══════════════════════════════════════════════════════════════════════ */
/* L (Bølge 1.8 / 2026-05-08): rules-modal overlay had been inheriting only the
   base .onboard-overlay rgba(15,23,42,.92) — at 8% transparency you can see the
   lobby code + Start-game button bleeding through behind the cream card,
   especially against bright lobby content. Force full-opacity solid backdrop
   on this overlay so the modal owns the screen unambiguously. */
.rules-modal-overlay {
  background: rgba(15, 4, 24, 0.97);
}
.rules-modal-card {
  /* D-032 (Pantsy-8 Batch 26): rules modal corner radius 24 → 20 to match design's
     slightly tighter rounding. */
  background: #FFFFFF !important;
  color: var(--ink) !important;
  border-radius: 20px !important;
  padding: 24px 22px 16px !important;
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.45) !important;
  max-width: 380px !important;
  max-height: 88dvh;
  display: flex;
  flex-direction: column;
  gap: 12px;
  text-align: left;
  overflow-y: auto;
}
.rules-modal-icon {
  display: flex;
  justify-content: center;
  align-items: flex-end;
  gap: 4px;
  margin-bottom: 4px;
  line-height: 0;
  height: 60px;
}
.rules-modal-title {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(26px * var(--text-scale));
  letter-spacing: -0.025em;
  line-height: 1.05;
  color: var(--ink);
  text-align: center;
}
.rules-modal-body {
  display: flex;
  flex-direction: column;
  /* Match Pantsy-5: tighter inter-paragraph spacing (var 10px → 6px) så
     scoring-card ikke pushes ned utenfor modal-frame. */
  gap: 6px;
  font-size: calc(14px * var(--text-scale));
  color: var(--ink-soft);
  line-height: 1.4;
  padding: 0 2px;
}
.rules-modal-body p strong {
  color: var(--ink);
  font-weight: 700;
}
.rules-modal-body p {
  margin: 0;
}
.rules-modal-scoring {
  margin-top: 4px;
  background: #FBEFD9;
  border: 1px solid rgba(255, 210, 74, 0.20);
  border-radius: 14px;
  padding: 12px 14px;
}
.rules-modal-scoring .rms-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(13px * var(--text-scale));
  color: var(--pantsy);
  letter-spacing: -0.01em;
  margin-bottom: 4px;
  text-transform: none;
}
.rules-modal-scoring .rms-details {
  font-size: calc(13px * var(--text-scale));
  color: #5A2818;
  line-height: 1.45;
  /* M (Bølge 1.8 / 2026-05-08): iOS Safari Data Detectors was auto-wrapping
     "(Smartypants)" in an implicit <a> + system-blue color, even with
     format-detection meta in place — the parenthesized capitalized word fires
     a heuristic that the meta tag doesn't fully suppress for non-phone/email
     patterns. -webkit-text-fill-color wins over the auto-link's color. */
  -webkit-text-fill-color: #5A2818;
}
.rules-modal-scoring .rms-details a {
  color: #5A2818;
  -webkit-text-fill-color: #5A2818;
  text-decoration: none;
  pointer-events: none;
}
.rules-modal-body {
  -webkit-text-fill-color: var(--ink-soft);
}
.rules-modal-body a {
  color: var(--ink-soft);
  -webkit-text-fill-color: var(--ink-soft);
  text-decoration: none;
  pointer-events: none;
}
.rules-modal-body strong {
  -webkit-text-fill-color: var(--ink);
}
.rules-modal-cta {
  /* D-033 (Pantsy-8 Batch 26): CTA was 52px tall in app vs design's ~46px standard. */
  margin-top: 6px;
  min-height: 46px;
  width: 100%;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(16px * var(--text-scale));
  letter-spacing: -0.01em;
  border-radius: 14px;
}
/* Name-prompt seksjon på 02a Rules — Pantsy-3 redesign:
   "FIRST, WHO ARE YOU?"-eyebrow + "Pick a name"-h1 + cream input med caret +
   microcopy + horisontal divider. Vises kun first-time (needsName=true). */
.rules-name-eyebrow {
  text-align: center;
  margin-top: 4px;
  margin-bottom: 6px;
  font-size: calc(12px * var(--text-scale));
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--primary);
}
.rules-name-h1 {
  text-align: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(22px * var(--text-scale));
  letter-spacing: -0.02em;
  color: var(--ink);
  line-height: 1.1;
  margin-bottom: 12px;
}
.rules-name-input-wrap {
  position: relative;
  margin-bottom: 6px;
}
.rules-name-input {
  /* D-026 (Pantsy-8 Batch 21 round 2): even at 0.30 alpha border read as too thick.
     Drop alpha to 0.16 + reduce padding 14→12 so input feels lighter overall. */
  width: 100%;
  padding: 12px 14px;
  background: #FFF8E6;
  border: 1px solid rgba(255, 87, 34, 0.16);
  border-radius: 12px;
  font-family: var(--font-sans);
  font-size: calc(16px * var(--text-scale));
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.01em;
  outline: none;
  box-shadow: none;
  transition: border-color 0.15s, background 0.15s;
}
.rules-name-input::placeholder {
  color: rgba(15, 8, 20, 0.32);
  font-style: italic;
  font-weight: 500;
}
.rules-name-input:focus {
  border-color: var(--primary);
  background: #FFF1D8;
  box-shadow: none;
}
.rules-name-microcopy {
  text-align: center;
  font-size: calc(11.5px * var(--text-scale));
  font-style: italic;
  color: var(--ink-soft);
  margin-bottom: 16px;
}
.rules-name-divider {
  /* D-031 (Pantsy-8 user-decision): bumped alpha 0.08 → 0.16 so divider reads as a
     visible separator between name-input and rules body. */
  height: 1px;
  background: rgba(15, 8, 20, 0.16);
  margin: 0 -22px 16px;
}
/* Body title: smaller når name-prompt er over (Pantsy-3 design: 20px vs 26px) */
.rules-modal-title-with-name {
  font-size: calc(20px * var(--text-scale)) !important;
  letter-spacing: -0.02em !important;
  margin-bottom: 12px !important;
}

/* ═══════════════════════════════════════════════════════════════════════
   02b Categories picker — REDESIGN match Claude Design
   ═══════════════════════════════════════════════════════════════════════
   Full-screen sheet med stats banner, search, filter pills, auto-pick,
   2-kol cream cat-cards med icon-tile/check-badge/spicy-badge/new-badge,
   custom-section med shared-with-club-tag, og dotted "Build a new" card.
   Dark surface-deep bakgrunn (sheet-overlay leverer det). */

.cat-pick-body {
  /* Strammere gap enn standard cat-sheet-body siden vi har flere seksjoner */
  gap: 14px;
  /* Bølge 2.3 Item M (2026-05-06): explicit min-height on the picker body
     so the sheet always paints a full-viewport surface even when content
     is shorter than the screen. Belt-and-suspenders against the user's
     "lobby Start button visible at bottom of picker" report — the
     .sheet-overlay already has --surface-deep background, but if any
     descendant clips visibility (transform / contain / etc.), this min-
     height ensures the body itself fills. */
  min-height: 100dvh;
  padding-bottom: max(24px, env(safe-area-inset-bottom));
}

/* ── Status row (top: count + words + games estimate + Clear) ──────────
   Match Pantsy-5 design 02b: plain inline tekst, INGEN bordered card.
   Stats er kontekstuelt — ikke en CTA — så bør ikke se ut som en.
   B70 (2026-05-10): `position: sticky` so the summary stays visible when the
   user scrolls long category lists. Per RESKIN-PRINCIPLES sec. 7 (cross-screen
   coherence) + Decision 1 in B70/B89 specs. The wrapper carries a solid
   `--surface-deep` bg so scrolled content beneath doesn't bleed through. */
.cat-pick-stats {
  position: sticky;
  top: 0;
  z-index: 4;
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 8px 4px 6px;
  background: var(--surface-deep);
  border: none;
  border-radius: 0;
}
.cat-pick-stats .cps-chip {
  /* Pantsy-7: liten orange "N"-boks i starten av summary-banner. Filled fire-color
     med ink text for kontrast. Match design — gir count visuell vekt. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 22px;
  height: 22px;
  padding: 0 7px;
  background: var(--primary);
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: calc(12px * var(--text-scale));
  letter-spacing: -0.02em;
  border-radius: 6px;
  flex-shrink: 0;
}
/* Skjul chippen når 0 valgt — ingen orange "0" som ser merkelig ut */
.cat-pick-stats:has(.cps-chip:empty) .cps-chip { display: none; }
.cat-pick-stats .cps-meta {
  flex: 1;
  min-width: 0;
}
.cat-pick-stats .cps-meta-line {
  font-size: calc(12px * var(--text-scale));
  font-weight: 700;
  color: var(--text-on-deep);
  line-height: 1.3;
  letter-spacing: -0.005em;
}
/* #65 polish (2026-05-05): pool-over-cap hint — soft amber emphasis line below
   the count, only visible when totalWords > 200. Uses warning palette without
   the alarm tone of an error. */
.cat-pick-stats .cps-cap-hint {
  font-size: calc(11px * var(--text-scale));
  color: var(--gold, #FFD24A);
  margin-top: 4px;
  line-height: 1.35;
  font-weight: 500;
  letter-spacing: 0;
}
.cat-pick-stats .cps-meta-sub {
  font-size: calc(11px * var(--text-scale));
  color: var(--text-muted);
  margin-top: 1px;
  line-height: 1.35;
}
.cat-pick-stats .cps-clear-btn {
  /* Match Pantsy-5: bare tekst-link, ingen pill-border */
  background: transparent;
  color: var(--text-soft);
  border: none;
  padding: 0 4px;
  font-family: inherit;
  font-weight: 600;
  font-size: calc(12px * var(--text-scale));
  cursor: pointer;
  flex-shrink: 0;
  text-decoration: underline;
  text-decoration-color: rgba(255, 244, 222, 0.20);
  text-underline-offset: 2px;
}
.cat-pick-stats .cps-clear-btn:hover {
  color: var(--text-on-deep);
}

/* B44 D-011 (2026-05-09): selection-summary card chassis. Mirrors the
   design pack at screens-4.jsx:174–212 — fire-tinted bg + border, 28x28
   number badge on the left, label/sub stack in the middle, small Clear
   button on the right. The outer .cat-pick-stats stays as the section
   wrapper (so the .cps-cap-hint sibling for over-cap warning still
   renders in the same flow column). */
/* B70 (2026-05-10): summary banner is fire-tinted per `_pantsy9/<folder>/screens-4.jsx`
   (`${t.fire}0D` bg, `${t.fire}22` border, `${t.fire}33` badge bg, `t.fire` badge fg).
   Pre-B70 the chassis was amber (legacy from B44 D-011 mistake). Token-swap to
   `--fire` derivatives unifies the picker with the rest of the reskin (Vote/B64,
   BestClue/B65, Build-cat/B66, FinalStand/B67) where fire = primary accent. */
.cat-pick-summary-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  background: rgba(255, 87, 34, 0.05);
  border: 1px solid rgba(255, 87, 34, 0.13);
  border-radius: var(--radius-btn, 12px);
}
.cps-summary-badge {
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 87, 34, 0.20);
  color: var(--fire, #FF5722);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: calc(14px * var(--text-scale));
  letter-spacing: -0.02em;
  border-radius: 8px;
  flex-shrink: 0;
}
.cps-summary-meta {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.cps-summary-label {
  font-size: calc(13px * var(--text-scale));
  font-weight: 600;
  color: var(--text-on-deep);
  line-height: 1.3;
  letter-spacing: -0.005em;
}
.cps-summary-sub {
  font-size: calc(11px * var(--text-scale));
  color: var(--text-muted);
  line-height: 1.3;
}
.cps-summary-clear {
  position: relative;
  flex-shrink: 0;
  height: 28px;
  padding: 0 12px;
  background: transparent;
  border: 1px solid rgba(255, 244, 222, 0.16);
  border-radius: 8px;
  color: var(--text-soft);
  font-family: inherit;
  font-weight: 600;
  font-size: calc(12px * var(--text-scale));
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
/* B89 (2026-05-10) Decision 3: 44×44 hit target. The visual chip stays
   at 28px (matches the design pack), the ::before extends the touch
   surface to 44×44 per RESKIN-PRINCIPLES sec. 3 a11y. */
.cps-summary-clear::before {
  content: "";
  position: absolute;
  inset: -8px;
  border-radius: inherit;
}
.cps-summary-clear:hover {
  background: rgba(255, 244, 222, 0.06);
  border-color: rgba(255, 244, 222, 0.28);
  color: var(--text-on-deep);
}

/* (Search bar + filter pills CSS fjernet — features ble droppet fordi
    de ikke ga verdi med ~12 kategorier.) */

/* ── Section row (eyebrow left + tag right) ────────────────────────── */
.cat-pick-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.cat-pick-section-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(10.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.10em;
  color: var(--text-faint);
  text-transform: uppercase;
}
.cat-pick-section-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.cat-pick-shared-tag {
  font-family: var(--font-mono);
  font-size: calc(9.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.10em;
  color: var(--gold);
  background: rgba(255, 210, 74, 0.10);
  border: 1px solid rgba(255, 210, 74, 0.25);
  padding: 4px 8px;
  border-radius: 6px;
  text-transform: uppercase;
}

/* ── Cat-card grid (Pantsy-9 user-decision: 2-column tighter layout) ─────
   Pantsy-9: full-width tall rows ble for store når listen ble lang.
   2-col grid med gap 8px — hver kort er nå halve raden og litt mer kompakt.
   Cards beholder samme indre layout (icon + name/meta + check), bare narrower.
   Mobiler under 360px får 1-col fallback så cards ikke blir for trange. */
.cat-pick-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
@media (max-width: 360px) {
  .cat-pick-grid { grid-template-columns: 1fr; }
}

/* B41.2 (2026-05-09): seasonal-upcoming card ("next season dukker opp …")
   visual-rhymes with an UNSELECTED .cat-pick-card. Pre-B41.2 it carried
   `card sm` cream-fill, which read as "selected" in the picker grid — wrong
   semantic for an informational tile. Surface bg + same border/radius +
   icon-tile + body layout brings it in line with the rest of the picker. */
.cat-pick-seasonal-upcoming {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px 14px;
  background: rgba(255, 244, 222, 0.04);
  color: var(--text-on-deep, #FFF6E0);
  border: 1px solid rgba(255, 244, 222, 0.10);
  border-radius: 12px;
  min-height: 60px;
  width: 100%;
}
.cat-pick-seasonal-upcoming .cpsu-icon-tile {
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  flex-shrink: 0;
  background: transparent;
}
.cat-pick-seasonal-upcoming .cpsu-icon-emoji {
  font-size: calc(22px * var(--text-scale));
  line-height: 1;
}
.cat-pick-seasonal-upcoming .cpsu-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.cat-pick-seasonal-upcoming .cps-upcoming-line {
  font-weight: 600;
  font-size: calc(14px * var(--text-scale));
  letter-spacing: -0.005em;
  line-height: 1.25;
  color: var(--text-on-deep);
}
.cat-pick-seasonal-upcoming .cps-upcoming-sub {
  font-size: calc(12px * var(--text-scale));
  line-height: 1.3;
  color: var(--text-muted, rgba(255, 244, 222, 0.55));
}

/* Single cat-card. To distinkte tilstander:
     - SELECTED  → cream-fill bakgrunn (FFF6E0), mørk tekst, vert-centered check
     - UNSELECTED → dark transparent bakgrunn, lys tekst, outlined check
   Emoji-en sitter DIREKTE på card-bakgrunnen (ingen container-tile bak).
   Layout er flatere/widere enn høy for å matche design 2.
   min-width:0 på grid-item så cards alltid blir like brede uansett tekst-lengde. */
.cat-pick-card {
  /* #23 (Phase 4 Sprint D): with the check-badge moved to bottom-left and
     shrunk to 18px, we no longer reserve right-rail space for it. Padding
     bottom is bumped slightly so the small badge doesn't touch the meta-line.
     Tap target stays the whole card panel. */
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px 14px;
  background: rgba(255, 244, 222, 0.04);
  color: var(--text-on-deep, #FFF6E0);
  border: 1px solid rgba(255, 244, 222, 0.10);
  border-radius: 12px;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  min-height: 60px;
  min-width: 0; /* grid-item: lar ellipsis fungere på cpc-name */
  width: 100%;
  transition: background 0.12s ease, border-color 0.12s ease, transform 0.12s ease, color 0.12s ease;
  -webkit-tap-highlight-color: transparent;
}
.cat-pick-card:hover {
  background: rgba(255, 244, 222, 0.06);
  border-color: rgba(255, 244, 222, 0.16);
}
.cat-pick-card:active {
  transform: scale(0.985);
}

/* SELECTED: full cream-fill, dark tekst, lyst icon-tile-bakgrunn. */
.cat-pick-card.selected {
  background: var(--surface-card, #FFF6E0);
  color: var(--text-on-card, #2A1424);
  border-color: transparent;
}
.cat-pick-card.selected:hover {
  background: var(--surface-card, #FFF6E0);
}

.cat-pick-card.locked {
  opacity: 0.45;
  cursor: not-allowed;
}
.cat-pick-card.locked .cpc-icon-tile {
  filter: grayscale(0.35);
}

/* Icon "tile" — INGEN bakgrunn. Bare en flex-container med fast bredde slik
   at emojien sitter rolig venstrejustert uavhengig av om kategori-navn er
   1 eller 2 ord. Emojien er det visuelle ankret. */
.cpc-icon-tile {
  /* Pantsy-9: 2-col layout — icon-tile redusert fra 40→34 så cards har plass
     til navnet uten å bli truncated. Emoji-en er fortsatt visuelt anker. */
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  flex-shrink: 0;
  background: transparent;
}
.cpc-icon-emoji {
  font-size: calc(22px * var(--text-scale));
  line-height: 1;
}

.cpc-body {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.cpc-name {
  /* D-034: bumped to 16px for tall-row layout — more present than the dense 2-col grid. */
  font-weight: 700;
  font-size: calc(16px * var(--text-scale));
  letter-spacing: -0.005em;
  line-height: 1.2;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.cpc-meta {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: nowrap;
  font-size: calc(11px * var(--text-scale));
  color: inherit;
  opacity: 0.65;
  font-family: var(--font-mono);
  font-weight: 500;
  line-height: 1.2;
}
.cat-pick-card.selected .cpc-meta {
  opacity: 0.75;
  color: var(--ink-soft, #5C4033);
}
.cpc-words { white-space: nowrap; }
.cpc-author { white-space: nowrap; opacity: 0.75; }

/* Check badge — #23 (Phase 4 Sprint D): lower-left, shrunk, hidden until
   selected. Tap target stays the entire card panel; the badge is now a quiet
   confirmation stamp rather than a competing right-rail anchor. Selected
   cards already get a primary border + background tint via .selected, so the
   tiny corner stamp adds an at-a-glance confirmation without visual noise on
   unselected cards. */
.cpc-check {
  position: absolute;
  bottom: 6px;
  right: 8px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  display: none;
  align-items: center;
  justify-content: center;
  font-size: calc(9px * var(--text-scale));
  font-weight: 800;
  background: var(--primary);
  border: none;
  color: #fff;
  pointer-events: none;
}
.cat-pick-card.selected .cpc-check,
.cpc-check.filled {
  display: flex;
}
.cat-pick-card.spicy.selected .cpc-check {
  background: var(--pantsy);
}

/* Spicy badge inline i meta-row */
.cpc-spicy-badge {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  background: rgba(255, 23, 68, 0.14);
  color: var(--pantsy);
  border: 1px solid rgba(255, 23, 68, 0.25);
  padding: 2px 7px;
  border-radius: 999px;
  font-size: calc(10px * var(--text-scale));
  font-weight: 700;
  font-family: var(--font-mono);
  letter-spacing: 0.04em;
  white-space: nowrap;
}
.cpc-spicy-flame { font-family: inherit; font-size: calc(10px * var(--text-scale)); }

/* NEW badge — vertikalt sentrert, like til venstre for check-sirkelen.
   Matcher Claude Design 2 hvor NEW-pill sitter mid-card på høyre side. */
.cpc-new-badge {
  position: absolute;
  top: 50%;
  right: 42px;
  transform: translateY(-50%);
  background: var(--pantsy);
  color: #fff;
  font-family: var(--font-mono);
  font-size: calc(9.5px * var(--text-scale));
  font-weight: 800;
  letter-spacing: 0.06em;
  padding: 3px 7px;
  border-radius: 999px;
  text-transform: uppercase;
  box-shadow: 0 2px 6px rgba(255, 23, 68, 0.30);
}

/* B70 (2026-05-10): 18+ badge — pantsyRed-tinted mono pill per
   `_pantsy9/<folder>/screens-4.jsx` lines 96-101. When NEW is also present
   the 18+ pill nudges left to avoid overlap. */
.cpc-age-badge {
  position: absolute;
  top: 50%;
  right: 42px;
  transform: translateY(-50%);
  background: rgba(255, 23, 68, 0.14);
  color: var(--pantsy);
  border: 1px solid rgba(255, 23, 68, 0.25);
  font-family: var(--font-mono);
  font-size: calc(9px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.10em;
  padding: 2px 6px;
  border-radius: 4px;
  text-transform: uppercase;
}
.cat-pick-card .cpc-new-badge + .cpc-age-badge,
.cat-pick-card:has(.cpc-new-badge) .cpc-age-badge {
  right: 78px;
}

/* ── Build a new category card (full-width, dotted) ───────────────── */
.cat-pick-build {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 16px;
  background: transparent;
  border: 1.5px dashed rgba(255, 244, 222, 0.22);
  border-radius: 14px;
  color: var(--text-on-deep);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
}
.cat-pick-build:hover {
  border-color: rgba(255, 87, 34, 0.45);
  background: rgba(255, 87, 34, 0.04);
}
.cat-pick-build .cpb-plus {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: rgba(255, 244, 222, 0.06);
  border: 1px solid rgba(255, 244, 222, 0.18);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(22px * var(--text-scale));
  line-height: 1;
  font-weight: 300;
  color: var(--text-soft);
  flex-shrink: 0;
}
.cat-pick-build .cpb-body {
  flex: 1;
  min-width: 0;
}
.cat-pick-build .cpb-title {
  font-weight: 700;
  font-size: calc(14px * var(--text-scale));
  color: var(--text-on-deep);
  line-height: 1.2;
}
.cat-pick-build .cpb-hint {
  font-size: calc(11.5px * var(--text-scale));
  color: var(--text-muted);
  margin-top: 3px;
  line-height: 1.35;
}

/* ═══════════════════════════════════════════════════════════════════════
   Build category sheet — full-screen tabbed sheet (AI ↔ Manuell)
   ═══════════════════════════════════════════════════════════════════════ */

/* Sheet-modal med pinned footer-rad: body scroller, footer står stille. */
.sheet-modal-with-footer {
  display: flex;
  flex-direction: column;
}
.sheet-modal-with-footer .sheet-body {
  flex: 1;
  overflow-y: auto;
}
.sheet-footer {
  border-top: 1px solid rgba(255, 244, 222, 0.08);
  padding: 14px 20px calc(14px + env(safe-area-inset-bottom, 0));
  background: var(--surface-deep);
  flex-shrink: 0;
}

.build-sheet-body {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* ── Segmented tab control (AI generate / Type my own) ───────────
   D-043 (user decision): tightened active pill so it doesn't protrude — design uses
   a flat cream pill with subtle inset shadow, not a raised oval. Reduce padding +
   shadow blur. */
.build-tab-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  padding: 3px;
  background: rgba(255, 244, 222, 0.04);
  border: 1px solid rgba(255, 244, 222, 0.10);
  border-radius: var(--radius-pill);
}
.build-tab {
  background: transparent;
  border: none;
  color: var(--text-soft);
  font-family: inherit;
  font-weight: 600;
  font-size: calc(13px * var(--text-scale));
  padding: 7px 10px;
  border-radius: calc(var(--radius-pill) - 3px);
  cursor: pointer;
  transition: background 0.12s, color 0.12s;
}
.build-tab:hover {
  color: var(--text-on-deep);
}
.build-tab.active {
  background: var(--surface-card, #FFF6E0);
  color: var(--text-on-card, #2A1424);
  font-weight: 700;
  box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.04), 0 1px 3px rgba(0, 0, 0, 0.10);
}

/* Item 1 (Bølge 1.9 / 2026-05-08): tap-to-edit name display card. Renders
   as a button-styled chip with circular emoji avatar + vertical orange
   separator + bold-italic name + small "TAP TO EDIT" hint. Tap flips to
   .build-name-field edit mode. */
.build-name-card {
  display: flex;
  align-items: center;
  gap: 0;
  padding: 10px 14px;
  background: rgba(255, 244, 222, 0.04);
  border: 1px solid rgba(255, 244, 222, 0.10);
  border-radius: 14px;
  cursor: pointer;
  transition: background .12s, border-color .12s;
  width: 100%;
  font-family: inherit;
  text-align: left;
}
.build-name-card:hover {
  background: rgba(255, 244, 222, 0.06);
  border-color: rgba(255, 244, 222, 0.16);
}
.build-name-card .bnc-emoji {
  width: 44px;
  height: 44px;
  border-radius: 22px;
  background: rgba(255, 244, 222, 0.06);
  border: 1px solid rgba(255, 244, 222, 0.12);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(22px * var(--text-scale));
  flex-shrink: 0;
}
.build-name-card .bnc-divider {
  width: 2px;
  height: 28px;
  background: var(--primary);
  margin: 0 14px;
  flex-shrink: 0;
  border-radius: 1px;
}
.build-name-card .bnc-name {
  flex: 1;
  min-width: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-style: italic;
  font-size: calc(17px * var(--text-scale));
  color: var(--text-on-deep);
  letter-spacing: -0.005em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.build-name-card .bnc-name.empty {
  color: var(--text-faint);
  font-weight: 600;
}
.build-name-card .bnc-edit-hint {
  font-family: var(--font-mono);
  font-size: calc(9.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--text-faint);
  text-transform: uppercase;
  flex-shrink: 0;
  margin-left: 8px;
}

/* ── Name field with emoji avatar ──────────────────────────────── */
.build-name-field {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  background: rgba(255, 244, 222, 0.04);
  border: 1px solid rgba(255, 244, 222, 0.10);
  border-radius: 14px;
}
.build-emoji-avatar {
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: rgba(255, 244, 222, 0.06);
  border: 1px solid rgba(255, 244, 222, 0.12);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(22px * var(--text-scale));
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
  font-family: inherit;
}
.build-emoji-avatar:hover {
  background: rgba(255, 244, 222, 0.10);
}
.build-name-input-wrap {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.build-name-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(9.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--text-faint);
  text-transform: uppercase;
}
.build-name-input {
  background: transparent;
  border: none;
  outline: none;
  color: var(--text-on-deep);
  font-family: inherit;
  font-size: calc(16px * var(--text-scale));
  font-weight: 700;
  letter-spacing: -0.005em;
  padding: 0;
  width: 100%;
}
.build-name-input::placeholder {
  color: var(--text-faint);
  font-weight: 600;
}

/* ── AI mode body ─────────────────────────────────────────────── */
.build-ai-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.build-ai-pending {
  text-align: center;
  padding: 16px 12px;
  background: rgba(255, 210, 74, 0.06);
  border: 1px dashed rgba(255, 210, 74, 0.32);
  border-radius: 12px;
}
.build-ai-pending-emoji {
  font-size: calc(28px * var(--text-scale));
  margin-bottom: 6px;
  animation: aiSparkle 1.2s ease-in-out infinite;
}
@keyframes aiSparkle {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.15); opacity: 0.7; }
}
.build-ai-pending-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(14px * var(--text-scale));
  color: var(--gold);
  margin-bottom: 3px;
}
.build-ai-pending-sub {
  font-size: calc(12px * var(--text-scale));
  color: var(--text-muted);
  font-style: italic;
}

.build-ai-desc {
  margin: 0;
  font-size: calc(13px * var(--text-scale));
  line-height: 1.45;
  color: var(--text-soft);
  padding: 0 2px;
}

/* Eksempler-blokk */
.build-examples {
  background: rgba(255, 244, 222, 0.03);
  border: 1px solid rgba(255, 244, 222, 0.08);
  border-radius: 12px;
  padding: 10px 4px 10px 4px;
  display: flex;
  flex-direction: column;
  gap: 0;
}
/* Card-variant brukt i den nye build-cat layouten — mer luft rundt rader,
   konsistent emoji-bredde for tight kolonne-alignment matching design. */
.build-examples-card {
  background: rgba(255, 244, 222, 0.04);
  border: 1px solid rgba(255, 244, 222, 0.10);
  padding: 8px 4px;
}

/* ─── ★ SUGGESTED block (build-cat AI mode) ─────────────────────────
   Auto-derived navn + emoji fra description. Tap to edit → inline editor. */
.build-suggested-block {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 4px;
}
/* #25 P1 #1 typing-bug fix: SUGGESTED is always rendered (no mount/unmount on
   keystroke), and hidden via this class while the description is too short.
   Using visibility:hidden + min-height keeps layout stable so subsequent
   blocks (examples list) don't jump when the suggestion appears. */
.build-suggested-block.is-empty {
  visibility: hidden;
  pointer-events: none;
  /* Reserves the same vertical footprint as the populated state so the
     examples list sits at a stable scroll-position. Tweak if the suggested
     card grows. */
  min-height: 60px;
}
.build-suggested-eyebrow {
  display: flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: calc(9.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--text-faint);
  text-transform: uppercase;
  padding-left: 4px;
}
.build-suggested-eyebrow .bse-star {
  color: var(--gold);
  font-size: calc(11px * var(--text-scale));
  line-height: 1;
}
.build-suggested-card {
  /* D-046 (user decision): compact chip — design has tight horizontal pill, not a tall
     card. Tighten padding 14→8/12, emoji tile 36→26, name font 15.5→14. */
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: rgba(255, 244, 222, 0.04);
  border: 1px solid rgba(255, 244, 222, 0.12);
  border-radius: 999px;
  color: var(--text-on-deep);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: background .12s, border-color .12s;
}
.build-suggested-card:hover {
  background: rgba(255, 244, 222, 0.06);
  border-color: rgba(255, 244, 222, 0.18);
}
/* Bølge 97.3 (2026-05-10): match design pack JSX 133-138 — 36×36
   square avatar with 10px radius (was 26×26 circle pre-B97.3).
   Closes audit § B66 P1-6. */
.build-suggested-card .bsc-emoji {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: rgba(255, 244, 222, 0.06);
  border: 1px solid rgba(255, 244, 222, 0.10);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: calc(18px * var(--text-scale));
  flex-shrink: 0;
}
.build-suggested-card .bsc-name {
  flex: 1;
  min-width: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(14px * var(--text-scale));
  letter-spacing: -0.01em;
  color: var(--text-on-deep);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.build-suggested-card .bsc-edit-hint {
  font-family: var(--font-mono);
  font-size: calc(9px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--text-faint);
  text-transform: uppercase;
  flex-shrink: 0;
}
/* Inline edit-state — emoji-tile + tekst-input på samme rad */
.build-suggested-edit {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 14px;
  background: rgba(255, 87, 34, 0.06);
  border: 1px solid rgba(255, 87, 34, 0.28);
  border-radius: 14px;
}
.build-emoji-inline {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: rgba(255, 244, 222, 0.06);
  border: 1px solid rgba(255, 244, 222, 0.14);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: calc(18px * var(--text-scale));
  cursor: pointer;
  padding: 0;
}
.build-suggested-name-input {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(15.5px * var(--text-scale));
  letter-spacing: -0.01em;
  color: var(--text-on-deep);
  outline: none;
}
.build-examples-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(9.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--text-faint);
  text-transform: uppercase;
  padding: 4px 12px 6px;
}
.build-example-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: transparent;
  border: none;
  color: var(--text-on-deep);
  font-family: inherit;
  font-size: calc(13.5px * var(--text-scale));
  font-weight: 500;
  text-align: left;
  cursor: pointer;
  border-radius: 8px;
  transition: background 0.10s;
}
.build-example-row:hover {
  background: rgba(255, 244, 222, 0.05);
}
.build-example-row .be-icon {
  font-size: calc(16px * var(--text-scale));
  width: 22px;
  text-align: center;
  flex-shrink: 0;
}
.build-example-row .be-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Beskriv-input-blokk — Pantsy-6: input-wrap har relative position så
   inline Generate-pill kan absolute-positionere bottom-right inni boksen. */
.build-describe-block {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 4px;
}
.build-describe-input-wrap {
  position: relative;
  /* Bølge 13 (2026-05-08, marathon-2 H5): cursor:text on the wrap so users
     get the standard "click here to type" affordance even at coordinates
     where the inline Generate pill is absolutely-positioned. The wrap's
     onclick handler (in render) re-targets focus onto the textarea when
     the click target wasn't the pill itself. */
  cursor: text;
}
.build-describe-input.has-inline-cta {
  /* Padding bottom large nok til at Generate-pill ikke overlapper tekst */
  padding-bottom: 44px;
  resize: none;
  font-family: inherit;
  width: 100%;
  background: rgba(255, 244, 222, 0.04);
  border: 1px solid rgba(255, 244, 222, 0.12);
  border-radius: 12px;
  padding-left: 14px;
  padding-right: 14px;
  padding-top: 12px;
  color: var(--text-on-deep);
  font-size: calc(14px * var(--text-scale));
  line-height: 1.4;
  outline: none;
}
.build-describe-input.has-inline-cta:focus {
  border-color: rgba(255, 87, 34, 0.42);
  background: rgba(255, 87, 34, 0.06);
}
/* Inline Generate-pill — Pantsy-6 design 02b1: liten fire-tinted pill nederst
   til høyre INNI describe-input-boksen. Fire-tinted bg + outline + sparkle ikon. */
.build-inline-generate {
  position: absolute;
  right: 8px;
  bottom: 8px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 30px;
  padding: 0 12px;
  background: rgba(255, 87, 34, 0.10);
  border: 1px solid rgba(255, 87, 34, 0.34);
  border-radius: 999px;
  color: var(--primary);
  font-family: var(--font-sans);
  font-weight: 700;
  font-size: calc(12px * var(--text-scale));
  letter-spacing: -0.005em;
  cursor: pointer;
  transition: background .12s, border-color .12s;
}
.build-inline-generate:hover {
  background: rgba(255, 87, 34, 0.18);
}
.build-inline-generate.is-pending {
  opacity: 0.7;
  cursor: progress;
}
/* Bølge 13 (2026-05-08, marathon-2 H3): empty-input disabled state. Pairs
   with the disabled HTML attribute set in the render — the attribute blocks
   the click; this gives users the visual signal so they don't tap into a
   silent no-op. Subtle enough to not feel like a hard error. */
.build-inline-generate[disabled],
.build-inline-generate.is-disabled {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
}
.build-inline-generate .big-spark {
  font-size: calc(12px * var(--text-scale));
  color: var(--primary);
}

/* × delete affordance på custom category cards (Pantsy-6 02b/02b3).
   Subtle hairline-circle i top-right; sel + unsel begge synlige. */
.cat-pick-card.custom-card { position: relative; }
.cat-pick-card .cpc-delete-btn {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 20px;
  height: 20px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-faint);
  border: none;
  font-family: inherit;
  font-size: calc(13px * var(--text-scale));
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  flex-shrink: 0;
  transition: background .12s, color .12s;
}
/* B89 (2026-05-10) Decision 3: 44×44px hit target. Visual chip stays at
   20×20 (per design pack screens-4.jsx:113-123 which uses an 18×18 disc),
   the ::before extends the touch surface to a11y-compliant 44×44.
   Pre-B89 a delete-X tap was easy to miss-fire onto the underlying card
   toggle — the hit-area expansion fixes that without altering pixels. */
.cat-pick-card .cpc-delete-btn::before {
  content: "";
  position: absolute;
  inset: -12px;
  border-radius: inherit;
}
.cat-pick-card .cpc-delete-btn:hover {
  background: rgba(255, 23, 68, 0.18);
  color: var(--pantsy-hi);
}
.cat-pick-card.selected .cpc-delete-btn {
  /* På selected (cream-fill) kort vil vi ha mørk tone for kontrast */
  background: rgba(0, 0, 0, 0.08);
  color: var(--ink-soft);
}

/* Pantsy-6 lobby: club-recognised banner over Start-game CTA.
   Gold-tinted card med klubb-initial avatar + navn + GAMES/BEHIND-stat. */
.lobby-club-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: linear-gradient(135deg, rgba(255, 210, 74, 0.08) 0%, rgba(255, 210, 74, 0.02) 100%);
  border: 1px solid rgba(255, 210, 74, 0.27);
  border-radius: var(--radius-btn);
  margin: 6px 0 8px;
  cursor: pointer;
}
.lobby-club-banner .lcb-avatar {
  width: 32px;
  height: 32px;
  border-radius: 9px;
  background: linear-gradient(135deg, var(--gold), var(--ember, #FF8A50));
  color: var(--ink);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(14px * var(--text-scale));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.lobby-club-banner .lcb-meta {
  flex: 1;
  min-width: 0;
}
.lobby-club-banner .lcb-name {
  font-size: calc(12.5px * var(--text-scale));
  font-weight: 700;
  color: var(--text-on-deep);
  line-height: 1.15;
}
.lobby-club-banner .lcb-stat {
  font-size: calc(10px * var(--text-scale));
  color: var(--text-faint);
  font-family: var(--font-mono);
  letter-spacing: 0.06em;
  margin-top: 2px;
  text-transform: uppercase;
}
.lobby-club-banner .lcb-arrow {
  color: var(--text-faint);
  font-size: calc(14px * var(--text-scale));
  flex-shrink: 0;
}
.build-describe-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(9.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--text-faint);
  text-transform: uppercase;
}
/* Bølge 13 (2026-05-08): empty-input hint sitting below the textarea wrap.
   Muted/italic so it reads as guidance, not error. Only rendered when the
   input is empty (build-describe-empty-hint mounts conditionally in app.js). */
.build-describe-empty-hint {
  margin-top: 6px;
  font-size: calc(12px * var(--text-scale));
  font-style: italic;
  color: var(--text-faint);
  line-height: 1.4;
}
.build-describe-input {
  width: 100%;
  background: rgba(255, 244, 222, 0.04);
  border: 1px solid rgba(255, 244, 222, 0.12);
  border-radius: 12px;
  padding: 12px 14px;
  color: var(--text-on-deep);
  font-family: inherit;
  font-size: calc(14px * var(--text-scale));
  font-weight: 500;
  outline: none;
  transition: border-color 0.12s, background 0.12s;
}
.build-describe-input::placeholder {
  color: var(--text-faint);
  font-style: italic;
}
.build-describe-input:focus {
  border-color: rgba(255, 87, 34, 0.40);
  background: rgba(255, 87, 34, 0.04);
}

/* ── Manual mode body ──────────────────────────────────────────── */
.build-manual-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.build-words-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 4px;
}
.build-words-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(9.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--text-faint);
  text-transform: uppercase;
}
.build-words-count {
  /* D-056 (Pantsy-8 user-decision): app rendered counter in fire/orange — design uses
     a calmer faint-grey mono. The counter is supporting information, not a CTA, so it
     shouldn't compete with the title. */
  font-family: var(--font-mono);
  font-size: calc(9.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.12em;
  color: var(--text-faint);
  text-transform: uppercase;
}
/* Items 2-5 (Bølge 1.9 / 2026-05-08): words list refactor.
   - Container: stack of chips (no shared box, gap rhythm).
   - Row: tinted chip with focus-within highlight + 2px orange cursor bar
     on the left edge while editing.
   - bw-input: italic faint grey by default; bright + non-italic on focus. */
.build-words-list {
  display: flex;
  flex-direction: column;
  gap: 3px;
  background: transparent;
  border: none;
  border-radius: 0;
  overflow: visible;
}
.build-word-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 14px 9px 12px;
  background: rgba(255, 244, 222, 0.025);
  border: 1px solid rgba(255, 244, 222, 0.06);
  border-radius: 9px;
  border-left: 2px solid transparent;
  transition: background .12s, border-color .12s;
}
.build-word-row:focus-within {
  background: rgba(255, 244, 222, 0.04);
  border-color: rgba(255, 87, 34, 0.20);
  border-left-color: var(--primary);
}
.bw-num {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  font-weight: 600;
  color: var(--text-faint);
  width: 22px;
  flex-shrink: 0;
  letter-spacing: 0.04em;
}
.bw-input {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: none;
  outline: none;
  color: var(--text-soft);
  font-family: inherit;
  font-style: italic;
  font-size: calc(14px * var(--text-scale));
  font-weight: 400;
  padding: 4px 0;
  transition: color .15s, font-style .15s, font-weight .15s;
}
.bw-input:focus {
  color: var(--text-on-deep);
  font-style: normal;
  font-weight: 500;
}
.bw-input::placeholder {
  color: var(--text-faint);
  font-style: italic;
  font-weight: 400;
}

/* B98.1 (2026-05-11): legacy `.build-review-*` chassis retired.
   B66 originally shipped a vertical-list review state for the AI Generate
   surface (.build-review-row + .build-review-word + .build-review-delete
   + .build-review-back + .build-review-words-list). B97.3 (commit d8ae11e)
   replaced this with the wrap-flow pill-grid chassis
   (.build-review-chips-grid + .build-review-chip — see the B97.3 block
   later in this file). The legacy rules became inert at that point.
   ~95 LOC removed. */

/* ── Footer (Cancel + primary CTA) ────────────────────────────── */
.build-cta-row {
  display: flex;
  align-items: center;
  gap: 10px;
}
.build-cancel-btn {
  flex-shrink: 0;
  width: auto;
  min-width: 88px;
  padding: 14px 22px;
  background: transparent;
  color: var(--text-soft);
  border: 1px solid rgba(255, 244, 222, 0.18);
  border-radius: var(--radius-pill);
  font-family: inherit;
  font-weight: 600;
  font-size: calc(14px * var(--text-scale));
  cursor: pointer;
}
.build-cancel-btn:hover {
  background: rgba(255, 255, 255, 0.04);
}
.build-primary-btn {
  flex: 1;
  min-height: 50px;
  border-radius: var(--radius-pill) !important;
  font-size: calc(15px * var(--text-scale)) !important;
  font-weight: 700 !important;
}
.build-primary-btn.is-pending {
  opacity: 0.7;
  pointer-events: none;
}

/* ─── Pantsy-6 Profile clubs section ─────────────────────────────────
   "Your clubs · N" subsection mellom identity-card og Lifetime stats.
   Hver rad: 32px klubb-initial avatar (gold gradient hvis hi/leader),
   klubbnavn + games-count mono, så crown + topp 3 navn.  Tappbar. */
.profile-club-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  margin-bottom: 5px;
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-btn);
  cursor: pointer;
  width: 100%;
  text-align: left;
  font-family: inherit;
  color: inherit;
}
.profile-club-row .pcr-avatar {
  width: 32px;
  height: 32px;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.06);
  color: var(--text-soft);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(14px * var(--text-scale));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.profile-club-row.is-hi .pcr-avatar {
  background: linear-gradient(135deg, var(--gold), var(--ember, #FF8A50));
  color: var(--ink);
}
.profile-club-row .pcr-meta {
  flex: 1;
  min-width: 0;
}
.profile-club-row .pcr-top {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
}
.profile-club-row .pcr-club-name {
  font-weight: 600;
  font-size: calc(13px * var(--text-scale));
  line-height: 1.15;
  color: var(--text-on-deep);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 0 1 auto;
  min-width: 0;
}
.profile-club-row .pcr-games {
  font-size: calc(9.5px * var(--text-scale));
  color: var(--text-faint);
  font-family: var(--font-mono);
  letter-spacing: 0.06em;
  flex-shrink: 0;
}
.profile-club-row .pcr-bottom {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-top: 3px;
  font-size: calc(11px * var(--text-scale));
  color: var(--text-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.profile-club-row .pcr-crown {
  font-size: calc(10px * var(--text-scale));
  line-height: 1;
  flex-shrink: 0;
}
.profile-club-row .pcr-name {
  color: var(--text-soft);
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 80px;
}
.profile-club-row .pcr-name.is-leader {
  color: var(--gold);
  font-weight: 700;
}
.profile-club-row .pcr-name.is-me {
  color: var(--primary);
}
.profile-club-row .pcr-sep {
  color: var(--text-faint);
  opacity: 0.5;
  margin: 0 1px;
  flex-shrink: 0;
}
.profile-club-row .pcr-arrow {
  font-size: calc(12px * var(--text-scale));
  color: var(--text-faint);
  margin-left: 4px;
  flex-shrink: 0;
}
.profile-see-all-link {
  background: none;
  border: none;
  color: var(--text-faint);
  font-size: calc(12px * var(--text-scale));
  cursor: pointer;
  padding: 0;
  font-family: inherit;
}

/* ─── Pantsy-7 Final screen — awards / top3 / club totals ──────────────
   Replaces the old "Final standings" stack with three focused sections:
   1. p7-awards-card: SMARTY/HOUDINI/TRUTH titles with player + nickname + stat
   2. p7-top3-card: club's all-time top 3 (rank/avatar/name/YOU/pts)
   3. p7-club-card: simplified header (★+name+See all) + 4-stat strip */

.final-section-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
  padding: 0 4px;
}
.final-see-all {
  background: none;
  border: none;
  color: var(--text-faint);
  font-size: calc(11px * var(--text-scale));
  cursor: pointer;
  padding: 0;
  font-family: inherit;
}

/* Awards card — single bordered container with stacked rows */
.p7-awards-card {
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-btn);
  overflow: hidden;
}

/* 2026-05-11 (Stian): TOP RIVALS section on the end-of-game screen
   reuses `.p7-awards-card` as its container but its rows are plain
   text divs (`.final-grudge-row`) — no avatar/tag chrome like
   `.p7-award-row`. Pre-fix those rows had no CSS at all, so the text
   fell through to the screen's display font and rendered huge. This
   block gives them sensible row padding + body typography matching
   the broader `.final-*` rhythm. */
.final-grudge-tracker .p7-awards-card {
  padding: 4px 0;
}
.final-grudge-row {
  padding: 10px 14px;
  font-family: var(--font-body, inherit);
  font-size: calc(14px * var(--text-scale));
  font-weight: 500;
  line-height: 1.35;
  color: var(--text-on-deep);
  border-top: 1px solid rgba(255, 255, 255, 0.05);
}
.final-grudge-row:first-child {
  border-top: none;
}
.p7-award-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  min-width: 0;
}
.p7-award-row:first-child {
  border-top: none;
}
.p7-aw-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 7px;
  border-radius: 999px;
  border: 1px solid;
  font-family: var(--font-mono);
  font-size: calc(9px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.1em;
  line-height: 1;
  flex-shrink: 0;
  min-width: 70px;
  justify-content: center;
}
.p7-aw-glyph {
  font-size: calc(9px * var(--text-scale));
}
.p7-aw-avatar {
  width: 22px; height: 22px;
  border-radius: 999px;
  background: var(--primary);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: calc(10px * var(--text-scale));
  flex-shrink: 0;
}
.p7-aw-meta {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 6px;
  font-size: calc(13px * var(--text-scale));
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.p7-aw-name {
  font-weight: 700;
  color: var(--text-on-deep);
  letter-spacing: -0.005em;
  flex-shrink: 0;
}
.p7-aw-nick {
  /* D-152 (Pantsy-8 Batch 16): design uses italic SERIF font for award quote ("The
     Quip Sniper"), not the body sans-serif. Adding serif fallback (Georgia/serif)
     before var(--font-display) so the italic reads as a serif accent. */
  font-family: Georgia, "Times New Roman", serif;
  font-style: italic;
  font-weight: 500;
  color: var(--text-soft);
  font-size: calc(11.5px * var(--text-scale));
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
/* D-180 (Pantsy-8 user-decision): club memorable-moments section. Shown between stats
   and members on 13b Club detail when moments data exists. Soft cream pill rows with
   tier-color bullet markers. */
.club-moments-card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 6px 0;
}
.club-moment-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 14px;
  background: rgba(255, 255, 255, 0.04);
  border-radius: var(--radius-btn);
  border: 1px solid rgba(255, 255, 255, 0.06);
}
.club-moment-row .cmr-dot {
  flex: 0 0 auto;
  width: 6px;
  height: 6px;
  border-radius: 999px;
  margin-top: 7px;
}
.club-moment-row .cmr-text {
  font-size: calc(13px * var(--text-scale));
  line-height: 1.45;
  color: var(--text-on-deep);
}

/* D-150 (Pantsy-8 user-decision): locked / unearned award row. Greyed out so players
   see what's possible to earn next game without it competing with earned rows. */
.p7-award-row.p7-award-locked {
  opacity: 0.5;
}
.p7-aw-tag-locked {
  font-weight: 600 !important;
}
.p7-aw-avatar-locked {
  background: rgba(255, 244, 222, 0.06) !important;
  color: var(--text-faint) !important;
  font-weight: 700;
}
.p7-aw-locked-text {
  color: var(--text-faint) !important;
}
.p7-aw-stat {
  font-family: var(--font-mono);
  font-size: calc(9.5px * var(--text-scale));
  color: var(--text-faint);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  flex-shrink: 0;
}

/* Bølge 61 Phase 2 card refactor (2026-05-10): BADGES Phase B4 unified
   end-of-game card. SMARTY/HOUDINI/TRUTH (priority rows, existing layout
   with .p7-aw-tag/.p7-aw-avatar/.p7-aw-meta/.p7-aw-stat) sit at the top.
   Earned session-tier rows below them use the .p7-award-row-session
   variant — same .p7-award-row wrapper (shared border-top divider) but
   simpler internal flex (icon + stacked title/desc, no tag/avatar/stat).
   "+N more" / "Show less" button mounts at the bottom of the card when
   3+ session rows earned (cap-5 = 3 priority + 2 session visible). */
.p7-award-row.p7-award-row-session {
  /* Re-use shared .p7-award-row gap + padding + border-top from above so
     the visual rhythm of priority and session rows reads as one card. */
  align-items: center;
}
.p7-saw-icon {
  width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: calc(15px * var(--text-scale));
  flex-shrink: 0;
  line-height: 1;
}
.p7-saw-meta {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.p7-saw-title {
  font-weight: 700;
  color: var(--text-on-deep);
  letter-spacing: -0.005em;
  font-size: calc(13px * var(--text-scale));
  line-height: 1.25;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.p7-saw-desc {
  font-family: Georgia, "Times New Roman", serif;
  font-style: italic;
  font-weight: 500;
  color: var(--text-soft);
  font-size: calc(11.5px * var(--text-scale));
  line-height: 1.3;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.p7-saw-more-btn {
  width: 100%;
  background: transparent;
  border: none;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  color: var(--text-soft);
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.1em;
  padding: 10px 12px;
  cursor: pointer;
  text-transform: uppercase;
}
.p7-saw-more-btn:hover {
  background: rgba(255, 255, 255, 0.04);
}

/* Top 3 in club — compact 3-row leaderboard */
.p7-top3-card {
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-btn);
  overflow: hidden;
}
.p7-top3-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-top: 1px solid rgba(255, 255, 255, 0.05);
  min-width: 0;
}
.p7-top3-row:first-child {
  border-top: none;
}
.p7-top3-row.is-leader {
  background: rgba(255, 210, 74, 0.05);
}
.p7-t3-rank {
  width: 14px;
  font-family: var(--font-mono);
  font-size: calc(10.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--text-faint);
  text-align: right;
  flex-shrink: 0;
}
.p7-top3-row.is-leader .p7-t3-rank {
  color: var(--gold);
}
.p7-t3-avatar {
  width: 22px; height: 22px;
  border-radius: 999px;
  background: var(--primary);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: calc(10px * var(--text-scale));
  flex-shrink: 0;
}
.p7-t3-name {
  flex: 1;
  min-width: 0;
  font-weight: 600;
  font-size: calc(13px * var(--text-scale));
  color: var(--text-on-deep);
  display: flex;
  align-items: baseline;
  gap: 6px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.p7-t3-name-text {
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.p7-t3-you {
  font-family: var(--font-mono);
  font-size: calc(9px * var(--text-scale));
  color: var(--text-faint);
  font-weight: 600;
  letter-spacing: 0.06em;
  flex-shrink: 0;
}
.p7-t3-pts {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(15px * var(--text-scale));
  letter-spacing: -0.02em;
  color: var(--text-soft);
  flex-shrink: 0;
}
.p7-top3-row.is-leader .p7-t3-pts {
  color: var(--gold);
}

/* Simplified club totals card */
.p7-club-card {
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-btn);
  padding: 10px 12px 11px;
  position: relative;
  overflow: hidden;
}
.p7-cc-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 8px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  cursor: pointer;
}
.p7-cc-star {
  font-size: calc(12px * var(--text-scale));
  color: var(--gold);
  line-height: 1;
}
.p7-cc-name {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(13.5px * var(--text-scale));
  color: var(--text-on-deep);
  letter-spacing: -0.005em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  flex: 1;
  min-width: 0;
}
.p7-cc-link {
  font-size: calc(11px * var(--text-scale));
  color: var(--text-faint);
  font-family: var(--font-mono);
  letter-spacing: 0.02em;
  flex-shrink: 0;
}
.p7-cc-stats {
  margin-top: 8px;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}
.p7-cc-stat {
  text-align: center;
  padding: 2px;
  border-left: 1px solid rgba(255, 255, 255, 0.06);
}
.p7-cc-stat:first-child {
  border-left: none;
}
.p7-cc-num {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(18px * var(--text-scale));
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--text-on-deep);
}
.p7-cc-lbl {
  font-size: calc(9.5px * var(--text-scale));
  color: var(--text-faint);
  letter-spacing: 0.04em;
  margin-top: 3px;
  text-transform: lowercase;
}

/* Pantsy-7: Award tags on Club leaderboard rows — SMARTY (gold), HOUDINI (red),
   TRUTH (orange). Sits inline next to the name, doesn't wrap to a new row. */
.clr-award {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: calc(8.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.1em;
  padding: 1.5px 5px;
  margin-left: 6px;
  border: 1px solid;
  border-radius: 3px;
  line-height: 1;
  vertical-align: 1px;
  flex-shrink: 0;
}
.clr-award-smarty {
  color: var(--gold);
  background: rgba(255, 210, 74, 0.10);
  border-color: rgba(255, 210, 74, 0.34);
}
.clr-award-houdini {
  color: var(--pantsy-hi);
  background: rgba(255, 23, 68, 0.10);
  border-color: rgba(255, 23, 68, 0.34);
}
.clr-award-truth {
  color: var(--primary);
  background: rgba(255, 87, 34, 0.10);
  border-color: rgba(255, 87, 34, 0.34);
}

/* Pantsy-7: gold ★ prefix on Best clue title (typographic, not emoji) */
.best-clue-star {
  color: var(--gold);
  font-size: 0.9em;
  vertical-align: 1px;
}

/* ─── #36 Profile prefs row — link from profileSheet to semantic-prefs sheet ─── */
.profile-prefs-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 12px;
  margin-top: 10px;
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-btn);
  cursor: pointer;
  width: 100%;
  text-align: left;
  font-family: inherit;
  color: inherit;
}
.profile-prefs-row .ppr-icon {
  width: 32px;
  height: 32px;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.06);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: calc(18px * var(--text-scale));
  flex-shrink: 0;
}
.profile-prefs-row .ppr-meta {
  flex: 1;
  min-width: 0;
}
.profile-prefs-row .ppr-title {
  font-weight: 600;
  font-size: calc(13px * var(--text-scale));
  color: var(--text-on-deep);
  line-height: 1.2;
}
.profile-prefs-row .ppr-sub {
  font-size: calc(11px * var(--text-scale));
  color: var(--text-faint);
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* #54 (2026-05-05): emoji row replaces subtitle when user has selected prefs.
   Slightly larger so emojis read at a glance; same nowrap+ellipsis safety. */
.profile-prefs-row .ppr-emoji-row {
  font-size: calc(16px * var(--text-scale));
  letter-spacing: 0.04em;
  line-height: 1.2;
  margin-top: 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* B41.1 (2026-05-09): right-side chip preview inside the canonical
   .profile-panel-row chassis. Tastes-row carries valueChips (region /
   era / vibe) as a compact preview before the chevron. Reuses the
   existing .ppr-chip primitive so visual rhythm matches the legacy
   .profile-prefs-row chip row used elsewhere. */
.profile-panel-row .ppr-value-chips {
  display: flex;
  flex-wrap: nowrap;
  gap: 6px;
  align-items: center;
  margin-left: auto;
  overflow: hidden;
  max-width: 60%;
}
.profile-panel-row .ppr-value-chips .ppr-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 999px;
  font-size: calc(11px * var(--text-scale));
  font-weight: 600;
  color: var(--text-on-deep);
  white-space: nowrap;
  flex-shrink: 0;
  line-height: 1.2;
}
.profile-panel-row .ppr-value-chips .ppr-chip-icon {
  font-size: calc(12px * var(--text-scale));
  line-height: 1;
}
.profile-panel-row .ppr-value-chips .ppr-chip-label {
  font-family: var(--font-body);
  letter-spacing: -0.01em;
}

/* D (Bølge 1.8 / 2026-05-08): preview-chip row — supersedes ppr-emoji-row.
   Renders icon+label pills (matches the picker chip primitive in style) so the
   summary reads as actual content, not a ribbon of emoji. Single-row clip with
   horizontal scroll only as a fallback for very wide labels. */
.profile-prefs-row .ppr-chip-row {
  display: flex;
  flex-wrap: nowrap;
  gap: 6px;
  margin-top: 4px;
  overflow: hidden;
  align-items: center;
}
.profile-prefs-row .ppr-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 999px;
  font-size: calc(11px * var(--text-scale));
  font-weight: 600;
  color: var(--text-on-deep);
  white-space: nowrap;
  flex-shrink: 0;
  line-height: 1.2;
}
.profile-prefs-row .ppr-chip-icon {
  font-size: calc(12px * var(--text-scale));
  line-height: 1;
}
.profile-prefs-row .ppr-chip-label {
  font-family: var(--font-body);
  letter-spacing: -0.01em;
}
.profile-prefs-row .ppr-chip-more {
  font-family: var(--font-mono);
  font-size: calc(10.5px * var(--text-scale));
  color: var(--text-muted);
}
.profile-prefs-row .ppr-arrow {
  font-size: calc(12px * var(--text-scale));
  color: var(--text-faint);
  flex-shrink: 0;
}
/* #64 polish: chevron paired with subtitle-only inner content. */
.profile-prefs-row .ppr-chevron {
  font-size: calc(18px * var(--text-scale));
  color: var(--text-faint);
  flex-shrink: 0;
  line-height: 1;
  padding-left: 6px;
}

/* ─── #36 Semantic preferences — 3-section identity sheet (region/era/vibe) ─ */
.semantic-prefs-body {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 6px 0 16px;
}
.semantic-prefs-help {
  font-size: calc(13px * var(--text-scale));
  color: var(--text-soft);
  line-height: 1.4;
  margin-bottom: 4px;
}
.semantic-prefs-section {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.semantic-prefs-section-title {
  font-family: var(--font-mono);
  font-size: calc(10.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--text-faint);
  padding-left: 2px;
}
.semantic-prefs-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
}
@media (max-width: 380px) {
  .semantic-prefs-grid { grid-template-columns: 1fr; }
}
/* Profile entry-row variant without left icon (#36 locked direction) */
.profile-prefs-row.profile-prefs-row-no-icon {
  padding: 12px 14px;
}
.profile-prefs-row.profile-prefs-row-no-icon .ppr-meta {
  margin-left: 0;
}
.semantic-pref-chip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 12px;
  background: var(--surface-mid);
  border: 1.5px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-btn);
  font-family: inherit;
  color: var(--text-on-deep);
  font-size: calc(13px * var(--text-scale));
  text-align: left;
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, transform 80ms ease;
}
.semantic-pref-chip:hover {
  border-color: rgba(255, 255, 255, 0.18);
}
.semantic-pref-chip:active { transform: scale(0.98); }
.semantic-pref-chip.is-on {
  background: rgba(255, 87, 34, 0.12);
  border-color: var(--primary);
  color: var(--primary);
}
.semantic-pref-chip .spc-icon {
  font-size: calc(18px * var(--text-scale));
  flex-shrink: 0;
  line-height: 1;
}
.semantic-pref-chip .spc-label {
  flex: 1;
  font-weight: 600;
  line-height: 1.2;
}

/* ─── IDEA-006 Category-picker chip row + leftmost search ─────────────────── */
.cat-chip-row {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding: 4px 2px 6px;
  scrollbar-width: none;
}
.cat-chip-row::-webkit-scrollbar { display: none; }
.cat-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px;
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-pill);
  font-family: inherit;
  font-size: calc(12px * var(--text-scale));
  font-weight: 600;
  color: var(--text-soft);
  white-space: nowrap;
  cursor: pointer;
  flex-shrink: 0;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.cat-chip:hover { border-color: rgba(255, 255, 255, 0.18); }
.cat-chip:active { transform: scale(0.97); }
.cat-chip.is-on {
  background: rgba(255, 87, 34, 0.14);
  border-color: var(--primary);
  color: var(--primary);
}
.cat-chip-icon {
  font-size: calc(14px * var(--text-scale));
  line-height: 1;
}
.cat-chip-label {
  letter-spacing: 0.01em;
}
/* #45 reversal: search chip — emoji-only with dotted outline (matches the
   shuffle-button styling). Slightly squarer padding so the bubble centers a
   single icon without the asymmetric label padding. */
.cat-chip.cat-chip-search {
  padding: 7px 10px;
  border-style: dashed;
  border-color: rgba(255, 255, 255, 0.28);
  background: transparent;
}
.cat-chip.cat-chip-search:hover {
  border-color: rgba(255, 255, 255, 0.45);
}
.cat-chip.cat-chip-search.is-on {
  border-style: dashed;
  border-color: var(--primary);
  background: rgba(255, 87, 34, 0.10);
}
.cat-chip-search-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 2px 6px;
}
.cat-chip-search-input {
  flex: 1;
  min-width: 0;
  padding: 9px 14px;
  background: var(--surface-mid);
  border: 1px solid var(--primary);
  border-radius: var(--radius-pill);
  color: var(--text-on-deep);
  font-family: inherit;
  font-size: calc(14px * var(--text-scale));
  outline: none;
}
.cat-chip-search-input::placeholder {
  color: var(--text-faint);
  font-style: italic;
}
.cat-chip-search-clear {
  width: 28px;
  height: 28px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.08);
  color: var(--text-soft);
  font-size: calc(18px * var(--text-scale));
  line-height: 1;
  cursor: pointer;
  flex-shrink: 0;
}
.cat-chip-search-clear:hover { background: rgba(255, 255, 255, 0.14); }

/* ─── #33 Profile feedback (Tally iframe) — only renders when URL configured ── */
.profile-feedback-section {
  margin-top: 14px;
}
.profile-feedback-iframe {
  width: 100%;
  min-height: 360px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-btn);
  background: var(--surface-mid);
}

/* ─── A #69 cont. (Bølge 1.7 / 2026-05-07) — PWA standalone height ────────
   When pinned to iOS home screen, viewport = full screen (no URL bar to
   collapse), and safe-area paddings push content further. Hero + code-input
   were overflowing the viewport, clipping "How it works ↘" + part of the
   code field. Compress hero spacing + mascot in standalone mode only.
   `body.pwa-standalone` is set at boot via JS detection. */
body.pwa-standalone .hero {
  padding: 4px 16px 0;
}
body.pwa-standalone .hero-mascot {
  height: 130px;          /* 170 → 130, ~24% reduction */
  margin: 0 auto 4px;
}
body.pwa-standalone .hero h1 {
  margin-top: 0;
  margin-bottom: 6px;
}
body.pwa-standalone .home-tagline,
body.pwa-standalone .hero-tagline {
  margin-top: 4px;
}
/* Tighten gap between hero and code-input card on home. */
body.pwa-standalone .home-screen .lobby-code-card,
body.pwa-standalone .home-screen .code-input-card,
body.pwa-standalone .home-screen .home-code-card {
  margin-top: 8px;
}

/* ─── B #61 step 6 (2026-05-06) — Dirty Mode lobby banner ─────────────────
   Inherits .card.dark; warm-informative tone, NOT warning. Tap row → expand
   the 3-line explainer in-place. Subtle chili emoji for theme recognition. */
.dirty-lobby-banner {
  padding: 10px 14px;
}
.dirty-lobby-banner-row {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: none;
  border: none;
  color: var(--text-on-deep);
  cursor: pointer;
  font-family: inherit;
  font-size: calc(14px * var(--text-scale));
  font-weight: 600;
  text-align: left;
  padding: 0;
}
.dirty-lobby-banner .dlb-icon { font-size: calc(16px * var(--text-scale)); line-height: 1; }
.dirty-lobby-banner .dlb-label { flex: 1; min-width: 0; }
.dirty-lobby-banner .dlb-info-toggle {
  color: var(--text-faint);
  font-size: calc(14px * var(--text-scale));
  font-weight: 500;
  flex-shrink: 0;
}
.dirty-lobby-banner.is-expanded .dlb-info-toggle { color: var(--text-on-deep); }
.dirty-lobby-explainer {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.dirty-lobby-explainer p {
  margin: 0;
  font-size: calc(13px * var(--text-scale));
  color: var(--text-soft);
  line-height: 1.4;
}

/* ─── F3-C #42 + Bølge 1.6 → C (Bølge 1.7) → B (Bølge 1.8 / 2026-05-08) — Larger text ─
   Body class set by applyA11y(). Bølge 1.7 used `zoom: 1.12` which scaled
   EVERYTHING (text, hit targets, gaps, layout) — caused subtle layout breakage
   on iOS Safari (modal-sheet sticky bottoms drifted, lobby code-card hit-target
   misaligned with QR badge). Bølge 1.8 architectural fix: bump --text-scale
   token to 1.15. Hot-path font-sizes use calc(<px> * var(--text-scale)), so
   text scales while paddings/gaps/buttons stay pixel-stable. */
body.a11y-larger-text {
  --text-scale: 1.15;
}

/* Bølge 2.3 Item A (2026-05-06): .name-modal-a11y-section + -header dropped
   — section header was small (defeats the purpose of an a11y feature) and
   added an unnecessary third surface. Now: a single .a11y-toggle-row pill
   styled below. */

/* Bølge 2.3 Item A (2026-05-06): single tappable panel-with-inline-icon row
   replacing the older a11y section. Lives on a WHITE name-modal-card so
   colors must use ink, NOT cream. */
.a11y-toggle-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 18px;
  background: rgba(0, 0, 0, 0.04);
  border: 1px solid rgba(0, 0, 0, 0.10);
  border-radius: var(--radius-btn);
  cursor: pointer;
  width: 100%;
  font-family: inherit;
  text-align: left;
  transition: background .12s, border-color .12s;
}
.a11y-toggle-row:hover { background: rgba(0, 0, 0, 0.07); }
.a11y-toggle-row.on {
  background: rgba(255, 87, 34, 0.08);
  border-color: var(--primary);
}
.a11y-toggle-row .a11y-row-label {
  font-family: var(--font-display);
  font-size: calc(16px * var(--text-scale));
  font-weight: 700;
  color: var(--ink);
}
.a11y-toggle-row .a11y-row-icon {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: calc(28px * var(--text-scale));
  color: var(--ink);
  line-height: 1;
  letter-spacing: -0.04em;
}
/* Single big toggle. Lives on a WHITE name-modal-card → must use ink (deep
   aubergine), NOT cream. Earlier version flipped color to --text-on-deep on
   ON state, which is cream and disappeared on white. Both states now use --ink;
   ON state distinguishes via stronger primary border + tinted background. */
.a11y-big-toggle {
  background: rgba(255, 87, 34, 0.06);
  border: 1px solid rgba(0, 0, 0, 0.10);
  color: var(--ink) !important;
  border-radius: var(--radius-btn);
  padding: 14px 18px;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.01em;
  cursor: pointer;
  width: 100%;
  text-align: center;
  transition: background .18s ease, border-color .18s ease, color .18s ease, font-size 200ms ease-out;
}
.a11y-big-toggle:hover { background: rgba(255, 87, 34, 0.10); }
.a11y-big-toggle.on {
  border-color: var(--primary);
  background: rgba(255, 87, 34, 0.18);
  color: var(--ink) !important;
}
/* Item 15 (Bølge 1.9 / 2026-05-08): belt-and-suspenders !important on color
   for the a11y toggle. Bug report: toggle font color reads unreadable on
   white name-modal in the live build. The Bølge 1.8 fix (color: var(--ink))
   should already cover this — adding !important guarantees no other selector
   in the cascade can override it (defensive against any future regressions
   where a more-specific .name-modal-card * rule lands). If the bug persists
   post-deploy, the affected element is somewhere else (Aa icon, header, etc.)
   — see APPROVALS-QUEUE for follow-up. */
/* C (Bølge 1.7 / 2026-05-07): Aa icon — small A next to big A. Reads the same
   on every device (no emoji-font dependency). Inherits the button's display
   font so it visually belongs to the label. */
.a11y-icon-aa {
  display: inline-flex;
  align-items: baseline;
  font-family: var(--font-display);
  font-weight: 700;
  letter-spacing: -0.04em;
  margin-right: 4px;
}
.a11y-icon-aa .big {
  font-size: 1.6em;
  margin-left: -2px;
}
.name-modal-a11y-row {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: center;
}

/* Item 9 + 11 + 12 (Bølge 1.9 / 2026-05-08): vibe-vote redesigned.
   - Re-roll dropped → no more `.vibe-vote-reroll` / `.just-rolled` / vibe-roll animation
   - Eyebrow/title replaced by standard `.label` heading + `.vibe-vote-sub`
   - All 4 chips wrap to 2 rows on narrow viewports (flex-wrap: wrap)
   - No emojis on chips → `.vvc-icon` removed
   - Live category swap on leader change (server-side); chip is just a
     count-aware tappable label. */
.vibe-vote-card {
  display: flex;
  flex-direction: column;
  gap: 0;
}
/* Item F (Bølge 2.1 / 2026-05-08): vibe-vote header dropped — subtitle
   becomes the title. .vibe-vote-sub retired; .vibe-vote-title inherits
   the .label primitive (mono, uppercase, faint cream on dark) but with
   normal-case via text-transform override and tighter line-height. */
.vibe-vote-title {
  font-size: calc(13px * var(--text-scale));
  line-height: 1.3;
  text-transform: none;
  letter-spacing: 0;
}
.vibe-vote-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.vibe-vote-chip {
  flex: 1 1 0;
  min-width: 0;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 8px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-btn);
  color: var(--text-on-deep);
  font-family: var(--font-body);
  font-size: calc(13px * var(--text-scale));
  font-weight: 600;
  cursor: pointer;
  transition: transform .12s ease, background .12s ease, border-color .12s ease;
}
.vibe-vote-chip:hover { background: rgba(255, 255, 255, 0.07); }
.vibe-vote-chip:active { transform: scale(0.97); }
.vibe-vote-chip.is-mine {
  border-color: var(--primary);
  background: rgba(255, 87, 34, 0.10);
}
.vibe-vote-chip.is-winner {
  border-color: var(--gold);
  background: rgba(255, 210, 74, 0.12);
  box-shadow: 0 0 0 1px rgba(255, 210, 74, 0.30);
}
.vibe-vote-chip .vvc-label {
  font-size: calc(12px * var(--text-scale));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.vibe-vote-chip .vvc-count {
  position: absolute;
  top: 4px;
  right: 6px;
  font-size: calc(10px * var(--text-scale));
  font-weight: 700;
  color: var(--text-on-deep);
  background: rgba(0, 0, 0, 0.32);
  border-radius: 999px;
  padding: 0 5px;
  min-width: 14px;
  text-align: center;
}
/* Bølge 2.4 Item G (2026-05-06): Spicy vibe locked state. Visual cue that
   the chip is gated by the room's Spicy Mode toggle — dims the label and
   surfaces a 🔒 glyph in the count slot. Hover/active still respond so
   the modal explainer reads as the next step rather than "broken chip". */
.vibe-vote-chip.is-spicy-locked {
  opacity: 0.62;
  border-style: dashed;
}
.vibe-vote-chip.is-spicy-locked .vvc-label {
  color: var(--text-faint);
}
.vibe-vote-chip .vvc-lock {
  position: absolute;
  top: 4px;
  right: 6px;
  font-size: calc(10px * var(--text-scale));
  line-height: 1;
}

/* ═══════════════════════════════════════════════════════════════════════
   Bølge 2.0 (2026-05-08) — Floor Screen + Smart-Roast ticker + Peke-kaos +
   Role Reveal "shit-moment" upgrade.
   ═══════════════════════════════════════════════════════════════════════ */

/* Item A — Smart-Roast ticker. Rolling commentary strip. Sits below the
   floor card during clue-giving; subtle on overlay surfaces. */
.smart-roast-ticker {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  margin-top: 10px;
  background: rgba(255, 244, 222, 0.025);
  border: 1px solid rgba(255, 244, 222, 0.06);
  border-radius: 8px;
  font-family: var(--font-mono);
  font-size: calc(11.5px * var(--text-scale));
  color: var(--text-soft);
  letter-spacing: 0.02em;
  line-height: 1.4;
  min-height: 32px;
  overflow: hidden;
}
.smart-roast-ticker.is-subtle {
  background: transparent;
  border: none;
  padding: 6px 0;
}
.smart-roast-ticker .srt-icon {
  font-size: calc(14px * var(--text-scale));
  opacity: 0.5;
  flex-shrink: 0;
}
.smart-roast-ticker .srt-text {
  flex: 1;
  transition: opacity .2s ease, transform .2s ease;
}
.smart-roast-ticker .srt-text.fade-out { opacity: 0; transform: translateY(-2px); }
.smart-roast-ticker .srt-text.fade-in  { opacity: 1; transform: translateY(0); }

/* Item B — Floor Screen "all clues in" host-advance state. The discuss
   screen flips to this UI when clueRoundCurrent > settings.clueRounds. */
.floor-advance-btn {
  width: 100%;
  margin-top: 16px;
}
.floor-spectator-hint {
  text-align: center;
  font-size: calc(13px * var(--text-scale));
  color: var(--text-soft);
  margin-top: 16px;
}
.clue-screen.all-clues-in .clue-floor-card {
  /* Soft visual hint that we're past clue-giving — slight desaturation. */
  opacity: 0.85;
}

/* B97.6 (2026-05-11) — PointAtPantsy parity rebuild against design pack JSX
   `_audit/_pantsy9/07c.5-point-at-pantsy/screens-final-stand.jsx:842-940`.
   Live previously was a minimal placeholder; now matches accusation theatre.
   Topbar-hide rule retired — AppBar visible during pekeKaos per JSX 878.
   `.peke-kaos-screen` now flows normally inside #screen (was position:fixed
   in pre-B97.6 to claim viewport behind the hidden topbar). */
/* Specificity note: `.screen.intro` (line 403) sets `animation: slideIn .28s`
   with specificity 0-2-0; to win the cascade for the strobe animation, this
   rule is also declared at 0-2-0 specificity (`.screen.peke-kaos-screen`)
   and lives later in the stylesheet. */
.screen.peke-kaos-screen {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  justify-content: stretch;
  text-align: center;
  position: relative;
  /* Bølge 126 (2026-05-11): the screen-level background was the source
     of a double-bg seam against html's radial-gradient. The strobe now
     lives on body.peke-kaos-active::before as a full-viewport overlay
     (see rule below); the screen itself stays transparent so html shows
     through cleanly. Negative inset retained for layout parity with the
     legacy chassis (other content still needs the edge-to-edge frame). */
  margin: -8px -12px 0;
  padding: 8px 12px 0;
  background: transparent;
}
/* Bølge 126 — full-bleed strobe overlay (Decision #6). Sits at position:
   fixed; inset:0 so the blink covers the full viewport including topbar
   chrome, not just the .screen content area. Pointer-events:none so taps
   pass through to the rings + countdown. z-index sits below .pk-theatre
   (which is z:2) so the rings render on top. */
body.peke-kaos-active::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background: radial-gradient(ellipse at 50% 0%, #2A1038 0%, #1A0820 55%, #0F0418 100%);
  animation: pk-bg-strobe 1.1s ease-in-out infinite;
}
body.peke-kaos-active:has(.peke-kaos-screen.urgent)::before {
  animation: pk-bg-strobe-urgent 0.6s ease-in-out infinite;
}

/* ═══════════════════════════════════════════════════════════════════════
   Bølge 28 (2026-05-21) — profile + lobby polish CSS additions
   ═══════════════════════════════════════════════════════════════════════ */

/* N3: Spicy mode standalone panel. Single-row pill: title left, toggle
   right. Title uses club-name typography family (.pcr-club-name's
   13px / 600 / -0.005em letter-spacing) so it slots into the same
   visual hierarchy as Lifetime / Recovery / About-you headings. The
   row itself stays unobtrusive — no eyebrow above the panel; the
   title IS the heading. */
.profile-spicy-panel { padding: 12px 16px; }
.profile-spicy-panel .spicy-mode-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
}
.profile-spicy-panel .spicy-mode-title {
  font-weight: 600;
  font-size: calc(13px * var(--text-scale));
  letter-spacing: -0.005em;
  color: var(--text-on-deep);
}

/* N6: about-you subtitle uses club-name typography so the empty-state
   nudge reads as identity-tier copy rather than form-label voice. */
.aboutYouSubtitle {
  font-weight: 600;
  font-size: calc(13px * var(--text-scale));
  letter-spacing: -0.005em;
  color: var(--text-faint);
}

/* N4: Lifetime + Hosting merged 2x4 stat grid. Each cell is a button
   (tappable) showing the number + label; tap opens a brandConfirm
   explainer popup. Replaces the prior 1×4 .profile-stats-strip — the
   existing flex strip CSS handles 4 children but breaks visually with
   8. Grid layout gives consistent 4-wide rows + a hairline between
   rows. */
.profile-stats-grid-2x4 {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-card);
  padding: 4px 0;
}
.profile-stats-grid-2x4 .profile-stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 12px 6px;
  border-right: 1px solid rgba(255, 255, 255, 0.04);
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  background: transparent;
  cursor: pointer;
  font-family: inherit;
  text-align: center;
  /* Reset native button chrome so the cell looks like a div but stays
     keyboard-tappable. */
  -webkit-appearance: none;
  appearance: none;
  border-top: 0;
  border-left: 0;
}
.profile-stats-grid-2x4 .profile-stat:nth-child(4n) { border-right: 0; }
.profile-stats-grid-2x4 .profile-stat:nth-child(n+5) { border-bottom: 0; }
.profile-stats-grid-2x4 .profile-stat:hover { background: rgba(255, 255, 255, 0.03); }
.profile-stats-grid-2x4 .profile-stat:active { transform: scale(0.97); transition: transform 80ms ease-out; }
.profile-stats-grid-2x4 .profile-stat-tappable .profile-stat-num {
  font-size: calc(20px * var(--text-scale));
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--text-on-deep);
}
.profile-stats-grid-2x4 .profile-stat-tappable.hi .profile-stat-num { color: var(--gold, var(--primary)); }
.profile-stats-grid-2x4 .profile-stat-tappable .profile-stat-lbl {
  font-size: calc(10px * var(--text-scale));
  color: var(--text-faint);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

/* Bølge 129 (Wave OO, 2026-05-11): Vertskap section — re-introduced
   dedicated hosting surface (ROADMAP #86 Phase 2). Different visual
   rhythm from the 2x4 grid above (which is scoreboard-style): big
   numbers + poetic sentence-case labels stacked as rows, with a muted
   tree-reach line at the bottom. */
.profile-vertskap-section .profile-vertskap-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--surface-mid);
  border: 1px solid rgba(255, 255, 255, 0.06);
  border-radius: var(--radius-card);
  padding: 14px 16px;
}
.profile-vertskap-row {
  display: flex;
  align-items: baseline;
  gap: 10px;
}
.profile-vertskap-num {
  font-size: calc(22px * var(--text-scale));
  font-weight: 800;
  letter-spacing: -0.02em;
  color: var(--gold, var(--primary));
  min-width: 36px;
  text-align: right;
}
.profile-vertskap-lbl {
  font-size: calc(14px * var(--text-scale));
  color: var(--text-on-deep);
  line-height: 1.35;
}
.profile-vertskap-reach {
  margin-top: 10px;
  padding: 0 6px;
  font-size: calc(12px * var(--text-scale));
  color: var(--text-faint);
  text-align: center;
  font-style: italic;
  line-height: 1.4;
}

/* Bølge 131 (Wave OO Bundle PP, 2026-05-11): random-player-name CTAs.
   Two surfaces — rulesModal "Random name" inline pill + addLocalPlayerModal
   "Try another" pill rendered between the input and the action row. */
.rules-name-random-btn,
.input-modal-random-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 8px 0 0;
  padding: 6px 12px;
  background: var(--surface-mid);
  color: var(--text-on-deep);
  border: 1px solid rgba(255, 255, 255, 0.10);
  border-radius: 999px;
  font-size: calc(12px * var(--text-scale));
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background 100ms ease, transform 80ms ease-out;
}
.rules-name-random-btn:hover,
.input-modal-random-btn:hover { background: rgba(255, 255, 255, 0.06); }
.rules-name-random-btn:active,
.input-modal-random-btn:active { transform: scale(0.96); }
.input-modal-random-btn {
  align-self: flex-start;
  margin: 6px 0 4px;
}

/* N1: haptic toggle's "(mobile only)" disabled state. Visually muted but
   still reads as a control surface so users see haptics exists. */
.gs-toggle-row.is-unsupported {
  cursor: not-allowed;
  opacity: 0.55;
}
.gs-toggle-row.is-unsupported .gs-toggle-switch {
  opacity: 0.6;
}

/* N8: Achievements collapsed-strip — 5 tiles, larger size to fill the
   row width. Each tile is a column: glyph on top, optional progress
   bar + "C / T" text below for next-up tiles. */
.profile-achievements-panel .achievements-row {
  display: flex;
  align-items: stretch;
  justify-content: space-between;
  gap: 8px;
  flex-wrap: nowrap;
  overflow: hidden;
}
.profile-achievements-panel .achievement-icon {
  /* 5 tiles across, 8px gaps (4 of them = 32px) — each tile gets
     ((100% - 32px) / 5). Min-width 0 lets them shrink on the
     iPhone-narrow (320px) viewport without overflowing. */
  flex: 1 1 calc((100% - 32px) / 5);
  min-width: 0;
  width: auto;
  height: auto;
  padding: 12px 6px 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 6px;
  border-radius: 12px;
  background: rgba(255, 210, 74, 0.10);
  border: 1px solid rgba(255, 210, 74, 0.30);
}
.profile-achievements-panel .achievement-icon .ach-tile-glyph {
  font-size: calc(28px * var(--text-scale));
  line-height: 1;
}
.profile-achievements-panel .achievement-icon-pending {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.10);
  opacity: 1;
}
.profile-achievements-panel .achievement-icon-pending .ach-tile-glyph { opacity: 0.55; }
.ach-tile-progress {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  width: 100%;
}
.ach-tile-progress-track {
  width: 100%;
  height: 4px;
  background: rgba(255, 255, 255, 0.08);
  border-radius: 2px;
  overflow: hidden;
}
.ach-tile-progress-fill {
  height: 100%;
  background: var(--gold, var(--primary));
  border-radius: 2px;
  transition: width 0.18s ease-out;
}
.ach-tile-progress-text {
  font-family: var(--font-mono);
  font-size: calc(9px * var(--text-scale));
  letter-spacing: 0.04em;
  color: var(--text-faint);
  line-height: 1;
}

/* N10: Round + Game-summary CTA stacks. Primary on top, footer-links
   row below. Mirrors the lobby footer rhythm. */
.result-bottom-actions-stack,
.final-bottom-actions-stack {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.result-bottom-footer-links {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
}
.result-bottom-footer-links .result-bottom-footer-sep {
  color: var(--text-faint);
  opacity: 0.5;
}

/* B97.6 (2026-05-11) — accusation theatre chassis. Replaces the legacy
   .peke-kaos-eyebrow + .peke-kaos-countdown + .peke-kaos-instruction
   typography rules that rendered the pre-B97.6 placeholder.

   .pk-theatre — flex column centering the rings frame + command text.
     The theatre shakes when .peke-kaos-screen has the .urgent modifier
     (JSX 851-857, 885).
   .pk-alarm-rings-frame — 320×320 positioning context for 4 rings + the
     centered countdown number (JSX 894-911).
   .pk-alarm-ring — single ring; per-instance --pk-ring-dur + --pk-ring-delay
     drive the staggered pulse via the pk-alarm-ring keyframe.
   .pk-countdown — 220px Fraunces tabular-nums cream number with the
     pk-tick-burst cinema-glow keyframe (JSX 913-925).
   .pk-command — 2-line "Point at / the Pantsy" Fraunces command (JSX 929-933).
*/
/* 2026-05-11 (Stian round 5): `.pk-theatre` rules retained for legacy
   matching only — the wrapper is no longer rendered. Rings-frame and
   command are direct children of `.peke-kaos-screen`. The previous
   `.peke-kaos-screen.urgent .pk-theatre { animation: pk-shake }`
   created a transform-induced containing block on `.pk-theatre`
   during urgent ticks, which trapped the rings-frame's
   `position: fixed` and pulled the countdown off viewport center.
   Shake is now applied per-fixed-element below with composed
   transforms that preserve each element's centering. */
.pk-theatre { display: contents; }
.pk-alarm-rings-frame {
  /* 2026-05-11 (Stian round 3): pinned to viewport center via
     `position: fixed` so the countdown digit (and the rings emanating
     from it) lands at the exact vertical center of the screen.
     Previously the frame sat in `.pk-theatre`'s flex column alongside
     `.pk-command`, which flex-centered the GROUP — putting the rings
     in the upper half of the theatre, ~40px above viewport center.
     The command's position is also pinned (rule below) so it doesn't
     re-stack onto the rings the way it did the first time around. */
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 320px;
  height: 320px;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Above the body::before strobe overlay; below the topbar's z-index. */
  z-index: 2;
  pointer-events: none;
}
.pk-alarm-ring {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 280px;
  height: 280px;
  margin-left: -140px;
  margin-top: -140px;
  border-radius: 999px;
  border: 2px solid var(--fire, #FF5722);
  box-shadow: 0 0 24px rgba(255, 87, 34, 0.4);
  /* Per-ring stagger via inline-style --pk-ring-delay; duration via
     --pk-ring-dur (1.6s normal / 1.0s urgent). */
  animation: pk-alarm-ring var(--pk-ring-dur, 1.6s) ease-out var(--pk-ring-delay, 0s) infinite;
  opacity: 0;
  z-index: 2;
}
.peke-kaos-screen.urgent .pk-alarm-ring {
  border-color: var(--pantsy-red, #FF1744);
  box-shadow: 0 0 24px rgba(255, 23, 68, 0.4);
}
.pk-countdown {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(220px * var(--text-scale));
  /* 2026-05-11 (Stian round 5): bounding box now matches the digit's
     own metrics so `translate(-50%, -50%)` centers the visible ink.
     - `line-height: 1` (was 0.85) — line box matches em-square so the
       vertical center of the box equals the vertical center of the glyph.
     - `tabular-nums` removed — Fraunces' tabular slot is sized for "8"
       and right-justifies the "1" within it, which made the digit lean
       right of bounding-box center. Proportional spacing lets each
       digit center on its own ink. Trade-off: tiny horizontal shift
       between countdown ticks (5→4→3→2→1) since each digit has its
       own natural width. That's preferred over the asymmetric lean. */
  line-height: 1;
  color: var(--cream, #FFF4DE);
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  animation: pk-tick-burst 1s ease-out;
  text-shadow: 0 0 22px rgba(255, 87, 34, 0.6), 0 0 56px rgba(255, 23, 68, 0.47);
}
.pk-command {
  /* 2026-05-11 (Stian round 3): position: fixed below the rings-frame
     so it can't re-stack onto the rings now that the frame is itself
     fixed at viewport center. `calc(50% + 168px)` = viewport-center
     + half-frame-height (160px) + design-pack gap (8px). Width 100%
     with text-align: center so the two-line "Point at / the Pantsy"
     centers on the same vertical axis as the countdown. */
  position: fixed;
  top: calc(50% + 168px);
  left: 0;
  right: 0;
  text-align: center;
  z-index: 3;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(34px * var(--text-scale));
  letter-spacing: -0.025em;
  line-height: 1.05;
  color: var(--cream, #FFF4DE);
  pointer-events: none;
}
.pk-command-line {
  display: block;
}
.pk-bottom-spacer {
  padding: 14px 20px 22px;
}

/* Keyframes — JSX 850-876, 887-892. */
@keyframes pk-bg-strobe {
  0%, 100% { background: radial-gradient(ellipse at 50% 0%, #2A1038 0%, #1A0820 55%, #0F0418 100%); }
  50%      { background: radial-gradient(ellipse at 50% 30%, #3A1648 0%, #221034 55%, #120620 100%); }
}
@keyframes pk-bg-strobe-urgent {
  0%, 100% { background: radial-gradient(ellipse at 50% 0%, #2A1038 0%, #1A0820 55%, #0F0418 100%); }
  50%      { background: radial-gradient(ellipse at 50% 30%, #4A2058 0%, #2A1240 55%, #14062A 100%); }
}
@keyframes pk-alarm-ring {
  0%   { transform: scale(0.7); opacity: 0; border-width: 3px; }
  12%  { opacity: 0.9; }
  100% { transform: scale(1.55); opacity: 0; border-width: 1px; }
}
@keyframes pk-tick-burst {
  /* 2026-05-11 (Stian): translate(-50%, -50%) preserved across the
     scale so the countdown's center stays pinned to the rings center
     for the full animation. Pre-fix the keyframe overrode the
     translate, snapping the digit to the frame's top-left during the
     burst. */
  0%   { transform: translate(-50%, -50%) scale(1.32); text-shadow: 0 0 0 var(--fire, #FF5722), 0 0 0 var(--pantsy-red, #FF1744); }
  15%  { transform: translate(-50%, -50%) scale(1.32); text-shadow: 0 0 32px rgba(255, 87, 34, 0.8), 0 0 72px rgba(255, 23, 68, 0.67); }
  100% { transform: translate(-50%, -50%) scale(1);    text-shadow: 0 0 18px rgba(255, 87, 34, 0.47), 0 0 44px rgba(255, 23, 68, 0.33); }
}
@keyframes pk-shake {
  0%, 100% { transform: translate(0, 0); }
  20%      { transform: translate(-2px, 1px); }
  40%      { transform: translate(2px, -1px); }
  60%      { transform: translate(-1px, 2px); }
  80%      { transform: translate(1px, -2px); }
}
/* 2026-05-11 (Stian round 5): shake variant that preserves the
   rings-frame's `translate(-50%, -50%)` centering. Applied directly to
   `.pk-alarm-rings-frame` on urgent ticks instead of `.pk-theatre`
   (which used to wrap it), so the rings-frame's `position: fixed`
   isn't trapped by a transformed ancestor. */
@keyframes pk-shake-centered {
  0%, 100% { transform: translate(-50%, -50%); }
  20%      { transform: translate(calc(-50% - 2px), calc(-50% + 1px)); }
  40%      { transform: translate(calc(-50% + 2px), calc(-50% - 1px)); }
  60%      { transform: translate(calc(-50% - 1px), calc(-50% + 2px)); }
  80%      { transform: translate(calc(-50% + 1px), calc(-50% - 2px)); }
}
.peke-kaos-screen.urgent .pk-alarm-rings-frame {
  animation: pk-shake-centered 0.18s steps(2) infinite;
}
.peke-kaos-screen.urgent .pk-command {
  animation: pk-shake 0.18s steps(2) infinite;
}
@media (prefers-reduced-motion: reduce) {
  .peke-kaos-screen,
  .peke-kaos-screen.urgent,
  .pk-alarm-ring,
  .pk-countdown,
  .peke-kaos-screen.urgent .pk-alarm-rings-frame,
  .peke-kaos-screen.urgent .pk-command {
    animation: none !important;
  }
  .pk-alarm-ring { opacity: 0.4; }
}

/* Item A (Bølge 2.1 / 2026-05-08): rolled back. The 3-beat cascade
   (.reveal-stage + .reveal-tagline / .reveal-keyword / .reveal-word-frame /
   keyframes revealStamp / revealFadeUp / @media reduced-motion overrides)
   was removed in favor of the pre-Bølge-2.0 .reveal-card.pantsy / .smarty
   primitives that already exist higher up in this file. The simpler card
   read better in playtest. */

/* ═══════════════════════════════════════════════════════════════════════
   Bølge 2.1 (2026-05-08) — Final Stand 2-stage phase.
   Stage 1 (.final-stand-screen): Pantsy types guess in a hot-orange card
   on a deep aubergine bg. Spectator variant flips card to dark.
   Stage 2 (.final-stand-judge-screen): guess + actual word + Mercy/Execution
   verdict buttons. Pantsy sees a watching hint instead of the buttons.
   Both screens share .fs-timer-bar (server-anchored countdown).
   ═══════════════════════════════════════════════════════════════════════ */
.final-stand-screen {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  padding: calc(env(safe-area-inset-top, 0) + 24px) 16px max(20px, env(safe-area-inset-bottom));
  background: linear-gradient(180deg, #1a0e1f 0%, #0a0410 100%);
}
.final-stand-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.20em;
  color: var(--text-faint);
  text-transform: uppercase;
  text-align: center;
  margin: 24px 0 16px;
}
.final-stand-card {
  flex: 1;
  background: linear-gradient(145deg, rgba(255, 87, 34, 0.95) 0%, rgba(216, 30, 22, 0.95) 100%);
  border-radius: 24px;
  padding: 24px 22px 28px;
  display: flex;
  flex-direction: column;
  color: var(--text-on-deep);
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.4);
}
.final-stand-card.spectator-card {
  background: linear-gradient(145deg, #2a1838 0%, #1a0e1f 100%);
}
.fs-card-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.16em;
  color: rgba(255, 244, 222, 0.8);
  text-transform: uppercase;
  margin-bottom: 32px;
}
.fs-card-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.fs-instruction {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(20px * var(--text-scale));
  margin-bottom: 24px;
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.fs-guess-input {
  background: rgba(0, 0, 0, 0.18);
  border: 1.5px solid rgba(255, 244, 222, 0.32);
  border-radius: 12px;
  padding: 18px 16px;
  font-family: var(--font-display);
  font-size: calc(22px * var(--text-scale));
  font-weight: 700;
  color: var(--text-on-deep);
  outline: none;
  width: 100%;
  margin-bottom: 14px;
  box-sizing: border-box;
}
.fs-guess-input::placeholder { color: rgba(255, 244, 222, 0.45); font-weight: 500; }
.fs-guess-input:focus { border-color: var(--text-on-deep); }
.fs-submit-btn { width: 100%; }
.fs-spectator-name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: calc(36px * var(--text-scale));
  text-align: center;
  margin-bottom: 8px;
}
.fs-spectator-sub {
  text-align: center;
  font-size: calc(13px * var(--text-scale));
  color: var(--text-soft);
  font-style: italic;
}
.fs-timer-bar {
  position: relative;
  height: 8px;
  background: rgba(255, 244, 222, 0.10);
  border-radius: 4px;
  margin: 16px 0 8px;
  overflow: visible;
}
.fs-timer-fill {
  height: 100%;
  background: var(--primary);
  border-radius: 4px;
  transition: width 0.2s linear;
}
.fs-timer-text {
  position: absolute;
  right: 0;
  top: 12px;
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  color: var(--text-faint);
}

/* Bølge 9 (2026-05-07) — pantsySpeaks beat. Sits between vote-tally and
   the verdict pass. The word is intentionally not rendered here — anti-peek.
   2026-05-11 (Stian round 3): standalone `min-height` + `padding` + `background`
   gradient removed. Since the post-B9 migration the render uses the
   `.discuss-screen.pantsy-speaks-screen` chassis with `.floor-big-card`
   inside — `.discuss-screen` now owns the layout (padding: 0, min-height:
   calc(100dvh - 80px)), and the card itself paints its own dark gradient
   bg. The leftover `linear-gradient` here was visible behind the card
   (and bled out around its edges where it didn't reach), producing the
   "double background" effect. Removing the duplicate lets `.app`'s html
   radial-gradient show through cleanly. */
.pantsy-speaks-screen {
  /* No-op — all rules now inherited from `.discuss-screen`. Selector
     retained so future pantsy-speaks-specific overrides have a hook. */
}
.ps-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.18em;
  color: var(--smarty);
  text-align: center;
  margin-bottom: 12px;
}
.ps-card {
  margin-top: 16px;
  padding: 28px 22px;
  text-align: center;
}
.ps-title {
  font-size: calc(22px * var(--text-scale));
  font-weight: 700;
  line-height: 1.3;
  color: var(--card-fg);
  margin-bottom: 14px;
}
.ps-body {
  font-size: calc(15px * var(--text-scale));
  line-height: 1.45;
  color: var(--text-soft);
}
.ps-cta {
  margin-top: auto;
  margin-bottom: 8px;
}
.ps-spectator-hint {
  margin-top: auto;
  text-align: center;
  font-size: calc(13px * var(--text-scale));
  color: var(--text-muted);
  padding: 10px 18px;
}

/* Stage 2 — Verdict screen.
   B45.2 (2026-05-09) D-010 redesign: aligned to ScreenResult chassis
   pattern from _audit/_pantsy8/screens-2.jsx:226–312. The verdict screen
   now uses the same surface-grad chassis + pantsyRed border tint as the
   round-result screen, with the action beat (Mercy/Execution buttons)
   sitting BELOW the chassis as a separate row — not inside it. Pre-B45.2
   crammed buttons inside the chassis card, which read off-brand. */
.final-stand-judge-screen {
  /* 2026-05-11 (Stian round 6): `min-height: calc(100dvh - 80px)` removed.
     It was added in round 2 to give the cream card a tall flex-grow target
     when the CTA was `position: fixed` at the viewport bottom. With the
     CTA back in normal flow (round 4), the min-height is unnecessary AND
     actively pushes the FSJ screen taller than `#screen`'s real content
     area — `.app` reserves ~150px of chrome (safe-area-top + 16px + topbar
     + safe-area-bottom) and the 80px subtraction only accounts for ~half
     of that. Net result: FSJ overflowed below `.app`'s content area and
     the CTA row landed off-screen. `.screen { flex: 1 }` (base rule) is
     sufficient to size the screen against `#screen`, same way
     pass-the-phone does it. */
  display: flex;
  flex-direction: column;
  /* 2026-05-11 (Stian round 3): padding dropped to 0, matching the
     pass-the-phone pattern. `.app` already provides safe-area-aware
     viewport padding; adding more `calc(env(safe-area-inset-top) + 24px)`
     etc. on this screen double-counted the safe-area, pushing the FSJ
     cream card 50-70px deeper from the topbar than pass-to-Nn. */
  padding: 0;
  /* Bølge 126 (2026-05-11, Decision #7): screen-level linear-gradient
     removed — duplicated the html radial-gradient (style.css:241-244).
     Transparent here lets the canonical html bg show through. The
     cream-card chassis inside retains its own bg (intentional, drives
     the design's two-tone contrast). */
  background: transparent;
  gap: 16px;
}

/* Chassis card. Mirrors ScreenResult inline style at screens-2.jsx:226–232
   (linear-gradient(135deg, surface 0%, surfaceLo 100%) + pantsyRed border
   at ~27% alpha + radiusCard 28). */
.fsj-card {
  background: linear-gradient(135deg, var(--surface-mid) 0%, var(--surface-lo, #1a0e1f) 100%);
  border: 1px solid rgba(220, 38, 38, 0.27); /* pantsyRed @ 27% */
  border-radius: var(--radius-card, 28px);
  padding: 28px 24px;
  margin-top: 8px;
  position: relative;
  overflow: hidden;
  /* Bølge 69 P1 (2026-05-10): chassis extends to CTA — flex-grow within
     the .final-stand-judge-screen flex-column so the card fills the
     gap between the header band and the button row instead of leaving
     empty middle space. Inner content stack centers vertically within
     the now-tall card via justify-content. Mirrors the .floor-big-card
     pattern from Starter/Discuss/PantsySpeaks (which already shipped
     this layout — `flex: 1 1 auto` + `justify-content: center`). */
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
/* Optional radial fire glow — top-right positioned. Same ambience as
   ScreenResult's caught-flame (screens-2.jsx:234–238). */
.fsj-card .fsj-glow {
  position: absolute;
  top: -60px; right: -60px;
  width: 240px; height: 240px;
  border-radius: 999px;
  background: radial-gradient(circle, rgba(220, 38, 38, 0.40) 0%, rgba(255, 87, 34, 0.15) 35%, transparent 70%);
  pointer-events: none;
}
.fsj-card .fsj-eyebrow {
  position: relative;
  color: var(--pantsy-red-hi, #f87171);
  font-family: var(--font-sans, var(--font-mono));
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 600;
  margin: 0 0 6px;
}
.fsj-card .fsj-headline {
  position: relative;
  font-family: var(--font-display);
  font-weight: 700;
  /* D-020 lesson: clamp scales the headline down before forcing a wrap
     on iPhone-narrow viewports with long names like "RoundHandover". */
  font-size: calc(clamp(28px, 9vw, 48px) * var(--text-scale));
  letter-spacing: -0.04em;
  line-height: 0.95;
  color: var(--text-on-deep);
  margin: 0 0 4px;
  text-wrap: balance;
  overflow-wrap: anywhere;
}
.fsj-card .fsj-actual-eyebrow {
  position: relative;
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  letter-spacing: 0.16em;
  color: var(--text-faint);
  text-transform: uppercase;
  margin: 16px 0 6px;
}
.fsj-card .fsj-actual-word {
  position: relative;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: calc(28px * var(--text-scale));
  color: var(--gold);
  letter-spacing: -0.02em;
  line-height: 1.1;
  word-break: break-word;
}

/* Mercy + Execution: Btn primitive extensions, NOT custom button shapes.
   Mercy = ghost (transparent + border, gold-tinted hover), Execution =
   pantsyRed gradient. Sit BELOW the chassis in a flex row. */
.fsj-button-row {
  display: flex;
  gap: 10px;
  margin-top: 4px;
}
.fsj-button-row .btn {
  flex: 1;
  min-height: 56px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(17px * var(--text-scale));
  letter-spacing: -0.01em;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  position: relative;
  transition: transform .12s, background .12s, border-color .12s, box-shadow .12s;
}
.fsj-button-row .btn:active { transform: scale(0.97); }
/* Mercy — ghost variant, gold-tinted text + border so the choice feels
   merciful (gold is the Smartypants/grace tone). Inherits .btn-ghost
   transparent bg. */
.btn.fsj-mercy {
  color: var(--gold);
  border-color: rgba(255, 210, 74, 0.35);
}
.btn.fsj-mercy:hover {
  background: rgba(255, 210, 74, 0.08);
  border-color: rgba(255, 210, 74, 0.55);
}
.btn.fsj-mercy.is-mine {
  background: rgba(255, 210, 74, 0.18);
  border-color: var(--gold);
  color: var(--gold);
}
/* Execution — pantsyRed gradient. Override the default .btn-primary look
   without claiming btn-primary class (avoids semantic conflict with the
   primary-CTA pattern elsewhere on the screen). */
.btn.fsj-execution {
  background: linear-gradient(135deg, var(--pantsy-red, #FF1744) 0%, var(--pantsy-red-hi, #FF3D6B) 100%);
  color: #fff;
  border: none;
  box-shadow: 0 4px 14px rgba(220, 38, 38, 0.30);
}
.btn.fsj-execution:hover {
  box-shadow: 0 6px 18px rgba(220, 38, 38, 0.42);
}
.btn.fsj-execution.is-mine {
  box-shadow: 0 0 0 2px rgba(255, 244, 222, 0.18), 0 6px 18px rgba(220, 38, 38, 0.42);
}

/* Tally badge — inline with the button label. */
.fsj-vote-count {
  background: rgba(0, 0, 0, 0.25);
  border-radius: 10px;
  padding: 2px 8px;
  font-size: 0.72em;
  font-family: var(--font-mono);
  font-weight: 700;
}

.fsj-spectator-hint {
  text-align: center;
  margin-top: 4px;
  font-style: italic;
  color: var(--text-soft);
  font-size: calc(14px * var(--text-scale));
  padding: 18px 8px;
}

/* ────────────────────────────────────────────────────────────────────
   Bølge 67 (2026-05-10): Final Stand reskin — 4 frames per Pantsy9
   design pack `_audit/_pantsy9/07f-final-stand-verdict/`.

   - Frame 1A (Pantsy guess) — `.fs-pantsy-*` mic chassis + pulse anims.
     The hidden text input behind the mic glyph preserves accessibility
     (Decision 2 — keep current text input, no Web Speech API).
   - Frame 1B (Group waiting) — `.fs-group-*` avatar spotlight + listen
     card + waveform. Same 20s timer eyebrow.
   - Frame 2 (Verdict) — `.btn.fsj-mercy` upgraded from ghost to filled
     smartyGold gradient + ink fg + gold shadow per design pack
     `.fs-verdict-btn.mercy` shape. `.btn.fsj-execution` already had
     the right pantsyRed gradient from a prior sprint — kept as-is.
   - Result — `.result-stamp.escaped` / `.caught` animation upgraded
     to design-pack `fs-r-stamp-slam` keyframe (scale 2.6→0.86→1.04→1
     + blur-in + ease-out-back, ~600ms). Old `pantsy-stamp-thump`
     keyframes preserved for `prefers-reduced-motion: reduce` fallback.

   :root tokens reused from B64 (--pantsy / --pantsy-hi / --gold /
   --fire / --cream / --ink / --text-on-deep / etc.). No new tokens.
   ──────────────────────────────────────────────────────────────────── */

@keyframes fs-pantsy-mic-pulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.05); }
}
@keyframes fs-pantsy-mic-ring {
  0%   { transform: scale(1); opacity: 0.7; }
  100% { transform: scale(1.6); opacity: 0; }
}
@keyframes fs-pantsy-wave {
  0%, 100% { transform: scaleY(0.4); }
  50%      { transform: scaleY(1); }
}
@keyframes fs-pantsy-pulse-glow {
  0%, 100% { opacity: 0.4; transform: scale(1); }
  50%      { opacity: 0.85; transform: scale(1.08); }
}

/* Frame 1A — Pantsy guess. Mic chassis sits above the existing
   `.fs-guess-input` so the input is functionally present (Tab + Enter
   submit work) but visually the mic is the stage. */
.fs-pantsy-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-faint);
  text-align: center;
  padding: 8px 20px 4px;
}
.fs-pantsy-eyebrow.urgent {
  color: var(--pantsy-hi, #FF3D6B);
}
.fs-pantsy-mic-block {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  padding: 18px 0 22px;
}
.fs-pantsy-mic-halo {
  position: absolute;
  top: -4px;
  left: 50%;
  width: 160px;
  height: 160px;
  margin-left: -80px;
  background: radial-gradient(circle, rgba(255, 87, 34, 0.20) 0%, transparent 65%);
  animation: fs-pantsy-pulse-glow 2.4s ease-in-out infinite;
  pointer-events: none;
  z-index: 0;
}
.fs-pantsy-mic-disc {
  position: relative;
  width: 86px;
  height: 86px;
  border-radius: 999px;
  background: linear-gradient(160deg, var(--fire, #FF5722) 0%, var(--fire-dim, #D33E14) 100%);
  border: 3px solid var(--cream, #FFF4DE);
  display: flex;
  align-items: center;
  justify-content: center;
  animation: fs-pantsy-mic-pulse 1.2s ease-in-out infinite;
  box-shadow: 0 6px 20px rgba(255, 87, 34, 0.4);
  z-index: 1;
}
.fs-pantsy-mic-ring {
  position: absolute;
  inset: -3px;
  border-radius: 999px;
  border: 2px solid var(--fire, #FF5722);
  animation: fs-pantsy-mic-ring 1.4s ease-out infinite;
  pointer-events: none;
}
.fs-pantsy-mic-glyph {
  width: 40px;
  height: 40px;
  color: #fff;
  display: block;
}
.fs-pantsy-wave-row {
  display: flex;
  align-items: center;
  gap: 4px;
  height: 30px;
  z-index: 1;
}
.fs-pantsy-wave-bar {
  width: 4px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--gold, #FFD24A) 0%, var(--fire, #FF5722) 100%);
  transform-origin: center;
  opacity: 0.92;
  animation: fs-pantsy-wave 0.6s ease-in-out infinite;
}
/* Hide-but-keep-accessible: the text input behind the mic glyph stays
   functional (Tab into it, type a guess, Enter submits) but is
   visually tucked into a small line at the bottom of the card so the
   mic owns the visual stage. */
.fs-pantsy-screen .fs-guess-input {
  margin-top: 10px;
  text-align: center;
  font-size: calc(15px * var(--text-scale));
  background: rgba(255, 244, 222, 0.04);
}
.fs-pantsy-screen .fs-guess-input:focus {
  background: rgba(255, 244, 222, 0.08);
}

/* Frame 1B — Group waiting. Avatar spotlight + listen card + waveform.
   The existing `.final-stand-spectator-screen` chassis stays put;
   these add atop. */
@keyframes fs-grp-spot {
  0%, 100% { transform: translate(-50%, 0) scale(1); opacity: 0.6; }
  50%      { transform: translate(-50%, 0) scale(1.08); opacity: 0.85; }
}
@keyframes fs-grp-pulse-avatar {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 87, 34, 0.5), 0 0 0 0 rgba(255, 87, 34, 0); }
  50%      { box-shadow: 0 0 0 6px rgba(255, 87, 34, 0), 0 0 24px rgba(255, 87, 34, 0.6); }
}
@keyframes fs-grp-letter-flicker {
  0%, 92%, 100% { opacity: 1; }
  93%, 96%      { opacity: 0.4; }
}
.fs-group-spotlight {
  position: absolute;
  top: -40px;
  left: 50%;
  width: 320px;
  height: 320px;
  margin-left: -160px;
  pointer-events: none;
  background: radial-gradient(ellipse 50% 50% at 50% 50%, rgba(255, 87, 34, 0.20) 0%, rgba(255, 87, 34, 0.07) 30%, transparent 65%);
  animation: fs-grp-spot 2.4s ease-in-out infinite;
  z-index: 0;
}
.fs-group-avatar {
  position: relative;
  z-index: 1;
  margin-top: 10px;
  padding: 6px;
  border-radius: 999px;
  animation: fs-grp-pulse-avatar 1.6s ease-in-out infinite;
  align-self: center;
}
.fs-group-avatar-disc {
  width: 96px;
  height: 96px;
  border-radius: 999px;
  background: var(--fire, #FF5722);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(38px * var(--text-scale));
  color: #fff;
  border: 3px solid var(--cream, #FFF4DE);
  letter-spacing: -0.02em;
}
.fs-group-name {
  margin-top: 18px;
  position: relative;
  z-index: 1;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(36px * var(--text-scale));
  letter-spacing: -0.03em;
  color: var(--text-on-deep, #FFF4DE);
  line-height: 1;
  text-align: center;
}
.fs-group-caption {
  margin-top: 10px;
  position: relative;
  z-index: 1;
  font-family: var(--font-body);
  font-size: calc(15px * var(--text-scale));
  color: var(--text-muted, rgba(255, 244, 222, 0.7));
  letter-spacing: -0.005em;
  text-align: center;
  padding: 0 24px;
}
.fs-group-caption .flicker-dot {
  display: inline-block;
  animation: fs-grp-letter-flicker 1.6s ease-in-out infinite;
}
.fs-group-caption .flicker-dot:nth-child(1) { animation-delay: 0s; }
.fs-group-caption .flicker-dot:nth-child(2) { animation-delay: 0.18s; }
.fs-group-caption .flicker-dot:nth-child(3) { animation-delay: 0.36s; }

.fs-group-listen-card {
  margin-top: 24px;
  position: relative;
  z-index: 1;
  background: rgba(0, 0, 0, 0.4);
  border: 1.5px dashed rgba(255, 87, 34, 0.34);
  border-radius: var(--radius-card, 28px);
  padding: 18px 18px;
  text-align: center;
  overflow: hidden;
}
.fs-group-listen-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(9.5px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.18em;
  color: var(--text-faint);
  text-transform: uppercase;
}
.fs-group-listen-wave {
  display: flex;
  gap: 4px;
  justify-content: center;
  align-items: center;
  margin-top: 14px;
  height: 28px;
}
.fs-group-listen-wave > span {
  width: 4px;
  border-radius: 2px;
  background: linear-gradient(180deg, var(--gold, #FFD24A) 0%, var(--fire, #FF5722) 100%);
  animation: fs-grp-letter-flicker 0.6s ease-in-out infinite;
  opacity: 0.9;
}

/* Frame 2 — Verdict button upgrade. The Mercy side moves from ghost
   (gold-tinted text + border) to FILLED smartyGold gradient + ink fg
   + gold shadow per design pack `.fs-verdict-btn.mercy` shape. The
   `.btn.fsj-mercy` selector already has higher specificity than
   `.btn.btn-ghost`, so we override the ghost chrome with explicit
   filled rules. The Execution side stays as-is (already has the
   right pantsyRed gradient + white fg + red shadow). */
.btn.fsj-mercy {
  background: linear-gradient(160deg, #FFE38A 0%, var(--gold, #FFD24A) 100%);
  color: #3A2410;
  border: 1px solid #8A5A1A;
  box-shadow: 0 6px 18px rgba(255, 210, 74, 0.40), inset 0 1px 0 rgba(255, 255, 255, 0.35);
}
.btn.fsj-mercy:hover {
  background: linear-gradient(160deg, #FFEAA0 0%, var(--gold, #FFD24A) 100%);
  border-color: #6F4815;
  box-shadow: 0 8px 22px rgba(255, 210, 74, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.45);
}
.btn.fsj-mercy.is-mine {
  background: linear-gradient(160deg, #FFE38A 0%, var(--gold, #FFD24A) 55%, var(--fire, #FF5722) 100%);
  color: #3A2410;
  border-color: #8A5A1A;
  box-shadow: 0 8px 22px rgba(255, 210, 74, 0.55), inset 0 1px 0 rgba(255, 255, 255, 0.45);
}
.btn.fsj-mercy .fsj-vote-count {
  background: rgba(58, 36, 16, 0.18);
  color: #3A2410;
}

/* Result stamp animation upgrade — match design pack `fs-r-stamp-slam`.
   Bigger initial scale (2.6 vs prior 1.3) + blur-in + intermediate
   overshoot at 70% creates a more climactic slam. Duration 600ms
   (vs prior 450ms) matches Decision 3 default. Rotation themes
   preserved per .caught (-8deg) / .escaped (6deg) modifiers. */
@keyframes fs-result-stamp-pantsed {
  0%   { transform: rotate(-8deg) scale(2.6); opacity: 0; filter: blur(8px); }
  45%  { transform: rotate(-12deg) scale(0.86); opacity: 1; filter: blur(0); }
  70%  { transform: rotate(-7deg) scale(1.04); }
  100% { transform: rotate(-8deg) scale(1); opacity: 1; }
}
@keyframes fs-result-stamp-escaped {
  0%   { transform: rotate(6deg) scale(2.6); opacity: 0; filter: blur(8px); }
  45%  { transform: rotate(2deg) scale(0.86); opacity: 1; filter: blur(0); }
  70%  { transform: rotate(5deg) scale(1.04); }
  100% { transform: rotate(6deg) scale(1); opacity: 1; }
}
.result-stamp.caught {
  animation: fs-result-stamp-pantsed 0.6s cubic-bezier(.2,.9,.3,1.4) both;
}
.result-stamp.escaped {
  animation: fs-result-stamp-escaped 0.6s cubic-bezier(.2,.9,.3,1.4) both;
}
@media (prefers-reduced-motion: reduce) {
  .result-stamp.caught,
  .result-stamp.escaped {
    animation: none !important;
    transform: rotate(-8deg);
    filter: none;
    opacity: 1;
  }
  .result-stamp.escaped { transform: rotate(6deg); }
}

/* ============================================================
   Bølge 2.2 (2026-05-06) — Pass-the-phone simplification + polish overlays
   ============================================================ */

/* Item A: Stress Mode full-bleed turn notification. Replaces the previous
   discuss-screen overlay approach — this is now a top-level screen returned
   by the renderApp phase switch when the active speaker is on this device.
   Banner for other players renders inside screenDiscuss above the floor. */
.stress-notif-screen {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  background: linear-gradient(180deg, #0a0410 0%, #2a0e1f 100%);
  padding: 24px;
}
.stress-notif-eyebrow {
  font-family: var(--font-display, system-ui);
  font-size: calc(16px * var(--text-scale));
  font-weight: 800;
  letter-spacing: 0.20em;
  color: var(--primary, #FF5722);
  text-transform: uppercase;
  margin-bottom: 16px;
}
.stress-notif-name {
  font-family: var(--font-display, system-ui);
  font-weight: 900;
  font-size: calc(56px * var(--text-scale));
  color: var(--text-on-deep, #FFF4DE);
  letter-spacing: -0.02em;
  margin-bottom: 24px;
  word-break: break-word;
  max-width: 92%;
}
.stress-notif-countdown {
  font-family: var(--font-display, system-ui);
  font-weight: 900;
  font-size: calc(140px * var(--text-scale));
  line-height: 1;
  color: var(--primary, #FF5722);
  text-shadow: 0 0 32px rgba(255, 87, 34, 0.5);
  animation: stressNotifPulse 1s ease-in-out infinite alternate;
}
@keyframes stressNotifPulse {
  0%   { opacity: 0.85; transform: scale(1); }
  100% { opacity: 1; transform: scale(1.03); }
}
.stress-notif-instruction {
  font-family: var(--font-display, system-ui);
  font-size: calc(15px * var(--text-scale));
  color: var(--text-soft);
  margin-top: 24px;
}
.stress-banner {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 14px;
  background: rgba(255, 87, 34, 0.18);
  border: 1px solid rgba(255, 87, 34, 0.45);
  border-radius: 10px;
  margin: 0 0 12px;
  animation: stressBannerSlide .25s ease-out;
}
@keyframes stressBannerSlide {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.stress-banner-name { font-weight: 700; color: var(--primary, #FF5722); }
.stress-banner-text { color: var(--text-on-deep, #FFF4DE); font-size: calc(13px * var(--text-scale)); }
@media (prefers-reduced-motion: reduce) {
  .stress-notif-countdown { animation: none; }
  .stress-banner { animation: none; }
}

/* Item B: Reconnecting screen — branded mascot + subtle pulse. */
.reconnecting-screen {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: linear-gradient(180deg, #1a0e1f 0%, #0a0410 100%);
}
.reconnecting-mascot-wrap {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  animation: reconnectingPulse 1.4s ease-in-out infinite alternate;
}
@keyframes reconnectingPulse {
  0%   { opacity: 0.7; transform: translateY(0); }
  100% { opacity: 1; transform: translateY(-4px); }
}
.reconnecting-eyebrow {
  margin-top: 32px;
  font-family: var(--font-display, system-ui);
  font-size: calc(16px * var(--text-scale));
  font-weight: 700;
  color: var(--text-soft);
  letter-spacing: 0.06em;
}
@media (prefers-reduced-motion: reduce) {
  .reconnecting-mascot-wrap { animation: none; }
}

/* Item C: Mid-game-join blocked screen — friendlier card with mascot. */
.join-blocked-screen {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.join-blocked-card {
  background: rgba(255, 244, 222, 0.04);
  border: 1px solid rgba(255, 244, 222, 0.10);
  border-radius: 18px;
  padding: 32px 24px;
  text-align: center;
  max-width: 320px;
}
.jbc-mascot {
  margin: 0 auto 16px;
  opacity: 0.7;
  display: flex;
  justify-content: center;
}
.jbc-title {
  font-family: var(--font-display, system-ui);
  font-weight: 800;
  font-size: calc(22px * var(--text-scale));
  color: var(--text-on-deep, #FFF4DE);
  margin-bottom: 12px;
}
.jbc-body {
  font-size: calc(14px * var(--text-scale));
  color: var(--text-soft);
  line-height: 1.5;
}
.join-blocked-btn {
  margin-top: 24px;
  width: 100%;
  max-width: 320px;
}
.join-blocked-retry {
  margin-top: 8px;
  width: 100%;
  max-width: 320px;
}

/* Item E: Pantsy spectator screen during vote / bestClue. The Pantsy player
   on a shared device skips the vote handover and lands here while the rest
   of the room decides. */
.pantsy-spectator-screen {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: linear-gradient(180deg, #2a0e1f 0%, #0a0410 100%);
}
.pps-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.18em;
  color: var(--text-faint, rgba(255, 244, 222, 0.45));
  text-transform: uppercase;
  margin-bottom: 24px;
}
.pps-card {
  text-align: center;
}
.pps-name {
  font-family: var(--font-display, system-ui);
  font-weight: 800;
  font-size: calc(48px * var(--text-scale));
  color: var(--text-on-deep, #FFF4DE);
  margin-bottom: 12px;
}
.pps-sub {
  font-style: italic;
  color: var(--text-soft);
  font-size: calc(14px * var(--text-scale));
}

/* Item D: standalone Smart-Roast overlay is mounted inside screenVote /
   screenBestClue / screenResult via the engine's own subtle variant.
   No extra CSS needed — the existing `.smart-roast-ticker.is-subtle`
   rule from Bølge 2.0 (transparent bg, no border) handles the look. */

/* ============================================================
   Bølge 2.3 (2026-05-06) — Bug-killing + floor screen redesign
   ============================================================ */

/* Item N: clockwise floor screen big-card layout. ONE card that switches
   contents at the 30-second mark from starter info → in-card Smart-Roast
   comments. Replaces the dual floor-card + bottom-strip Smart-Roast that
   shipped Bølge 2.0. */
.discuss-screen {
  display: flex;
  flex-direction: column;
  /* min-height removed 2026-05-11 (Stian round 7) — `flex: 1` from `.screen` base is sufficient; min-height was making the screen overflow `#screen` and pushing CTAs under the home-indicator on iOS PWA */
  /* 2026-05-11 (Stian round 3): padding dropped entirely, matching the
     pass-the-phone screen which uses `.screen` base (no padding override)
     and lets `.app` provide all the viewport gutter. Pre-fix the
     `calc(env(safe-area-inset-top, 0) + 24px) ... max(20px, env(safe-area-inset-bottom))`
     pattern double-counted the safe-area that `.app` already adds
     (`padding: env(safe-area-inset-top) + 16px ... max(20px, env(safe-area-inset-bottom))`),
     pushing the starter card ~50-70px lower from the topbar and
     ~20-34px higher from the bottom edge than pass-the-phone. With
     `padding: 0`, the starter sits at exactly the same vertical
     rhythm as the pass-to-Nn card. */
  padding: 0;
  /* 2026-05-11 (Stian round 4): gap set to 14px to match the pass-the-phone
     `.handover-wrap`'s canonical 14px between card and CTA. Was 12px.
     Net: card→peek = peek→CTA = card→CTA = 14px everywhere. */
  gap: 14px;
}
/* Bølge 29.5 N1 (2026-05-24): peek + bottom CTA need to sit at the
   column footer. 2026-05-11 (Stian) revision: the auto-margin approach
   the N1 fix used absorbed the free space BEFORE the card's flex-grow
   could claim it (per CSS spec: auto margins take priority over
   flex-grow), which left a visible gap between the bottom of the
   floor-big-card and the peek button. The card already has
   `flex: 1 1 auto` and the screen has `min-height: calc(100dvh - 80px)`,
   so flex-grow alone now pushes peek + CTA to the bottom — the
   auto-margin is removed. Net layout reads: card (grow) → peek → CTA. */
.discuss-screen .clue-peek-affordance,
.discuss-screen .clue-peek-affordance + .discuss-advance-btn {
  flex-shrink: 0;
}

/* Bølge 29.5 N6 (2026-05-24): Pantsy Speaks redesign. Inherits the
   .discuss-screen + .floor-big-card chassis from screenDiscuss. The
   title (e.g., "Anna, say the word out loud") is longer than the
   single-name .fbc-starter-name (just "Bjorn"), so we drop the
   font-size from 56px to a wrappable 30px and tighten line-height
   so 2-pantsy "Anna and Charlie, say the word together..." stays
   readable without overflowing the card on iPhone-narrow. The peek
   button is intentionally absent — anti-peek invariant since B9. */
.fbc-pantsy-speaks-title {
  font-size: calc(30px * var(--text-scale)) !important;
  line-height: 1.15 !important;
  max-width: 100%;
}
/* 2026-05-11 (Stian): Pantsy-speaks auto-margin removed in lockstep
   with the `.clue-peek-affordance` revision above — the card's
   flex-grow now pushes the CTA / spectator-hint to the column footer
   without needing an auto-margin spacer. */
.floor-big-card {
  background: linear-gradient(145deg, #2a1838 0%, #1a0e1f 100%);
  border: 1px solid rgba(255, 244, 222, 0.10);
  border-radius: 24px;
  padding: 32px 24px;
  text-align: center;
  min-height: 360px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  /* Bølge 2.4 Item I (2026-05-06): flex-grow so the card fills available
     vertical space between the safe-area top and the peek/CTA stack at
     bottom. Replaces the prior fixed `margin-top: 16px` + spacer-div
     pattern. */
  flex: 1 1 auto;
}
.fbc-icon {
  font-size: calc(48px * var(--text-scale));
  margin-bottom: 18px;
  line-height: 1;
}
.fbc-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.18em;
  color: var(--text-faint, rgba(255, 244, 222, 0.5));
  text-transform: uppercase;
  margin-bottom: 24px;
}
.fbc-body {
  display: flex;
  flex-direction: column;
  gap: 14px;
  align-items: center;
}
.fbc-starter-name {
  font-family: var(--font-display, system-ui);
  font-weight: 800;
  font-size: calc(56px * var(--text-scale));
  color: var(--text-on-deep, #FFF4DE);
  letter-spacing: -0.02em;
  line-height: 1.05;
  word-break: break-word;
  max-width: 92%;
}
.fbc-clockwise-help {
  font-family: var(--font-display, system-ui);
  font-size: calc(15px * var(--text-scale));
  color: var(--text-soft);
  font-weight: 600;
  letter-spacing: 0.04em;
}
.smart-roast-embedded {
  width: 100%;
  text-align: center;
  min-height: 80px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.smart-roast-embedded .sre-line {
  font-family: var(--font-display, system-ui);
  font-style: italic;
  font-size: calc(18px * var(--text-scale));
  color: var(--text-on-deep, #FFF4DE);
  line-height: 1.4;
  transition: opacity .25s ease, transform .25s ease;
  padding: 0 16px;
}
.smart-roast-embedded .sre-line.fade-out { opacity: 0; transform: translateY(-3px); }
.smart-roast-embedded .sre-line.fade-in  { opacity: 1; transform: translateY(0); }
.discuss-advance-btn {
  width: 100%;
  /* 2026-05-11 (Stian): `margin-top: 16px` removed. The `.discuss-screen`
     flex container already applies a `gap: 12px` between all siblings, so
     the extra margin was stacking on top of the gap and producing a
     ~28px peek→CTA distance — visually inconsistent with the ~16px
     card→peek gap above it, and looser than the pass-gate handover's
     single 14px rhythm. Dropping the margin returns the column to a
     uniform 12px gap. */
  white-space: normal;
  line-height: 1.2;
}

/* Bølge 29 (2026-05-22): merged STARTER + WHISPERS panel + Discuss screen.
   The card now stacks icon → eyebrow → body → whispers always-on instead of
   toggling at 30s. The eyebrow's margin-bottom shrinks (was 24px when only
   one block followed; now there are two) and the embedded whisper line gets
   a top margin so it reads as a separate beat from the starter name block.
   Discuss screen reuses the same chassis with a small italic subtitle slotted
   between eyebrow and whispers. */
.floor-big-card .fbc-body + .smart-roast-embedded {
  margin-top: 18px;
}
.discuss-screen.is-discuss-panel .fbc-eyebrow {
  margin-bottom: 12px;
}
.fbc-discuss-subtitle {
  font-family: var(--font-display, system-ui);
  font-size: calc(15px * var(--text-scale));
  color: var(--text-soft);
  font-weight: 600;
  letter-spacing: 0.04em;
  margin-bottom: 18px;
  padding: 0 16px;
}

/* Item P: Final Stand redesigned — big-card with timer-as-CTA at bottom.
   Pantsy view has hot-orange gradient (matches the Bølge 2.1 fs-card
   palette); spectator view uses the calm dark gradient (waiting feel). */
.final-stand-pantsy-screen,
.final-stand-spectator-screen {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  padding: calc(env(safe-area-inset-top, 0) + 24px) 16px max(20px, env(safe-area-inset-bottom));
}
.final-stand-card-big {
  flex: 1;
  background: linear-gradient(145deg, rgba(255, 87, 34, 0.95) 0%, rgba(216, 30, 22, 0.95) 100%);
  border-radius: 24px;
  padding: 32px 24px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  color: var(--text-on-deep, #FFF4DE);
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.4);
  margin-top: 12px;
}
.final-stand-card-big.spectator {
  background: linear-gradient(145deg, #2a1838 0%, #1a0e1f 100%);
}
.fsc-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.16em;
  color: rgba(255, 244, 222, 0.7);
  text-transform: uppercase;
  margin-bottom: 16px;
}
.fsc-title {
  font-family: var(--font-display, system-ui);
  font-weight: 800;
  font-size: calc(36px * var(--text-scale));
  letter-spacing: -0.02em;
  margin-bottom: 12px;
  line-height: 1.1;
}
.fsc-explainer {
  font-size: calc(15px * var(--text-scale));
  color: rgba(255, 244, 222, 0.85);
  margin-bottom: 24px;
  line-height: 1.4;
}
.fs-guess-input {
  background: rgba(0, 0, 0, 0.18);
  border: 1.5px solid rgba(255, 244, 222, 0.32);
  border-radius: 12px;
  padding: 18px 16px;
  font-family: var(--font-display, system-ui);
  font-size: calc(22px * var(--text-scale));
  font-weight: 700;
  color: var(--text-on-deep, #FFF4DE);
  outline: none;
  width: 100%;
  box-sizing: border-box;
}
.fs-guess-input::placeholder {
  color: rgba(255, 244, 222, 0.45);
  font-weight: 500;
}
.fs-guess-input:focus { border-color: var(--text-on-deep, #FFF4DE); }
.final-stand-cta-timer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  margin-top: 16px;
}
.final-stand-cta-timer .cta-label { flex: 1; text-align: left; }
.final-stand-cta-timer .cta-timer {
  font-family: var(--font-mono);
  font-size: calc(14px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.05em;
  background: rgba(0, 0, 0, 0.20);
  padding: 4px 10px;
  border-radius: 6px;
}
.fsc-non-host-timer {
  text-align: center;
  margin-top: 16px;
  font-family: var(--font-mono);
  font-size: calc(13px * var(--text-scale));
  color: var(--text-soft);
  letter-spacing: 0.08em;
}

/* Item H: shared-room "No time limit" hint where the timer bar would
   otherwise render. Quiet pill so it doesn't compete with the vote list. */
.vote-no-timer {
  text-align: center;
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.10em;
  text-transform: uppercase;
  color: var(--text-soft);
  padding: 6px 12px;
  background: rgba(255, 244, 222, 0.04);
  border: 1px solid rgba(255, 244, 222, 0.08);
  border-radius: 8px;
  margin: 0 0 12px;
  align-self: center;
}

/* Bølge 2.7 (2026-05-07): host-approved Layer 2 club recovery modal.
   Mounted at body level (escapes sheet z-index contexts). High z-index
   so it floats above settings/category sheets if host gets the prompt
   while a sheet is open. Two warning bands (recency, contested-before)
   share the .hrm-warning style — amber-on-warm for "pause and read". */
.host-recovery-modal-overlay {
  position: fixed; inset: 0;
  /* Bølge 168 (2026-05-13): backdrop migrated rgba(0,0,0,0.7) → token
     --modal-backdrop (rgba(15,4,24,0.94)). Was an outlier — deeper alpha
     + deep-purple tint aligns with the .onboard-overlay family. */
  background: var(--modal-backdrop);
  display: flex; align-items: center; justify-content: center;
  z-index: 350;
  padding: 24px;
}
.host-recovery-modal {
  background: var(--surface-mid);
  /* Bølge 168 (2026-05-13): radius 18px → --radius-modal (24px) to match
     .onboard-modal. The 18px was an unflagged outlier. */
  border-radius: var(--radius-modal);
  padding: 28px 22px;
  max-width: 380px; width: 100%;
  text-align: left;
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.5);
}
.hrm-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.18em;
  color: var(--gold, #ffd24a);
  text-transform: uppercase;
  margin-bottom: 12px;
}
.hrm-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: calc(20px * var(--text-scale));
  color: var(--text-on-deep);
  line-height: 1.3;
  margin-bottom: 12px;
}
.hrm-body {
  font-size: calc(14px * var(--text-scale));
  color: var(--text-soft);
  line-height: 1.4;
  margin-bottom: 14px;
}
.hrm-warning {
  font-size: calc(13px * var(--text-scale));
  color: var(--warning, #f59e0b);
  background: rgba(245, 158, 11, 0.08);
  border: 1px solid rgba(245, 158, 11, 0.25);
  border-radius: 10px;
  padding: 10px 12px;
  margin-bottom: 14px;
  line-height: 1.4;
}
.hrm-actions {
  display: flex; flex-direction: column; gap: 10px;
  margin-top: 18px;
}

/* ═══════════════════════════════════════════════════════════════════════
   Bølge 30 (2026-05-23) — profile surface lock-down
   ═══════════════════════════════════════════════════════════════════════
   Pattern anchor: Accessibility panel — single rounded outer box, eyebrow
   above, flat rows inside separated by hairline divider, no nested cards.
   B30 promotes this to a primitive .profile-panel + .profile-panel-row
   used by Accessibility, Recovery, About-You, and Spicy. Earlier panels
   (Recovery, About-You) were rendering nested .profile-prefs-row chrome
   inside .card.dark — visible "card-on-card" look. The new chassis is
   transparent rows on a single card, exactly matching the anchor.
*/

/* Base panel container. Equivalent to the prior .profile-a11y-panel
   (transparent rows, hairline divider on +) but namespaced for cross-
   panel reuse. Inherits from .card.dark for surface/border/shadow. */
.profile-panel {
  padding: 6px 0;
  /* N8: smooth the layout reflow when --text-scale changes via the
     Larger-text toggle. The rows grow taller because their font-sizes
     are calc(<px>*--text-scale); a transition on padding masks the
     instant jump that read as "background changes a bit" in Stian's
     2026-05-15 report. The card.dark bg + border + box-shadow are
     already pinned by the B28 N7 defensive guards (see line 3678). */
  transition: padding 200ms ease;
}
.profile-panel-row {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 12px 16px;
  background: transparent;
  border: 0;
  border-radius: 0;
  font-family: inherit;
  text-align: left;
  color: inherit;
  /* N8: same transition reasoning as the panel above. */
  transition: padding 200ms ease;
}
.profile-panel-row + .profile-panel-row {
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
/* N6: NO :hover bg/outline/border on profile rows. Stian reported the
   Haptic feedback row showed a "square/box" on mouse hover — a
   surface-hi bg from the legacy .gs-toggle-row:hover rule. The new
   primitive intentionally drops :hover entirely. Active-state press
   feedback stays for touch devices. */
.profile-panel-row:hover {
  background: transparent;
  outline: none;
  border-radius: 0;
}
.profile-panel-row:active {
  /* Bølge 87 (2026-05-11, ROADMAP #46): stronger press feedback so the
     tap is visibly acknowledged before renderApp() tears down + remounts
     the DOM. The previous 0.02 alpha was barely visible on a finger-tap
     and contributed to the playtest "did my tap register?" report.
     0.06 + slight scale-down + short transition reads as a deliberate
     press across both light + dark surfaces without competing with the
     chevron/toggle affordance. */
  background: rgba(255, 255, 255, 0.06);
  transform: scale(0.985);
  transition: background 80ms ease, transform 80ms ease;
}
/* Bølge 87 (2026-05-11): the post-click busy guard set by
   profilePanelRow's guardedOnTap. Brief pointer-events lock during the
   sheet open transition prevents a second pointerdown from re-firing
   the same onclick handler mid-renderApp. Visual remains the same as
   the steady-state row (no jitter). */
.profile-panel-row[data-busy="1"] {
  pointer-events: none;
}
/* Cursor: chevron rows signal forward navigation; toggle rows are inline
   state. Per spec — chevron pointer, toggle default. */
.profile-panel-row.is-chevron { cursor: pointer; }
.profile-panel-row.is-toggle { cursor: default; }
.profile-panel-row.is-disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.profile-panel-row.is-disabled .gs-toggle-switch { opacity: 0.6; }

.profile-panel-row .ppr-icon {
  width: 32px;
  height: 32px;
  border-radius: 9px;
  background: rgba(255, 255, 255, 0.06);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: calc(18px * var(--text-scale));
  flex-shrink: 0;
}
.profile-panel-row .ppr-meta {
  flex: 1;
  min-width: 0;
}
.profile-panel-row .ppr-label {
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: calc(14px * var(--text-scale));
  color: var(--text-on-deep);
  letter-spacing: -0.01em;
  line-height: 1.2;
}
/* Spicy mode label override — uses .pcr-club-name typography (13px /
   600 / -0.005em) so the standalone Spicy panel reads as an identity-
   tier surface, matching B28's intended hierarchy. */
.profile-panel-row .ppr-label.is-clubname {
  font-size: calc(13px * var(--text-scale));
  letter-spacing: -0.005em;
}
/* Bølge 31 N5 (2026-05-25): "Activate passkey" label was wrapping to
   two lines on narrow viewports (320px). Now that the 🔐 icon is gone
   per N4, there's enough horizontal room for the full label — but
   nowrap pins it explicitly. The .ppr-meta column is overflow-hidden
   on the parent so a freak long label still clips cleanly. */
.profile-panel-row .ppr-label.ppr-label-nowrap {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Bølge 31 N1 (2026-05-25): Spicy-panel row has no in-row label —
   the panel eyebrow ("SPICY MODE") IS the header. Hide the empty
   .ppr-label slot so the row collapses to just a right-aligned toggle.
   The aria-label on the row preserves screen-reader semantics. */
.profile-spicy-panel .profile-panel-row .ppr-label:empty {
  display: none;
}
.profile-spicy-panel .profile-panel-row {
  justify-content: flex-end;
}
.profile-panel-row .ppr-sub {
  font-size: calc(12px * var(--text-scale));
  color: var(--text-faint);
  -webkit-text-fill-color: var(--text-faint);
  margin-top: 2px;
  line-height: 1.4;
}
.profile-panel-row .ppr-chevron {
  font-size: calc(18px * var(--text-scale));
  color: var(--text-faint);
  flex-shrink: 0;
  line-height: 1;
  padding-left: 6px;
}

/* N9: Achievements tile background-fill. Replaces the prior mini-bar +
   text below the glyph (.ach-tile-progress / -track / -fill / -text)
   with a single bg-fill that grows left-to-right based on progress
   fraction. Icon stays muted and centered above the fill via
   z-index. No numbers shown — the visual itself communicates progress.
   Earned tiles keep the existing gold-tint treatment (no fill needed,
   they're already 100%). */
.profile-achievements-panel .achievement-icon-pending {
  position: relative;
  overflow: hidden;
}
.profile-achievements-panel .achievement-icon-pending .ach-tile-bgfill {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  width: var(--tile-progress, 0%);
  background: linear-gradient(90deg,
    rgba(255, 210, 74, 0.22) 0%,
    rgba(255, 210, 74, 0.14) 100%);
  pointer-events: none;
  z-index: 0;
  transition: width 0.18s ease-out;
}
.profile-achievements-panel .achievement-icon-pending .ach-tile-glyph {
  position: relative;
  z-index: 1;
  /* opacity inherited from existing .achievement-icon-pending .ach-tile-glyph
     rule (~0.55) — keeps the muted look against the partial fill. */
}
/* Drop the old mini-bar visual when used inside achievement-icon-pending —
   we still keep the .ach-tile-progress class definition above for legacy
   surfaces, but B30 stops rendering it on profile tiles. The CSS rule
   itself stays intact for backward compat in cached clients. */

/* B82 (2026-05-10) — Roadmap #41 prefs nudge banner.
   Renders at top of `.final-scroll-body` in screenEnded when post-first-game
   conditions are met. Golden tip-banner primitive: cream/gold gradient bg +
   ink fg + 3-button row. Dismissable via Later (24hr cooldown) / Never
   (terminal). Visual hierarchy below winnerHero (compact, doesn't compete
   with the win moment). */
.prefs-nudge-banner {
  margin: 8px 14px 14px;
  padding: 12px 14px;
  background: linear-gradient(160deg, rgba(255, 244, 222, 0.94) 0%, rgba(252, 233, 183, 0.88) 100%);
  border: 1px solid rgba(255, 210, 74, 0.35);
  border-radius: var(--radius-btn, 12px);
  color: var(--ink, #1A0820);
  display: flex;
  flex-direction: column;
  gap: 10px;
  box-shadow: 0 2px 10px rgba(138, 90, 26, 0.10);
}
.prefs-nudge-meta {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.prefs-nudge-title {
  font-family: var(--font-display, system-ui);
  font-weight: 800;
  font-size: calc(15px * var(--text-scale));
  letter-spacing: -0.015em;
  line-height: 1.2;
  color: var(--ink, #1A0820);
}
.prefs-nudge-body {
  font-size: calc(12.5px * var(--text-scale));
  line-height: 1.35;
  color: var(--ink-soft, #3F1A4A);
}
.prefs-nudge-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
.prefs-nudge-btn {
  position: relative;
  flex: 0 0 auto;
  min-height: 36px;
  padding: 0 14px;
  border-radius: var(--radius-pill, 999px);
  font-family: inherit;
  font-weight: 700;
  font-size: calc(12.5px * var(--text-scale));
  letter-spacing: -0.005em;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s, color 0.12s;
}
.prefs-nudge-btn-primary {
  background: var(--fire, #FF5722);
  color: #fff;
  border: 1px solid var(--fire, #FF5722);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08);
}
.prefs-nudge-btn-primary:hover {
  background: var(--fire-dim, #D33E14);
  border-color: var(--fire-dim, #D33E14);
}
.prefs-nudge-btn-ghost {
  background: transparent;
  color: var(--ink-soft, #3F1A4A);
  border: 1px solid rgba(26, 8, 32, 0.18);
}
.prefs-nudge-btn-ghost:hover {
  background: rgba(26, 8, 32, 0.05);
  border-color: rgba(26, 8, 32, 0.28);
}
/* B82: 44×44 hit target on each button (visual stays at 36px height,
   ::before extends touch surface) per RESKIN-PRINCIPLES sec. 3 a11y. */
.prefs-nudge-btn::before {
  content: "";
  position: absolute;
  inset: -4px;
  border-radius: inherit;
}

/* B64 P4 (2026-05-10) — Vote-screen status footer.
   Replaces the legacy `.vote-waiting`/`.vw-dots` chassis on the main vote
   list per `_pantsy9/07c.5-point-at-pantsy/screens-vote.jsx`. Legacy
   `.vote-waiting` styles preserved (~line 6201) since other surfaces still
   reference them; the new `.vote-status-footer` chassis is opt-in via
   render-side class swap. New keyframe name (`vote-status-dots-pulse`) so
   the legacy `vw-dots` animation isn't disturbed. */
.vote-status-footer {
  margin-top: auto;
  padding: 12px 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-size: calc(13px * var(--text-scale));
  color: var(--text-soft, #B5A48E);
  line-height: 1.3;
}
.vote-status-text strong {
  color: var(--text-on-deep, #FFF4DE);
  font-weight: 800;
  font-family: var(--font-display, system-ui);
  letter-spacing: -0.01em;
}
.vote-status-dots {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.vote-status-dot {
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--fire, #FF5722);
  opacity: 0.4;
  animation: vote-status-dots-pulse 1.2s ease-in-out infinite;
}
.vote-status-dot:nth-child(1) { animation-delay: 0s; }
.vote-status-dot:nth-child(2) { animation-delay: 0.18s; }
.vote-status-dot:nth-child(3) { animation-delay: 0.36s; }
@keyframes vote-status-dots-pulse {
  0%, 100% { opacity: 0.30; transform: scale(0.85); }
  50%      { opacity: 1.00; transform: scale(1.15); }
}
@media (prefers-reduced-motion: reduce) {
  .vote-status-dot { animation: none !important; opacity: 0.6; }
}

/* ============================================================
   Bølge 97.4 (2026-05-10) — Final Stand verdict re-do per audit
   `_audit/parity-audit-2026-05-10/REPORT.md` § B67. Mirrors design
   pack `_audit/_pantsy9/07f-final-stand-verdict/screens-final-stand.jsx`
   lines 360-592 (ScreenFinalStandVerdict). Ships behind the
   `.fsj-verdict-rebuild` modifier on the screen wrapper so the
   pre-existing `.fsj-card`/`.fsj-headline` rules above stay
   inert (they'd shadow the cream-card chassis otherwise).
   ============================================================ */

/* Cream card — JSX 380-387: cream bg, radiusCard, 28/24 padding,
   flex column, ink color. Fills the available vertical space
   between the topbar (global chrome above #app) and the bottom
   CTA grid. */
.fsj-verdict-rebuild {
  /* 2026-05-11 (Stian round 4): gap set to 14px matching the
     pass-the-phone canonical rhythm. All padding stays at 0 — `.app`
     provides the viewport gutter. The CTA row is now in normal flex
     flow (no longer `position: fixed`) so the column-gap creates the
     card→CTA distance directly, instead of relying on a manual
     `padding-bottom` to clear a fixed-positioned button row. */
  gap: 14px;
  padding: 0;
}
.fsj-verdict-rebuild .fsj-verdict-cream-card {
  /* 2026-05-11 (Stian): cream card grows to fill the available vertical
     space between the screen top and the fixed CTA row at the bottom.
     Reverses B126 Decision #7's `flex: 0 0 auto; height: auto;`.
     Decision #7's stated risk was "dead cream space below the coaching
     block" when the card stretched, but the inner flex layout already
     prevents this — `.fsj-verdict-word-block { flex: 1 }` grows to fill
     the middle, and `.fsj-verdict-coaching` is the last child so it
     hugs the card-bottom. Net layout when stretched: category eyebrow
     at top → word centered in the grown middle → coaching pinned to
     card-bottom, no dead space anywhere. The screen's
     `padding-bottom: 88px` still clears the fixed CTA row. */
  flex: 1 1 auto;
  background: var(--surface-card, #FFF4DE);
  color: var(--ink, #1A0820);
  border-radius: var(--radius-card, 28px);
  padding: 28px 24px;
  display: flex;
  flex-direction: column;
  position: relative;
  overflow: hidden;
}

/* Category eyebrow — JSX 433-438: 🌍 + "Category · Places" inkSoft
   mono caps, position relative for stacking above any future
   stamp overlay. */
.fsj-verdict-category {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--ink-soft, #3F1A4A);
  text-transform: uppercase;
}
.fsj-verdict-category .fsj-vc-icon {
  font-size: calc(13px * var(--text-scale));
  line-height: 1;
}
.fsj-verdict-category .fsj-vc-label {
  /* Already uppercased via parent text-transform — keep tracking */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Centered word block — JSX 440-453: flex 1, justifyCenter, with
   the word filling the remaining vertical space inside the card. */
.fsj-verdict-word-block {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
  margin-top: 2px;
}
.fsj-verdict-stage-label {
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft, #3F1A4A);
}
.fsj-verdict-word-headline {
  font-family: var(--font-display);
  font-weight: 700;
  /* JSX 449-450: 64px / 0.95 line-height / -0.035em letter-spacing.
     Clamp scales down on iPhone-narrow without forcing char-level
     breaks (B94 lesson — `word-break: keep-all` is already on
     `.reveal-card .word`; we apply it here too as a guard). */
  font-size: calc(clamp(40px, 16vw, 64px) * var(--text-scale));
  line-height: 0.95;
  letter-spacing: -0.035em;
  color: var(--ink, #1A0820);
  margin-top: 10px;
  word-break: keep-all;
  overflow-wrap: break-word;
  hyphens: auto;
  text-wrap: balance;
}

/* Coaching block — JSX 456-484: borderTop separator + question
   + stakes line. Sits below the word block, above the bottom of
   the cream card. */
.fsj-verdict-coaching {
  border-top: 1px solid rgba(63, 26, 74, 0.10); /* inkSoft @ ~10% */
  padding-top: 14px;
  position: relative;
}
.fsj-verdict-question {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: calc(17px * var(--text-scale));
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--ink, #1A0820);
}
.fsj-verdict-question .fsj-verdict-almost {
  color: var(--ink-soft, #3F1A4A);
  font-style: italic;
  font-weight: 500;
}

/* Stakes row — JSX 468-483: mono caps 10px label + middle dot +
   countdown. Countdown pulses red when ≤3s remain. */
.fsj-verdict-stakes-row {
  margin-top: 4px;
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-soft, #3F1A4A);
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.fsj-verdict-stakes-row .fsj-stakes-sep { opacity: 0.5; }
.fsj-verdict-stakes-row .fsj-stakes-countdown {
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft, #3F1A4A);
}
.fsj-verdict-stakes-row.is-urgent .fsj-stakes-countdown {
  color: var(--pantsy-red, #FF1744);
  animation: fsj-verdict-countdown-pulse 0.6s ease-in-out infinite;
}
.fsj-verdict-stakes-row .fsj-stakes-countdown.is-expired {
  color: var(--pantsy-red, #FF1744);
}
@keyframes fsj-verdict-countdown-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.7; transform: scale(1.08); }
}

/* Tally row + split bar — JSX 486-511: Mercy gold left, Execute
   red right, 6px height bar with proportional fills + 999 radius. */
.fsj-verdict-tally-row {
  margin-top: 12px;
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.fsj-verdict-tally-row .fsj-tally-mercy {
  color: var(--gold, #FFD24A);
  /* On cream the smarty-gold stays readable; design uses smartyGold
     (#FFD24A) directly. Slight underlay shadow keeps it crisp at
     small sizes when the cream backdrop is the same warm family. */
  text-shadow: 0 1px 0 rgba(58, 36, 16, 0.18);
}
.fsj-verdict-tally-row .fsj-tally-execute {
  color: var(--pantsy-red, #FF1744);
  text-shadow: 0 1px 0 rgba(80, 6, 14, 0.10);
}
.fsj-verdict-split-bar {
  margin-top: 6px;
  height: 6px;
  border-radius: 999px;
  background: rgba(63, 26, 74, 0.13); /* inkSoft @ ~13% — JSX uses 22 */
  display: flex;
  overflow: hidden;
}
.fsj-verdict-split-bar .fsj-split-mercy {
  background: var(--gold, #FFD24A);
  transition: width 0.4s cubic-bezier(.2,.9,.3,1);
  height: 100%;
}
.fsj-verdict-split-bar .fsj-split-execute {
  background: var(--pantsy-red, #FF1744);
  transition: width 0.4s cubic-bezier(.2,.9,.3,1);
  height: 100%;
}

/* Bottom CTA grid — JSX 546-588: 2 columns, both fire-orange,
   56h, 19px Fraunces 700 white text. The legacy `.fsj-button-row`
   + `.btn.fsj-mercy` (gold gradient) + `.btn.fsj-execution` (red
   gradient) rules are scoped to `.fsj-button-row` so they stay
   inert under the new chassis. */
.fsj-verdict-rebuild .fsj-verdict-cta-row {
  /* 2026-05-11 (Stian round 4): un-fixed back into normal flex flow.
     Pre-round-4 the row was `position: fixed; bottom: safe + 16px`
     because B126's content-sized cream card couldn't push the buttons
     to the screen bottom on its own. Now that the card flex-grows
     (revert of B126 Decision #7), the in-flow row sits at the column
     bottom naturally, with the 14px column gap setting card→CTA
     distance — same canonical rhythm as pass-the-phone. `.app`'s
     `max(20px, env(safe-area-inset-bottom))` padding handles the
     home-indicator buffer. */
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}
/* Bølge 126: with CTAs fixed-positioned out of flow, the screen needs
   bottom padding equal to the button height + the safe-area inset so
   the cream-card content doesn't slide under the floating row. */
/* 2026-05-11 (Stian round 4): `.final-stand-judge-screen.fsj-verdict-rebuild`
   `padding-bottom: 88px` rule removed. It was a workaround so the cream-card
   content didn't slide under the fixed-positioned CTA row. With the CTA row
   now in normal flex flow (un-fixed in round 4), no clearance padding is
   needed — the row reserves its own column space. */
.btn.fsj-verdict-cta {
  height: 56px;
  padding: 0 18px;
  background: var(--fire, #FF5722);
  color: #fff;
  border: none;
  border-radius: var(--radius-btn, 14px);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(19px * var(--text-scale));
  letter-spacing: -0.01em;
  line-height: 1;
  cursor: pointer;
  transition: transform 0.12s ease, background 0.12s ease, box-shadow 0.18s ease;
  box-shadow: 0 4px 14px rgba(255, 87, 34, 0.30);
}
.btn.fsj-verdict-cta:hover {
  background: var(--fire-dim, var(--fire, #FF5722));
  box-shadow: 0 6px 18px rgba(255, 87, 34, 0.42);
}
.btn.fsj-verdict-cta:active { transform: translateY(1px); }
.btn.fsj-verdict-cta.is-mine {
  box-shadow: 0 0 0 2px rgba(255, 244, 222, 0.32), 0 6px 18px rgba(255, 87, 34, 0.42);
}
.btn.fsj-verdict-cta .fsj-vc-label {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(19px * var(--text-scale));
  letter-spacing: -0.01em;
  line-height: 1;
}

@media (prefers-reduced-motion: reduce) {
  .fsj-verdict-stakes-row.is-urgent .fsj-stakes-countdown {
    animation: none !important;
  }
  .fsj-verdict-split-bar .fsj-split-mercy,
  .fsj-verdict-split-bar .fsj-split-execute {
    transition: none;
  }
}

/* ============================================================
   Bølge 97.3 (2026-05-10) — Build category preview state re-do.
   Mirrors design pack
   `_audit/_pantsy9/02b2-build-category-type-list/screens-build-cat.jsx`
   lines 310-435 (ScreenBuildCategoryPreview). Closes B97 audit
   § B66 (4 P0 + 4 P1). The legacy `.build-review-row` vertical
   list + `.build-review-back` link are no longer rendered when
   savedAIWords is populated — replaced by the chip-grid chassis
   below. Old CSS rules stay inert (no `.build-review-row` in
   the new DOM). The custom overlay uses the standard
   `.sheet-overlay` + `.sheet-modal-with-footer` chassis so the
   bottom-sticky footer + safe-area-inset padding inherit
   correctly.
   ============================================================ */

/* Custom header — Done LEFT + centered eyebrow + 64px spacer RIGHT
   (JSX 323-339). The default `.sheet-header` is space-between with
   text-block LEFT + Done RIGHT — we override layout + child
   placement under the modifier class. */
.sheet-header.sheet-header-build-preview {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 20px 12px;
  gap: 12px;
}
.sheet-header-build-preview .build-preview-done-btn {
  /* Pull from sheet-done-btn defaults; ensure it sits LEFT. */
  order: 0;
}
.sheet-header-build-preview .build-preview-header-eyebrow {
  flex: 1;
  text-align: center;
  font-family: var(--font-mono);
  font-size: calc(10px * var(--text-scale));
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--text-faint);
  text-transform: uppercase;
  order: 1;
}
.sheet-header-build-preview .build-preview-header-spacer {
  width: 64px;
  flex-shrink: 0;
  order: 2;
}

/* Preview body — JSX 322 (PhoneScreen children) renders the name pill,
   prompt summary, words header, and chip grid as a vertical stack with
   20px horizontal gutters. `.sheet-body` already provides the scroll
   container chrome; we add per-block spacing here. */
.sheet-body.build-preview-body {
  padding: 0 20px 20px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* Name + emoji pill — JSX 341-367. Replaces the legacy
   `.build-name-card` (which has a vertical orange separator bar
   that's NOT in the design pack — audit P1 finding 6). The
   design uses a 36×36 SQUARE avatar (10px radius) with no
   separator; italic Fraunces name; right-aligned TAP TO EDIT pill. */
.build-preview-name-pill,
.build-preview-name-edit {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--surface-lo, #160820);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-btn, 14px);
  padding: 10px 14px;
  height: 56px;
  width: 100%;
  cursor: pointer;
  color: var(--text-on-deep, #FFF4DE);
  font-family: var(--font-sans, system-ui);
  text-align: left;
  appearance: none;
}
.build-preview-name-pill:hover {
  background: rgba(255, 255, 255, 0.03);
  border-color: rgba(255, 255, 255, 0.12);
}
.bpnp-emoji,
.bpnp-emoji-btn {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.04);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: calc(20px * var(--text-scale));
  flex-shrink: 0;
  border: none;
  cursor: pointer;
  color: inherit;
}
.bpnp-name {
  flex: 1;
  min-width: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(17px * var(--text-scale));
  letter-spacing: -0.015em;
  color: var(--text-on-deep, #FFF4DE);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bpnp-name.is-empty {
  color: var(--text-faint);
  font-style: italic;
}
.bpnp-edit-hint {
  font-family: var(--font-mono);
  font-size: calc(9.5px * var(--text-scale));
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  flex-shrink: 0;
}
.build-preview-name-edit .build-preview-name-input {
  flex: 1;
  background: transparent;
  border: none;
  outline: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: calc(17px * var(--text-scale));
  letter-spacing: -0.015em;
  color: var(--text-on-deep, #FFF4DE);
}

/* Prompt summary card — JSX 369-382. surfaceLo bg, 1px stroke,
   "VIBE" eyebrow + Fraunces 13px aiDescription text. */
.build-preview-prompt-card {
  background: var(--surface-lo, #160820);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: var(--radius-btn, 14px);
  padding: 9px 12px 11px;
}
.build-preview-prompt-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(9.5px * var(--text-scale));
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.build-preview-prompt-body {
  font-family: var(--font-sans, system-ui);
  font-size: calc(13px * var(--text-scale));
  margin-top: 3px;
  line-height: 1.4;
  color: var(--text-soft);
}

/* Words header row — JSX 385-390. Eyebrow LEFT + gold ↻ REGENERATE
   pill RIGHT, on the same baseline. */
.build-preview-words-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0;
  margin-top: 4px;
}
.build-preview-words-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.build-preview-regenerate {
  appearance: none;
  background: transparent;
  border: none;
  padding: 4px 6px;
  margin: -4px -6px;
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--gold, #FFD24A);
  cursor: pointer;
  transition: opacity 0.12s ease, color 0.12s ease;
}
.build-preview-regenerate:hover {
  color: #FFE38A;
}
.build-preview-regenerate.is-pending {
  opacity: 0.55;
  cursor: wait;
}
.build-preview-regenerate[disabled] {
  pointer-events: none;
}

/* Pill-grid — JSX 392-408. flex-wrap with 6px gap; chips are
   rounded 999px pills with surface bg + 1px stroke + 6×12 padding.
   The chip body is a contenteditable span (auto-width via inline
   layout); the ✕ delete button sits inside the chip. Word-break
   keep-all on the text so long entries wrap at chip boundary
   instead of mid-character. */
.build-review-chips-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 4px 0 16px;
}
.build-review-chip {
  background: var(--surface-mid, #1F0E2C);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 999px;
  padding: 6px 8px 6px 12px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: var(--font-sans, system-ui);
  font-size: calc(12.5px * var(--text-scale));
  font-weight: 500;
  color: var(--text-on-deep, #FFF4DE);
  transition: background 0.12s ease, border-color 0.12s ease;
  max-width: 100%;
}
.build-review-chip:hover {
  background: var(--surface-hi, #2B143D);
  border-color: rgba(255, 255, 255, 0.14);
}
.build-review-chip-text {
  outline: none;
  min-width: 14px;
  white-space: nowrap;
  word-break: keep-all;
  overflow-wrap: normal;
  cursor: text;
}
.build-review-chip-text:focus {
  /* Focused chip gets a fire-orange caret without altering chip border. */
  color: var(--text-on-deep, #FFF4DE);
}
.build-review-chip-delete {
  appearance: none;
  background: transparent;
  border: none;
  width: 22px;
  height: 22px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--text-faint);
  font-size: calc(15px * var(--text-scale));
  line-height: 1;
  cursor: pointer;
  padding: 0;
  margin-left: 2px;
  transition: background 0.12s ease, color 0.12s ease;
}
.build-review-chip-delete:hover {
  background: rgba(255, 87, 34, 0.18);
  color: var(--fire, #FF5722);
}

/* Footer — JSX 410-432. Edit ghost LEFT + Save category fire CTA RIGHT.
   The default `.sheet-footer` already provides bottom-sticky + safe-
   area-inset padding; we just style the two children. */
.sheet-footer.build-preview-footer {
  display: flex;
  gap: 8px;
  padding: 12px 20px max(18px, env(safe-area-inset-bottom));
  border-top: 1px solid rgba(255, 255, 255, 0.06);
}
.build-preview-edit-btn {
  appearance: none;
  flex: 0 0 auto;
  padding: 0 22px;
  height: 50px;
  background: transparent;
  color: var(--text-on-deep, #FFF4DE);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: var(--radius-btn, 14px);
  font-family: var(--font-sans, system-ui);
  font-weight: 600;
  font-size: calc(14px * var(--text-scale));
  cursor: pointer;
  transition: background 0.12s ease, border-color 0.12s ease;
}
.build-preview-edit-btn:hover {
  background: rgba(255, 255, 255, 0.04);
  border-color: rgba(255, 255, 255, 0.22);
}
.build-preview-save-btn {
  flex: 1;
  height: 50px;
  background: var(--fire, #FF5722);
  color: #fff;
  border: none;
  border-radius: var(--radius-btn, 14px);
  font-family: var(--font-sans, system-ui);
  font-weight: 700;
  font-size: calc(14.5px * var(--text-scale));
  letter-spacing: -0.01em;
  cursor: pointer;
  transition: background 0.12s ease, box-shadow 0.18s ease;
  box-shadow: 0 4px 14px rgba(255, 87, 34, 0.30);
}
.build-preview-save-btn:hover {
  background: var(--fire-dim, var(--fire, #FF5722));
  box-shadow: 0 6px 18px rgba(255, 87, 34, 0.42);
}

@media (prefers-reduced-motion: reduce) {
  .build-preview-regenerate,
  .build-review-chip,
  .build-review-chip-delete,
  .build-preview-name-pill,
  .build-preview-edit-btn,
  .build-preview-save-btn { transition: none; }
}

/* ═══════════════════════════════════════════════════════════════════════
   B97.1 + B97.2 — Vote-Pantsy + Vote-Smarty parity chassis (2026-05-10)
   Sources:
   - JSX `_audit/_pantsy9/07c.5-point-at-pantsy/screens-vote.jsx`
   - Vote-Pantsy: lines 163-262
   - Vote-Smarty: lines 264-358
   ═══════════════════════════════════════════════════════════════════════ */

/* Category pill — JSX 180-192 (vote) + JSX 281-294 (best-clue).
   Centered, rgba bg + 1px stroke + 999 radius + 12px font + fgSoft color. */
.vote-category-pill-row {
  padding: 0 20px;
  display: flex;
  justify-content: center;
}
.vote-category-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.08);
  padding: 6px 12px;
  border-radius: 999px;
  font-family: var(--font-sans, -apple-system, system-ui, sans-serif);
  font-size: calc(12px * var(--text-scale));
  font-weight: 600;
  color: var(--text-soft, rgba(255, 244, 222, 0.7));
  letter-spacing: -0.01em;
}
.vote-category-pill .vcp-icon {
  font-size: calc(13px * var(--text-scale));
  line-height: 1;
}
.vote-category-pill .vcp-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 220px;
}

/* SVG question icons (replaces emoji `.vote-question-icon`).
   Wrapper is a span; SVG sits inline inside. Animation lives on the wrapper
   so the SVG geometry stays static. */
.vote-question-icon-svg {
  display: inline-block;
  flex: 0 0 auto;
  line-height: 0;
  width: 34px;
  height: 34px;
}
.vote-question-icon-svg.ballot {
  /* JSX 211-214 — wrapping span animates with tilt; transform-origin hugs
     the bottom of the box so the rocking motion looks anchored to the slot
     (not floaty). */
  animation: pantsy-vote-icon-tilt 2.2s ease-in-out infinite;
  transform-origin: 50% 80%;
}
.vote-question-icon-svg.star-shine {
  /* JSX 314-316 — outer wrapper does the shine (filter glow). */
  width: 32px;
  height: 32px;
  animation: pantsy-vote-star-shine 2.2s ease-in-out infinite;
}
.vote-question-icon-svg-inner.star-spin {
  /* JSX 318-321 — inner wrapper does the rotate-scale. */
  display: inline-block;
  animation: pantsy-vote-star-spin 3.2s ease-in-out infinite;
  transform-origin: 50% 50%;
  line-height: 0;
}
.vote-question-icon-svg svg {
  display: block;
}
@media (prefers-reduced-motion: reduce) {
  .vote-question-icon-svg.ballot,
  .vote-question-icon-svg.star-shine,
  .vote-question-icon-svg-inner.star-spin { animation: none !important; }
}

/* Row stagger via inline CSS variable — JSX 247 + 359.
   Each .vote-row gets `style="--vote-row-stagger: <n>s"`. Replaces the
   nth-child cap (which capped at 8 rows). */
.vote-screen .vote-list .vote-row,
.screen .vote-list .vote-row.smarty {
  animation: pantsy-vote-qpop 0.4s cubic-bezier(.2,.9,.3,1.2) var(--vote-row-stagger, 0s) both;
}
@media (prefers-reduced-motion: reduce) {
  .vote-screen .vote-list .vote-row,
  .screen .vote-list .vote-row.smarty { animation: none !important; }
}

/* Demoted host-advance CTA — not in design pack JSX, but kept for
   real-world game-flow (host-advance is the AFK-rescue lever). Demote
   per spec decision (b): smaller, dim, ghost. Surfaces in last 10s of
   the timer; render.js gates the mount. */
.vote-host-advance-btn {
  align-self: center;
  margin: 14px auto 4px;
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 999px;
  padding: 8px 16px;
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: calc(11px * var(--text-scale));
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint, rgba(255, 244, 222, 0.5));
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease;
}
.vote-host-advance-btn:hover {
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-soft, rgba(255, 244, 222, 0.7));
  border-color: rgba(255, 255, 255, 0.20);
}
.vote-host-advance-btn:active {
  transform: scale(0.98);
}

/* ═══════════════════════════════════════════════════════════════════════
   Bølge 112 (2026-05-11, ROADMAP #101) — Joiner conversion panel
   ═══════════════════════════════════════════════════════════════════════
   Replaces the legacy .first-lobby-hint banner with a conversion-focus
   chassis: PRIMARY = "Add to home" install flow CTA; SECONDARY = "How
   to play" quiet text-link; PLUS a 3-tip auto-rotating carousel above
   the CTAs. Renders only when `local._joinedDirectly === true` and not
   yet dismissed. Functional baseline only — visual polish flagged for
   design-port follow-up Cowork pass. */
.joiner-conversion-panel {
  position: relative;
  margin: 12px 0;
  padding: 16px 16px 12px;
  background: linear-gradient(160deg, rgba(255, 210, 74, 0.10) 0%, rgba(255, 87, 34, 0.04) 60%, rgba(15, 4, 24, 0.40) 100%);
  border: 1px solid rgba(255, 210, 74, 0.18);
  border-radius: 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.joiner-conversion-panel .jcp-eyebrow {
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold, #FFD24A);
}
.joiner-conversion-panel .jcp-dismiss {
  position: absolute;
  top: 8px;
  right: 8px;
  background: transparent;
  border: 0;
  color: var(--text-faint, rgba(255, 244, 222, 0.5));
  font-size: calc(20px * var(--text-scale));
  width: 28px;
  height: 28px;
  cursor: pointer;
  font-family: inherit;
}
.joiner-conversion-panel .jcp-carousel {
  background: rgba(0, 0, 0, 0.16);
  border-radius: 12px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.joiner-conversion-panel .jcp-tip-body {
  color: var(--text-on-deep, #FFF4DE);
  font-size: calc(14px * var(--text-scale));
  line-height: 1.4;
  min-height: calc(36px * var(--text-scale));
}
.joiner-conversion-panel .jcp-tip-dots {
  display: flex;
  gap: 6px;
  align-items: center;
}
.joiner-conversion-panel .jcp-tip-dot {
  background: rgba(255, 244, 222, 0.18);
  border: 0;
  border-radius: 999px;
  width: 8px;
  height: 8px;
  padding: 0;
  cursor: pointer;
  transition: background 0.18s ease, transform 0.18s ease;
}
.joiner-conversion-panel .jcp-tip-dot.active {
  background: var(--gold, #FFD24A);
  transform: scale(1.2);
}
.joiner-conversion-panel .jcp-cta-primary {
  /* Inherits .btn .btn-primary base — width:100% comes from sibling
     button rules already in style.css. Margin tightens the gap below
     the carousel without inflating the panel's overall height. */
  margin-top: 4px;
}
.joiner-conversion-panel .jcp-cta-secondary {
  background: transparent;
  border: 0;
  color: var(--text-soft, rgba(255, 244, 222, 0.75));
  font-size: calc(13px * var(--text-scale));
  font-family: inherit;
  text-decoration: underline;
  text-decoration-color: rgba(255, 244, 222, 0.30);
  cursor: pointer;
  padding: 4px 0 2px;
  align-self: center;
}

/* Bølge 142 (2026-05-12, ROADMAP #126): "How badges work" modal styles +
   the profile eyebrow tap-state. Inherits .profile-eyebrow typography
   via shared class so the tap surface reads as an affordance without
   visually overpowering the original heading rhythm. */
.profile-eyebrow-tap {
  background: transparent;
  border: 0;
  padding: 0 4px 0 4px;
  cursor: pointer;
  text-align: left;
  font: inherit;
  /* Match .profile-eyebrow exactly — the eyebrow IS the button now. */
  font-family: var(--font-mono);
  font-size: calc(11px * var(--text-scale));
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--text-faint);
  transition: color 0.15s ease, opacity 0.15s ease;
}
.profile-eyebrow-tap:hover,
.profile-eyebrow-tap:focus-visible {
  color: var(--text-soft);
  outline: none;
}
.profile-eyebrow-tap:active {
  opacity: 0.6;
}
.how-badges-body {
  display: flex;
  flex-direction: column;
  gap: 18px;
  padding: 4px 0 8px 0;
}
.how-badges-intro {
  font-size: calc(15px * var(--text-scale));
  line-height: 1.5;
  color: var(--text-soft, rgba(255, 244, 222, 0.85));
  padding: 0 4px;
}
.how-badges-section {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 0 4px;
}
.how-badges-section-header {
  font-family: var(--font-mono);
  font-size: calc(12px * var(--text-scale));
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--gold, #FFD24A);
}
.how-badges-section-body {
  font-size: calc(14px * var(--text-scale));
  line-height: 1.5;
  color: var(--text-soft, rgba(255, 244, 222, 0.85));
}
