/* Nocturne — design-system tokens and component classes. This file is the source of truth for the system's look; retune it here and see readme.md. */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');

:root {
  --color-bg: #000000;
  --color-surface: #232532;
  --color-text: #e9e9ed;
  --color-accent: #9184d9; /* review round 7 (Barron): the accent moves to
     the product's blurple — OKLCH hue 289.2, the hue of the app's own Pro
     accent (#9a8fe0, --om-accent-pro) — at the same lightness the steel
     accent held (L 0.660, so the documented ratios survive) and chroma
     in the product blurple's own range (its token sits at C 0.118; the
     accent takes 0.125, from the old steel's 0.030):
     the accent now reads as an accent rather than another neutral. */
  --color-accent-2: #a7a1db; /* the machine-derived stand-in follows: same
     hue, same L 0.734, chroma at the same 2:3 proportion it held */
  --color-divider: color-mix(in srgb, #e9e9ed 16%, transparent);
  --color-warn: oklch(0.74 0.15 55);

  /* Tonal ramps — generated in OKLCH on one shared lightness scale, so the
     same step of any role matches the others in visual value. */
  --color-neutral-100: #f3f5fe;
  --color-neutral-200: #e4e7f5;
  --color-neutral-300: #cfd3e5;
  --color-neutral-400: #b2b6ca;
  --color-neutral-500: #9397ab;
  --color-neutral-600: #75798c;
  --color-neutral-700: #595d6c;
  --color-neutral-800: #3f424d;
  --color-neutral-900: #292b31;

  --color-accent-100: #f5f4ff;
  --color-accent-200: #e7e5fe;
  --color-accent-300: #d2cefd;
  --color-accent-400: #b5abfc;
  --color-accent-500: #968ae0;
  --color-accent-600: #796cbf;
  --color-accent-700: #5d5294;
  --color-accent-800: #423a6a;
  --color-accent-900: #2b2741;

  --color-accent-2-100: #f5f4ff;
  --color-accent-2-200: #e7e5fe;
  --color-accent-2-300: #d2cefd;
  --color-accent-2-400: #b5afe8;
  --color-accent-2-500: #9690c9;
  --color-accent-2-600: #7972a9;
  --color-accent-2-700: #5c5783;
  --color-accent-2-800: #423e5d;
  --color-accent-2-900: #2b293a;

  /* Deck section-divider ground — review round 3: saturation as presence.
     Dividers take a saturated deep indigo (hue 277, the neutral ramp's own
     family; C 0.094 — written when the accent held C 0.030, before the
     round-7 blurple raised it past the ground's) with a lighter bloom and
     a ghost tint of the same hue, while the slide grounds stay
     desaturated. Deck-scale fills only — not interface colors. */
  --color-section: #262a60;
  --color-section-glow: #353b80;
  --color-section-ghost: #4c5397;

  --font-heading: "Inter", system-ui, sans-serif;
  --font-heading-weight: 500;
  --font-body: "Inter", system-ui, sans-serif;
  --font-mono: ui-monospace, "SF Mono", "Cascadia Code", "Consolas", monospace;

  --space-1: 2.8px;
  --space-2: 5.6px;
  --space-3: 8.4px;
  --space-4: 11.2px;
  --space-6: 16.8px;
  --space-8: 22.4px;

  --radius-sm: 4px;
  --radius-md: 8px;
  --radius-lg: 14px;

  /* Elevation — derived from the ground: soft ink-tinted shadows on a
     light theme, a hairline edge + ambient darkness on a dark one.
     The ground is pure black (#000), so a black ambient shadow would be
     literally invisible (same color as what's behind it) — the ambient
     component is instead a faint accent-tinted glow, which also keeps it
     visually consistent with the accent glow on the primary CTA. */
  --shadow-sm: 0 0 0 1px #3f424d;
  --shadow-md: 0 0 0 1px #595d6c, 0 6px 18px color-mix(in srgb, var(--color-accent) 16%, transparent);
  --shadow-lg: 0 0 0 1px var(--color-neutral-300), 0 16px 40px color-mix(in srgb, var(--color-accent) 22%, transparent);
}

body {
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
}
h1, h2, h3, h4 { font-family: var(--font-heading); font-weight: var(--font-heading-weight); }

.lighten{mix-blend-mode:lighten;background-color:transparent}

/* ══════════════════════════════════════════════════════════════════════════
   Components — built with the tokens above. Plain CSS
   on plain HTML: no JavaScript, no build step. Each class is documented in
   readme.md and demonstrated in foundations/ and components/.
   ══════════════════════════════════════════════════════════════════════ */

*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; font-size: 15px; line-height: 1.55; font-weight: 400; }
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  line-height: 1.12; letter-spacing: -0.015em; margin: 0 0 var(--space-2);
}
h1 { font-size: 42px; }
h2 { font-size: 32px; }
h3 { font-size: 25px; }
h4 { font-size: 20px; }
h5 { font-size: 16px; }
h6 { font-size: 13px; }
h6 { letter-spacing: 0.08em; text-transform: uppercase; }
p { margin: 0 0 var(--space-3); }
a { color: var(--color-accent); text-underline-offset: 3px; }
img { display: block; max-width: 100%; }
figure { margin: 0; }
figcaption {
  font-size: 11px; margin-top: var(--space-1);
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.text-muted { color: color-mix(in srgb, var(--color-text) 55%, transparent); }
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--color-accent) 30%, transparent); }

/* — rules — */
/* Rules fade to transparent at both ends instead of stopping cleanly — a
   Nocturne signature. The ramp is 48px an end (one deck baseline unit),
   painted from the same divider token. Freestanding rules fade; box
   outlines, in-control separators, and short accent marks stay solid. */
.hr {
  height: 1px; border: 0; margin: var(--space-4) 0;
  background: linear-gradient(to right,
    transparent, var(--color-divider) 48px,
    var(--color-divider) calc(100% - 48px), transparent);
}

/* — buttons — */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  cursor: pointer; text-decoration: none;
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 14px; line-height: 1.2; color: var(--color-text); /* matches the .input's 14px —
     the pair sits side by side in sign-up rows */
  background: transparent; border: 1px solid transparent;
  padding: var(--space-2) calc(var(--space-3) * 1.2);
  border-radius: var(--radius-md);
  transition: background 0.18s ease, border-color 0.18s ease, transform 0.18s ease, box-shadow 0.18s ease;
}
.btn svg { display: block; }
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-primary { color: var(--color-accent); border-color: var(--color-accent); }
.btn-primary:hover { background: color-mix(in srgb, var(--color-accent) 12%, transparent); }
.btn-primary:active { background: color-mix(in srgb, var(--color-accent) 22%, transparent); }
.btn-secondary { border-color: var(--color-divider); }
.btn-secondary:hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.btn-secondary:active { background: color-mix(in srgb, var(--color-text) 14%, transparent); }
.btn-ghost { color: var(--color-accent); padding-inline: var(--space-1); }
.btn-ghost:hover { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
.btn-ghost:active { background: color-mix(in srgb, var(--color-accent) 18%, transparent); }
.btn-icon { width: 36px; height: 36px; padding: 0; }
.btn-block { width: 100%; margin-top: var(--space-2); }

/* — forms — */
.field > label {
  display: block; font-size: 12px; margin-bottom: 5px;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}
.input {
  width: 100%; min-height: 36px; padding: 6px 10px; font: inherit;
  font-size: 14px; color: var(--color-text); caret-color: var(--color-accent);
  background: var(--color-surface);
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
}
.input:hover { border-color: color-mix(in srgb, var(--color-text) 45%, transparent); }
.input:focus-visible { border-color: var(--color-accent); outline-offset: 0; }
textarea.input { min-height: 90px; resize: vertical; }
.radio { display: inline-flex; align-items: center; gap: 8px; cursor: pointer; font-size: 14px; }
.radio input, .seg-opt input {
  position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none;
}
.radio .dot {
  width: 16px; height: 16px; flex: none; border-radius: 50%;
  border: 1.5px solid var(--color-divider);
}
.radio:hover .dot { border-color: var(--color-accent); }
.radio input:checked + .dot {
  border-color: var(--color-accent); background: var(--color-accent);
  box-shadow: inset 0 0 0 4px var(--color-bg);
}
.radio input:focus-visible + .dot { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.seg {
  display: inline-flex; overflow: hidden;
  border: 1px solid var(--color-divider); border-radius: var(--radius-md);
}
.seg-opt {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px; font-size: 13px; cursor: pointer;
}
.seg-opt + .seg-opt { border-left: 1px solid var(--color-divider); }
.seg-opt:has(input:checked) { color: var(--color-accent); box-shadow: inset 0 0 0 1px var(--color-accent); }
.seg-opt:not(:has(input:checked)):hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.seg-opt:has(input:focus-visible) { outline: 2px solid var(--color-accent); outline-offset: -2px; }

/* — cards — */
.card {
  display: flex; flex-direction: column; gap: var(--space-2);
  padding: var(--space-3); border-radius: var(--radius-md); background: var(--color-surface);
}
.card-kicker { font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-accent); }
.card-title {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 17px; line-height: 1.2;
}
.card-body { margin: 0; font-size: 13px; opacity: 0.8; flex: 1; }
.card-meta {
  display: flex; align-items: center; gap: 6px; font-size: 11px;
  color: color-mix(in srgb, var(--color-text) 50%, transparent);
}
.elev-sm { box-shadow: var(--shadow-sm); }
.elev-md { box-shadow: var(--shadow-md); }
.elev-lg { box-shadow: var(--shadow-lg); }

/* — tags — */
.tag {
  display: inline-flex; align-items: center; font-size: 11px;
  letter-spacing: 0.02em; padding: 3px 10px;
  border-radius: calc(var(--radius-md) * 0.75);
}
.tag-accent { background: var(--color-accent-800); color: var(--color-accent-100); }
.tag-accent-2 { background: var(--color-accent-2-800); color: var(--color-accent-2-100); }
.tag-neutral { background: var(--color-neutral-800); color: var(--color-neutral-100); }
.tag-outline { border: 1px solid var(--color-accent); color: var(--color-accent); }
/* Per-turn countdown, styled as the same outlined pill as the LIVE ROUND
   badge next to it — tabular-nums keeps the digits from jittering the
   pill's width as they count down. Ticks only while it's the player's
   turn (input enabled); warns in the last 10 seconds. */
.cuss-arena-timer { font-variant-numeric: tabular-nums; }
.cuss-arena-timer.is-warn { border-color: var(--color-warn); color: var(--color-warn); }

/* — navigation — */
.nav {
  display: flex; align-items: center; gap: var(--space-4); row-gap: var(--space-2);
  flex-wrap: wrap;
  padding: var(--space-3) var(--space-4);
  border-bottom: none;
}
/* Logo mark — sits immediately left of the wordmark, the nav's own
   gap (var(--space-4)) provides the spacing between the two. */
.nav-mark { display: block; height: 34px; width: auto; flex: none; }
.nav-brand {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 18px; margin-right: auto;
}
.nav a { color: inherit; text-decoration: none; font-size: 14px; }
.nav a:hover, .nav a[aria-current='page'] { color: var(--color-accent); }
/* Small outlined nav Chat button — reuses .btn-primary as-is (purple
   border, transparent fill, accent text). Same outline recipe as the big
   hero Chat button now, just at nav scale, so it still reads as visually
   secondary to it purely by size. */
.nav-cta { flex: none; }

/* — tables — */
.table { width: 100%; border-collapse: collapse; font-size: 14px; }
.table th {
  text-align: left; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
  padding: var(--space-2); border-bottom: 1px solid transparent; /* keeps layout; the row paints the fading rule */
}
.table td {
  padding: var(--space-2);
  border-bottom: 1px solid transparent;
}
/* Row rules as row-level strips so the end-fade spans the row, not each cell. */
.table thead tr {
  background: linear-gradient(to right,
    transparent, var(--color-divider) 48px,
    var(--color-divider) calc(100% - 48px), transparent) no-repeat bottom / 100% 1px;
}
.table tbody tr {
  background: linear-gradient(to right,
    transparent, color-mix(in srgb, var(--color-text) 8%, transparent) 48px,
    color-mix(in srgb, var(--color-text) 8%, transparent) calc(100% - 48px), transparent) no-repeat bottom / 100% 1px;
}
.table tbody tr:hover {
  /* the hover tint layers over the row rule, which keeps painting */
  background:
    linear-gradient(color-mix(in srgb, var(--color-text) 4%, transparent),
                    color-mix(in srgb, var(--color-text) 4%, transparent)) no-repeat 0 0 / 100% 100%,
    linear-gradient(to right,
      transparent, color-mix(in srgb, var(--color-text) 8%, transparent) 48px,
      color-mix(in srgb, var(--color-text) 8%, transparent) calc(100% - 48px), transparent) no-repeat bottom / 100% 1px;
}

/* — dialog — */
.dialog-backdrop {
  position: fixed; inset: 0; display: grid; place-items: center;
  padding: var(--space-4);
  background: color-mix(in srgb, var(--color-neutral-900) 50%, transparent);
}
.dialog {
  width: min(440px, 100%); display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4); border-radius: var(--radius-lg);
  background: var(--color-surface); box-shadow: var(--shadow-lg);
}
.dialog-title {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 20px;
}
.dialog-body { font-size: 14px; opacity: 0.85; }
.dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-2); }

/* ══════════════════════════════════════════════════════════════════════════
   Cussator landing — page-specific rules on top of the tokens/components above.
   ══════════════════════════════════════════════════════════════════════ */

html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

.cuss-page {
  --leading: 28px;
  --half: 14px;
  --edge: clamp(20px, 5vw, 72px);
  background:
    radial-gradient(1200px 720px at 82% -160px, color-mix(in srgb, var(--color-accent-900) 75%, transparent), transparent 60%),
    radial-gradient(1100px 800px at -10% 100%, color-mix(in srgb, black 30%, transparent), transparent 55%),
    var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  min-height: 100vh;
}
.cuss-wrap { max-width: 1200px; margin: 0 auto; padding: 0 var(--edge); }

.cuss-nav a { text-decoration: none; font-size: 14px; }

@keyframes cuss-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
.cuss-live-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--color-accent);
  animation: cuss-pulse 1.6s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) { .cuss-live-dot { animation: none; } }

.cuss-hero-grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(32px, 5vw, 80px); align-items: center;
  padding: var(--space-3) 0 var(--space-3);
  position: relative;
  z-index: 0;
}
/* Ambient court-line texture, homepage hero only — echoes the volley
   metaphor from the "Entering the Chat" animation. Kept to a near-invisible
   opacity on purpose; it's atmosphere, not a graphic. */
.cuss-hero-grid::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.08;
  background-repeat: no-repeat;
  background-position: center;
  background-size: 100% 100%;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 400'%3E%3Cg fill='none' stroke='%23e9e9ed' stroke-width='1.5'%3E%3Crect x='20' y='20' width='560' height='360'/%3E%3Cline x1='90' y1='20' x2='90' y2='380'/%3E%3Cline x1='510' y1='20' x2='510' y2='380'/%3E%3Cline x1='20' y1='200' x2='580' y2='200'/%3E%3Cline x1='90' y1='103' x2='510' y2='103'/%3E%3Cline x1='90' y1='297' x2='510' y2='297'/%3E%3Cline x1='300' y1='103' x2='300' y2='297'/%3E%3C/g%3E%3C/svg%3E");
}
.cuss-hero-copy h1 {
  font-size: clamp(36px, 4.4vw, 58px); line-height: 1.08;
  letter-spacing: -0.015em; margin: 0 0 0 -0.05em;
}
.cuss-hero-copy h1 span { display: block; }
.cuss-hero-copy p {
  font-size: 17px; line-height: var(--leading); max-width: 52ch;
  margin: var(--space-4) 0 0; color: var(--color-text);
}
.cuss-hero-actions {
  display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-3);
  margin: var(--space-4) 0 var(--space-4);
}
/* Bag's entry point sits immediately right of Chat, not stacked below it —
   its own row so the big primary CTA still reads as the one dominant
   action, with "How it works" staying on its own line beneath both. */
.cuss-hero-cta-row { display: flex; align-items: center; gap: var(--space-3); flex-wrap: wrap; }
/* Chat — outlined, not solid: black fill, purple border and text, same
   recipe .btn-primary already uses everywhere else, just scaled up. Keeps
   the same ambient purple glow it always had (an outline can still glow),
   referenced elsewhere in this file as "the homepage Chat button's glow". */
.cuss-cta-xl {
  /* Horizontal padding scales down with the viewport instead of staying a
     flat 72px a side — at 72px fixed, this plus its own text was tight or
     overflowing on ~320-375px phones (also applies to Bag, which shares
     this class — see the comment below). */
  font-size: 24px; padding: 26px clamp(24px, 8vw, 72px); border-width: 1.5px;
  background: var(--color-bg); color: var(--color-accent); border-color: var(--color-accent);
  box-shadow: 0 16px 40px color-mix(in srgb, var(--color-accent) 35%, transparent);
}
.cuss-cta-xl:hover { background: color-mix(in srgb, var(--color-accent) 12%, transparent); }
.cuss-cta-xl:active { background: color-mix(in srgb, var(--color-accent) 22%, transparent); }
/* Bag is styled as Chat's exact twin now (same .btn-primary / .cuss-cta-xl
   classes in the HTML) — no separate Bag-specific look here anymore. */

.cuss-demo {
  background: var(--color-bg); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-3); min-width: 0;
}
.cuss-demo-head { display: flex; align-items: center; gap: var(--space-2); }
.cuss-demo-timer {
  margin-left: auto; font-size: 11px;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
  font-feature-settings: 'tnum' 1;
}
.cuss-demo-motion {
  margin: 0; font-size: 12px; font-style: italic;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
}
.cuss-demo-label {
  margin: 0 0 4px; font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.cuss-demo-speech { margin: 0; font-size: 16px; line-height: 1.5; }
.cuss-demo-speech span { transition: color 0.25s ease; }

.cuss-ai-card {
  background: color-mix(in srgb, var(--color-warn) 14%, var(--color-surface));
  border-radius: var(--radius-md); padding: var(--space-3);
}
.cuss-ai-card-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); margin-bottom: 4px; }
.cuss-ai-label { margin: 0; font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--color-warn); }
.cuss-ai-card p.cuss-ai-body { margin: 0; font-size: 14px; line-height: 1.5; }
.cuss-simplify-btn {
  font-family: inherit; font-size: 10.5px; letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--color-accent); background: transparent; cursor: pointer; white-space: nowrap;
  border: 1px solid color-mix(in srgb, var(--color-accent) 45%, transparent); border-radius: 999px;
  padding: 3px 9px; transition: background 0.15s ease, opacity 0.15s ease, color 0.2s ease, border-color 0.2s ease;
}
.cuss-simplify-btn:hover:not(:disabled) { background: color-mix(in srgb, var(--color-accent) 14%, transparent); }
.cuss-simplify-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.cuss-simplify-btn.is-done { color: color-mix(in srgb, var(--color-text) 55%, transparent); border-color: var(--color-divider); }

.cuss-judge {
  display: flex; flex-direction: column; gap: 6px; padding-top: var(--space-2);
  border-top: 1px solid var(--color-divider);
  opacity: 0; transition: opacity 0.35s ease;
}
.cuss-judge.is-visible { opacity: 1; }
/* Collapses out of the flex flow entirely before the first turn resolves —
   otherwise its (invisible but full-height) box sits between the transcript
   and the legend/input, breaking the uniform gap rhythm described above. */
.cuss-judge[hidden] { display: none; }
.cuss-judge-label {
  margin: 0 0 2px; font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
/* Itemizes Logic/Precision/Delivery the same way the homepage's numbered
   rows are itemized — a fading rule between each, not just a bare stack of
   rows. Wraps the existing row+hint pair; nothing inside it changed. */
.cuss-judge-item {
  display: flex; flex-direction: column; padding-top: 6px;
  background: linear-gradient(to right, transparent, var(--color-neutral-800) 4px calc(100% - 4px), transparent) no-repeat top / 100% 1px;
}
.cuss-judge-item:first-child { background-image: none; padding-top: 0; }
/* Arena round screen goes fully line-free (unlike the homepage demo card
   above, which keeps its original look) — the top rule and the fading
   dividers between Logic/Precision/Delivery are dropped, relying on the
   existing gap/padding alone for rhythm instead of a drawn line. */
#cuss-arena-judge { border-top: none; }
#cuss-arena-judge .cuss-judge-item { background-image: none; }
.cuss-judge-row { display: flex; align-items: center; gap: 8px; }
.cuss-judge-row span:first-child { font-size: 12px; width: 64px; flex: none; cursor: help; }
.cuss-judge-track { flex: 1; height: 6px; border-radius: 99px; background: var(--color-neutral-800); overflow: hidden; }
.cuss-judge-fill { height: 100%; width: 0%; background: var(--color-accent); transition: width 0.1s linear; }
.cuss-judge-fill.is-warn { background: var(--color-warn); }
.cuss-judge-val { font-size: 11px; width: 28px; text-align: right; font-feature-settings: 'tnum' 1; }

/* Credibility (HP) bars get real visual weight — thicker track, a color
   shift toward danger as they drop, and a brief pulse whenever the number
   actually changes. Scoped under .cuss-arena-health so the Judge panel's
   bars (deliberately secondary — "feedback only") stay untouched; they
   share the same .cuss-judge-track/-fill/-val classes otherwise. */
/* overflow: visible (overriding the base track's overflow:hidden) so the
   fill's glow below can actually bleed outward instead of being clipped
   at the track edge — the fill rounds its own ends to match the track's
   pill shape instead, so it doesn't need the track to clip it square. */
.cuss-arena-health .cuss-judge-track { height: 12px; overflow: visible; }
.cuss-arena-health .cuss-judge-fill {
  position: relative; border-radius: 99px;
  background: var(--color-accent); color: var(--color-accent);
  transition: width 0.5s cubic-bezier(.22,.61,.36,1), background 0.3s ease, color 0.3s ease, box-shadow 0.3s ease;
  /* Ambient glow in whichever color the bar currently is (accent, warn, or
     the hp-warning/hp-critical danger tiers below) — same color-mix-with-
     currentColor technique as the hit pulse below and the same idea as the
     homepage Chat button's glow, just a symmetric blur rather than that
     button's directional drop-shadow (a 16px-down shadow reads as a
     shadow, not a glow, on something this thin). Turned up to be clearly
     visible at a glance, not just a faint edge softening. */
  box-shadow: 0 0 22px 4px color-mix(in srgb, currentColor 75%, transparent);
}
.cuss-arena-health .cuss-judge-fill.is-warn { background: var(--color-warn); color: var(--color-warn); }
.cuss-arena-health .cuss-judge-fill.is-hp-warning { background: oklch(0.78 0.16 80); color: oklch(0.78 0.16 80); }
.cuss-arena-health .cuss-judge-fill.is-hp-critical { background: oklch(0.63 0.22 25); color: oklch(0.63 0.22 25); }
.cuss-arena-health .cuss-judge-val { font-size: 13px; font-weight: 700; transition: color 0.3s ease; }
.cuss-arena-health .cuss-judge-val.is-hp-warning { color: oklch(0.78 0.16 80); }
.cuss-arena-health .cuss-judge-val.is-hp-critical { color: oklch(0.63 0.22 25); }

@keyframes cuss-hp-pulse {
  0% { box-shadow: 0 0 0 0 currentColor; }
  35% { box-shadow: 0 0 16px 2px currentColor; }
  100% { box-shadow: 0 0 0 0 currentColor; }
}
.cuss-arena-health .cuss-judge-fill.is-flash { animation: cuss-hp-pulse 0.7s ease-out; }
/* A drop (filler hit or a "bad"/"solid" verdict costing this side) always
   pulses in the filler-orange used for highlighted words in the transcript,
   regardless of which HP tier color the bar itself currently is — without
   this, a small hit while still above 50 HP pulsed in the ordinary accent
   purple, which read as neutral/positive rather than "something just
   landed." Gains (a solid-argument self-heal) keep the tier-color pulse,
   since those aren't a hit. See updateHealthDisplay() in script.js. */
.cuss-arena-health .cuss-judge-fill.is-flash.is-hit { animation-name: cuss-hp-pulse-hit; }
@keyframes cuss-hp-pulse-hit {
  0% { box-shadow: 0 0 0 0 var(--color-warn); }
  35% { box-shadow: 0 0 18px 3px var(--color-warn); }
  100% { box-shadow: 0 0 0 0 var(--color-warn); }
}
@keyframes cuss-hp-val-pulse {
  0% { transform: scale(1); }
  35% { transform: scale(1.4); }
  100% { transform: scale(1); }
}
.cuss-arena-health .cuss-judge-val.is-flash { display: inline-block; animation: cuss-hp-val-pulse 0.5s ease-out; }
/* Per-metric explanations under the live Judge panel — purely informational,
   these never feed back into Credibility (that's driven only by the per-word tags
   and the AI's per-turn verdict; folding the Judge score in too would
   double-count the same signal). */
.cuss-judge-note {
  margin: -2px 0 2px; font-size: 10px; font-style: italic;
  color: color-mix(in srgb, var(--color-text) 45%, transparent);
}
.cuss-judge-hint {
  margin: -3px 0 1px 72px; font-size: 10.5px; line-height: 1.3;
  color: color-mix(in srgb, var(--color-text) 50%, transparent);
}

.cuss-eyebrow {
  position: relative; display: block; font-size: 13px; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--color-accent); margin: 0 0 calc(var(--leading) - var(--half));
}

/* Word of the Day — a slim full-width band directly under the hero, so it
   lands in the first viewport instead of a tall centered block requiring a
   scroll. The reveal is a horizontal sliding reel (case-opening style):
   see buildWordReel() in script.js. Mechanic (sequence, easing, blur,
   edge-mask, "only the landed item is styled up") is adapted from a
   reference implementation; everything visual below is Cussator's own
   tokens — accent purple for the landed word, the same muted-gray pattern
   used everywhere else for the definition, --color-text for the top/bottom
   rule (needs to read against bare page background, not a surface panel).
   No new colors, no borrowed fonts. */
.cuss-wotd {
  width: 100%; padding: var(--space-2) 0;
  border-top: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent);
  border-bottom: 1px solid color-mix(in srgb, var(--color-text) 12%, transparent);
  display: flex; flex-direction: column; gap: 4px;
}
.cuss-wotd .cuss-eyebrow { margin: 0; }
.cuss-wotd-reel {
  width: 100%; height: 52px; overflow: hidden; position: relative;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, black 12%, black 88%, transparent 100%);
  mask-image: linear-gradient(to right, transparent 0%, black 12%, black 88%, transparent 100%);
}
.cuss-wotd-track { display: flex; height: 100%; will-change: transform; }
.cuss-wotd-item {
  flex: 0 0 190px; width: 190px; height: 100%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-heading); font-size: 15px; letter-spacing: 0.01em;
  color: color-mix(in srgb, var(--color-text) 38%, transparent);
  transition: color 0.5s ease, font-size 0.5s ease, transform 0.5s ease;
}
.cuss-wotd-item.is-landed {
  color: var(--color-accent); font-size: clamp(22px, 2.6vw, 28px);
  font-weight: var(--font-heading-weight); transform: scale(1.05);
}
.cuss-wotd-def {
  margin: 0; max-width: 52ch; font-size: 14px; opacity: 0;
  transition: opacity 0.4s ease; color: color-mix(in srgb, var(--color-text) 65%, transparent);
}
.cuss-wotd-def.is-visible { opacity: 1; }

.cuss-feature {
  display: grid; grid-template-columns: minmax(64px, 140px) minmax(0, 360px) minmax(0, 1fr);
  gap: var(--leading) clamp(24px, 4vw, 64px); align-items: baseline;
  padding: calc(1.4 * var(--leading)) 0;
  background: linear-gradient(to right, transparent, var(--color-neutral-800) 48px calc(100% - 48px), transparent) no-repeat top / 100% 1px;
}
.cuss-feature:first-child { background: none; }
.cuss-feature-num {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 15px;
  color: var(--color-accent); margin: 0; font-feature-settings: 'tnum' 1;
}
.cuss-feature h2 { font-size: 24px; margin: 0; letter-spacing: -0.01em; }
.cuss-feature-body {
  font-size: 15.5px; line-height: var(--leading); margin: 0;
  color: color-mix(in srgb, var(--color-text) 78%, transparent); max-width: 52ch;
}
/* Was accidentally sharing the .cuss-scars class with the real full-screen
   Vocabulary Scars overlay below (position:fixed; opacity:0 by default),
   which made this decorative preview invisible and pulled out of the grid
   entirely. Renamed so the two never collide again. */
.cuss-scars-preview { display: flex; flex-direction: column; gap: var(--space-3); }
.cuss-scars-tags { display: flex; gap: 6px; flex-wrap: wrap; }
.cuss-scars-tags .tag { background: color-mix(in srgb, var(--color-warn) 22%, var(--color-surface)); color: var(--color-warn); }

.cuss-steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(20px, 3vw, 32px); }
.cuss-step-num {
  font-family: var(--font-heading); font-size: 15px; color: var(--color-accent);
  margin: 0 0 8px; font-feature-settings: 'tnum' 1;
}
.cuss-steps h3 { font-size: 17px; margin: 0 0 6px; }
.cuss-steps p { font-size: 14px; line-height: 1.5; margin: 0; color: color-mix(in srgb, var(--color-text) 78%, transparent); }

.cuss-footer {
  padding: calc(1.6 * var(--leading)) 0; font-size: 13px;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
  display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); justify-content: space-between;
}
.cuss-footer-links { display: flex; gap: var(--space-3); }
.cuss-footer-links a { color: inherit; }
.cuss-footer-links a:hover { color: var(--color-accent); }

/* Terms / Privacy — plain, readable legal copy fit to the site's existing
   dark theme; deliberately not styled beyond basic typography and rhythm. */
.cuss-legal { max-width: 68ch; padding: calc(2 * var(--leading)) 0 calc(3 * var(--leading)); }
.cuss-legal h1 { margin-bottom: var(--space-2); }
.cuss-legal-updated {
  font-size: 13px; margin: 0 0 calc(1.5 * var(--leading));
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.cuss-legal h2 { font-size: 19px; margin: calc(1.5 * var(--leading)) 0 var(--space-2); }
.cuss-legal p, .cuss-legal li { font-size: 15px; line-height: var(--leading); color: color-mix(in srgb, var(--color-text) 85%, transparent); }
.cuss-legal ul { padding-left: 1.2em; margin: var(--space-2) 0; }
.cuss-legal a { color: var(--color-accent); }

@media (max-width: 900px) {
  .cuss-hero-grid { grid-template-columns: 1fr !important; }
  .cuss-feature { grid-template-columns: 1fr !important; }
  .cuss-steps { grid-template-columns: 1fr !important; }
}

/* ══════════════════════════════════════════════════════════════════════════
   Debate arena — the live-round screen opened from "Start round".
   ══════════════════════════════════════════════════════════════════════ */

/* Full-screen dedicated round view, not a popup over the page — the arena
   fills the viewport and owns the whole screen while a round is live. */
.cuss-arena {
  position: fixed; inset: 0; z-index: 100; display: flex; align-items: stretch; justify-content: center;
  padding: 0;
  background: var(--color-bg);
  opacity: 0; pointer-events: none; transition: opacity 0.2s ease;
}
.cuss-arena.is-open { opacity: 1; pointer-events: auto; }
.cuss-arena-inner {
  position: relative;
  /* Full-bleed — no centered max-width column. Header, motion, HP bars,
     transcript and input all fill this the entire way across since none
     of them set their own width/max-width (only the choose-your-side
     controls further down keep a centered, narrower measure of their
     own, deliberately, for readability of that one screen). */
  width: 100%; height: 100%; max-height: 100vh;
  /* Same gap token as .cuss-arena-transcript's internal gap (see below) —
     one consistent rhythm the whole way down: head → motion → HP bars →
     transcript (→ avatar row → prompt) → legend → input. */
  display: flex; flex-direction: column; gap: var(--space-4);
  background: var(--color-bg); border-radius: 0; box-shadow: none;
  padding: var(--space-4) var(--edge); overflow: hidden;
}
/* Stacked above the stance-select (z-index: 10) and round-over (z-index: 5)
   overlays so the close button stays clickable no matter which screen is
   showing — without this it sits at the default stacking level and the
   overlay's own layer (positioned + z-indexed) intercepts the click even
   though the header is still faintly visible through it. */
.cuss-arena-head {
  position: relative; z-index: 20;
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
}
.cuss-arena-head-info { display: flex; align-items: center; gap: var(--space-2); flex-wrap: wrap; }
/* Right-hand cluster mirrors the left one, same even left/right split the
   bottom legend row and the avatar row also use — keeps the header from
   reading as left-heavy with a bare close button stranded on the far right. */
.cuss-arena-head-right { display: flex; align-items: center; gap: var(--space-2); flex: none; }
/* Guaranteed minimum clearance from the arena's own right edge — without
   this, the close button sits exactly on the same boundary any inner
   overlay's scrollbar renders at (e.g. .cuss-result-transition when its
   content overflows), which reads as the button being flush against the
   scrollbar and cramped to click. Small and permanent, not conditional on
   whether a scrollbar actually happens to be showing. */
#cuss-arena-close { margin-right: 6px; }
/* Reflects the side the player already picked (see chooseStance()) — hidden
   until then. Same blue/red as the stance-select buttons and pre-round
   avatars for one consistent affirm/negate color language. Fades in
   (is-visible, added a frame after unhiding — see chooseStance()) rather
   than just popping into the header the instant a side is picked. */
.cuss-arena-side { opacity: 0; transition: opacity 0.2s ease; }
.cuss-arena-side.is-visible { opacity: 1; }
.cuss-arena-side.is-affirm { border-color: oklch(0.72 0.15 250); color: oklch(0.72 0.15 250); }
.cuss-arena-side.is-negate { border-color: oklch(0.63 0.22 25); color: oklch(0.63 0.22 25); }
.cuss-arena-side[hidden] { display: none; }
/* Keeps product identity present during an actual round, not just on the
   marketing page — same weight/family as .nav-brand, just smaller since it
   shares the row with the LIVE ROUND badge and timer. */
.cuss-arena-brand {
  font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 14px; margin-right: 2px; color: var(--color-text);
}
.cuss-arena-motion { margin: 0; font-size: 12px; font-style: italic; color: color-mix(in srgb, var(--color-text) 60%, transparent); }
.cuss-arena-transcript {
  /* Top-aligned with the same uniform gap used for every other row in this
     panel (see .cuss-arena-inner) — deliberately NOT vertically centered,
     so the HP bars → avatar row → prompt → input rhythm reads as one
     consistent stack instead of floating in the middle of the remaining
     space above a short transcript. */
  flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: var(--space-4);
  padding-right: 4px; min-height: 120px; position: relative;
}
/* Reads as an active prompt, not passive filler copy — the "YOUR TURN"
   badge reuses the exact .tag.tag-outline styling the "LIVE ROUND" badge
   uses, so the two read as the same visual language. */
.cuss-arena-empty {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px 10px;
  font-size: 13px; color: color-mix(in srgb, var(--color-text) 68%, transparent); margin: 0;
}
.cuss-arena-prompt-badge { flex: none; font-weight: 600; }
/* Pre-round anchor — foreshadows the left/right layout the first AI card
   and user bubble will actually use (.cuss-bubble-ai / .cuss-bubble-user),
   so the empty transcript reads as an intentional, populated layout rather
   than blank space. Removed the moment the first bubble is added. Same
   even left/right split as the bottom legend row and the header — AI
   pinned left, player pinned right, both on one horizontal line. */
.cuss-transcript-anchor { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); opacity: 0.65; }
.cuss-anchor-row { display: flex; align-items: center; gap: 8px; max-width: 46%; }
.cuss-anchor-right { flex-direction: row-reverse; }
.cuss-anchor-avatar {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 26px; height: 26px; border-radius: 50%; border: 1.5px solid currentColor;
  font-size: 11px; font-weight: 700; font-family: var(--font-heading);
  color: color-mix(in srgb, var(--color-text) 50%, transparent);
}
.cuss-anchor-avatar.is-affirm { color: oklch(0.72 0.15 250); }
.cuss-anchor-avatar.is-negate { color: oklch(0.63 0.22 25); }
.cuss-anchor-label { font-size: 12px; letter-spacing: 0.02em; color: color-mix(in srgb, var(--color-text) 50%, transparent); }
.cuss-bubble-user {
  align-self: flex-end; max-width: 88%; background: var(--color-surface);
  border-radius: var(--radius-md); padding: var(--space-3); font-size: 14px; line-height: 1.5; margin: 0;
}
/* Entrance for both message types — no ruled line (the arena is line-free,
   see .cuss-arena-transcript above), just motion. The player's own bubble
   gets a plain settle (fade + quick rise) since it's their own words
   appearing, not a reveal. The AI card (aliased .cuss-bubble-ai) gets a
   distinct, punchier pop — scaling up from slightly small rather than
   rising from below — so an incoming rebuttal reads as a different kind of
   event than the player's own bubble, not the same motion mirrored. Kept
   short — this fires on every turn, so it needs to feel instant. */
.cuss-bubble-user {
  opacity: 0; transform: translateY(6px);
  transition: opacity 0.22s ease, transform 0.22s ease;
}
.cuss-bubble-user.is-visible { opacity: 1; transform: translateY(0); }
.cuss-ai-card {
  opacity: 0; transform: scale(0.92);
  transition: opacity 0.24s ease-out, transform 0.24s cubic-bezier(.2,1.4,.4,1);
}
.cuss-ai-card.is-visible { opacity: 1; transform: scale(1); }
@media (prefers-reduced-motion: reduce) {
  .cuss-bubble-user, .cuss-ai-card { transition: opacity 0.15s ease; transform: none; }
}
/* Highlight tiers — filler orange, curse red, connective blue, vocab green.
   Each gets a soft text-shadow glow in its own color, same intensity as the
   Chat button's glow (color-mix at ~35% into a blur, no hard edge). */
.cuss-weak {
  color: var(--color-warn); text-decoration: underline wavy var(--color-warn); font-weight: 600;
  text-shadow: 0 0 8px color-mix(in srgb, var(--color-warn) 35%, transparent);
}
.cuss-weak-light { text-decoration-style: dotted; }
.cuss-curse {
  color: oklch(0.63 0.22 25); text-decoration: underline wavy oklch(0.63 0.22 25); font-weight: 700;
  text-shadow: 0 0 8px color-mix(in srgb, oklch(0.63 0.22 25) 35%, transparent);
}
.cuss-connective {
  color: oklch(0.72 0.15 250); font-weight: 600;
  text-shadow: 0 0 8px color-mix(in srgb, oklch(0.72 0.15 250) 35%, transparent);
}
.cuss-weak, .cuss-curse, .cuss-connective { transition: color 0.2s ease; }
.cuss-vocab {
  position: relative; display: inline-block; color: oklch(0.75 0.13 150); font-weight: 600;
  text-shadow: 0 0 8px color-mix(in srgb, oklch(0.75 0.13 150) 35%, transparent);
}
.cuss-vocab::before {
  content: "vocab"; position: absolute; left: 50%; top: -0.4em; transform: translateX(-50%);
  font-size: 8px; line-height: 1; letter-spacing: 0.05em; text-transform: uppercase;
  color: oklch(0.75 0.13 150); opacity: 0.8; white-space: nowrap; pointer-events: none;
}
.cuss-bubble-ai { align-self: flex-start; max-width: 88%; }
.cuss-arena-typing[hidden] { display: none; }
/* Visible motion for the whole wait — Chair-difficulty replies can take
   15-20+ seconds, and a static "typing…" label with no animation reads as
   frozen/broken over that long. Three dots pulsing in sequence, same
   pattern as chat-app typing indicators. */
.cuss-typing-dots { display: inline-flex; gap: 3px; margin-left: 5px; vertical-align: middle; }
.cuss-typing-dots span {
  width: 4px; height: 4px; border-radius: 50%; background: currentColor;
  display: inline-block; opacity: 0.3; animation: cuss-typing-dot 1.2s ease-in-out infinite;
}
.cuss-typing-dots span:nth-child(2) { animation-delay: 0.2s; }
.cuss-typing-dots span:nth-child(3) { animation-delay: 0.4s; }
@keyframes cuss-typing-dot {
  0%, 60%, 100% { opacity: 0.3; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-2px); }
}
@media (prefers-reduced-motion: reduce) {
  .cuss-typing-dots span { animation: none; opacity: 0.8; }
}
.cuss-arena-error { color: var(--color-warn); font-size: 13px; margin: 0; }

/* Color-legend key — visible from the start of every round (static, not
   tied to any round state) so new players learn the highlight system by
   reading it, not by losing Credibility first. Colors match the live
   highlight classes exactly: .cuss-weak (filler), .cuss-vocab, .cuss-curse. */
.cuss-color-legend { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; padding: 0 2px 6px; }
.cuss-legend-item {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.cuss-legend-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.cuss-legend-dot.is-filler { background: var(--color-warn); }
.cuss-legend-dot.is-vocab { background: oklch(0.75 0.13 150); }
.cuss-legend-dot.is-penalty { background: oklch(0.63 0.22 25); }

/* Word Economy token budget — pinned in the bottom-right corner of the
   input bar itself, right where the player is typing. Ticks down live
   (see checkTokenBudget() in script.js) as they type, same event as the
   highlighter; turns critical-red in the last 10% of the pool as a quiet
   warning before the auto-loss actually fires. Styled like a small CLI
   readout (monospace, muted grey, not accent purple) rather than a
   game-UI label, with the lips mark recolored to match via currentColor +
   fill="currentColor" on its paths (the standalone cussator-mark.svg
   hardcodes purple internally, so an <img> of it couldn't be retinted
   from CSS). pointer-events:none so it never blocks clicking/selecting
   the text underneath; .cuss-highlight-input's bottom padding keeps typed
   text from ever reaching this corner in the first place. */
.cuss-token-budget {
  position: absolute; right: 10px; bottom: 5px; pointer-events: none; z-index: 1;
  display: inline-flex; align-items: center; gap: 4px;
  font-family: var(--font-mono); font-size: 11px; font-variant-numeric: tabular-nums;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
  transition: color 0.2s ease;
}
.cuss-token-mark { width: 13px; height: auto; flex: none; color: inherit; }
.cuss-token-arrow { font-size: 10px; }
.cuss-token-val { font-weight: 700; color: var(--color-text); transition: color 0.2s ease; }
.cuss-token-budget.is-critical, .cuss-token-budget.is-critical .cuss-token-val { color: oklch(0.63 0.22 25); }

.cuss-arena-form {
  display: flex; gap: var(--space-3); align-items: flex-end;
  padding-top: var(--space-3);
}

/* Insert-from-Bag — a text-insertion shortcut, styled as a quiet square
   twin of the Enter-key send button so the two read as the input row's
   pair of controls, not one primary action and one random extra. */
.cuss-bag-insert-wrap { position: relative; flex: none; }
.cuss-bag-insert-btn {
  width: 42px; height: 42px; flex: none; border-radius: var(--radius-sm); padding: 0;
  background: transparent; color: var(--color-accent);
  border: 1px solid color-mix(in srgb, var(--color-accent) 45%, transparent);
}
.cuss-bag-insert-btn:hover { background: color-mix(in srgb, var(--color-accent) 12%, transparent); }
.cuss-bag-insert-icon { width: 20px; height: auto; }
.cuss-bag-insert-popover {
  /* width: min(220px, ...) instead of a flat 220px — anchored at left:0
     with nothing clamping it to the viewport, a fixed 220px could clip or
     overflow past the screen edge on narrow layouts depending on where
     the insert button sits. */
  position: absolute; left: 0; bottom: calc(100% + 8px); z-index: 20;
  width: min(220px, calc(100vw - 2 * var(--space-4))); max-height: 260px; overflow-y: auto;
  background: var(--color-surface); border-radius: var(--radius-md);
  border: 1px solid color-mix(in srgb, var(--color-accent) 35%, transparent);
  padding: var(--space-2); box-shadow: var(--shadow-lg);
}
.cuss-bag-insert-popover-title {
  margin: 0 0 4px; padding: 0 6px; font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.cuss-bag-insert-list { display: flex; flex-direction: column; gap: 2px; }
.cuss-bag-insert-word {
  display: block; width: 100%; text-align: left; font: inherit; font-size: 13px;
  background: transparent; border: none; border-radius: var(--radius-sm); padding: 6px 6px;
  color: oklch(0.75 0.13 150); cursor: pointer;
}
.cuss-bag-insert-word:hover { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }

/* The "pulling a card" animation — a transient, JS-created card (see
   playCardPullAnimation() in script.js) that appears at the Bag-insert
   button, flips over like a card being drawn to reveal the word (back
   face reuses the same lips mark used elsewhere in the app), then flies
   into the argument input and fades — purely cosmetic, blocks nothing,
   and the actual word insertion happens right as it finishes. */
.cuss-card-pull {
  position: fixed; z-index: 300; pointer-events: none;
  perspective: 600px;
  opacity: 0; transform: scale(0.5);
  transition: transform 0.22s ease, opacity 0.22s ease, left 0.35s cubic-bezier(.4,0,1,1), top 0.35s cubic-bezier(.4,0,1,1);
}
.cuss-card-pull.is-visible { opacity: 1; transform: scale(1); }
/* Matches .cuss-card-pull-inner's own flip duration below so the outer
   drift-up-and-grow reads as one combined motion with the flip, not two
   mistimed movements. */
.cuss-card-pull.is-flipped {
  transition: transform 0.42s cubic-bezier(.34,1.56,.64,1), opacity 0.22s ease,
    left 0.35s cubic-bezier(.4,0,1,1), top 0.35s cubic-bezier(.4,0,1,1);
}
.cuss-card-pull.is-flying { opacity: 0; transition: transform 0.38s cubic-bezier(.4,0,1,1), opacity 0.32s ease 0.06s, left 0.38s cubic-bezier(.4,0,1,1), top 0.38s cubic-bezier(.4,0,1,1); }
.cuss-card-pull-inner {
  position: relative; width: 100%; height: 100%; transform-style: preserve-3d;
  transition: transform 0.42s cubic-bezier(.34,1.56,.64,1);
}
.cuss-card-pull.is-flipped .cuss-card-pull-inner { transform: rotateY(180deg); }
.cuss-card-pull-face {
  position: absolute; inset: 0; backface-visibility: hidden;
  display: flex; align-items: center; justify-content: center; padding: var(--space-3);
  border-radius: var(--radius-md);
  box-shadow: 0 10px 28px color-mix(in srgb, var(--color-accent) 35%, transparent);
}
.cuss-card-pull-back {
  color: var(--color-accent);
  background: color-mix(in srgb, var(--color-accent) 16%, var(--color-surface));
  border: 1px solid color-mix(in srgb, var(--color-accent) 50%, transparent);
}
.cuss-card-pull-back svg { width: 36px; height: auto; }
.cuss-card-pull-front {
  transform: rotateY(180deg);
  background: color-mix(in srgb, oklch(0.75 0.13 150) 14%, var(--color-surface));
  border: 1px solid color-mix(in srgb, oklch(0.75 0.13 150) 50%, transparent);
}
.cuss-card-pull-front-word {
  font-size: 15px; font-weight: 700; text-align: center; color: oklch(0.75 0.13 150);
}
@media (prefers-reduced-motion: reduce) {
  .cuss-card-pull, .cuss-card-pull.is-flying, .cuss-card-pull-inner { transition: none; }
}

.cuss-highlight-wrap {
  /* Borderless, same --color-bg as the rest of the page — spacing alone
     (var(--space-4) gap above, from .cuss-arena-inner) separates the round
     content from the input now, not a ruled line or a boxed panel. */
  position: relative; flex: 1; min-height: 78px; border-radius: var(--radius-md);
  background: var(--color-bg);
}
/* Send — styled like a physical keyboard Enter key (rectangular keycap,
   small corner radius, the return-arrow glyph a real Enter key shows)
   rather than a circular chat-app send button — reinforces that pressing
   the actual Enter key does the same thing. Solid accent purple, same
   color as .cuss-cta-xl (the Chat CTA), but far smaller/quieter. */
.cuss-send-btn {
  width: 68px; height: 42px; flex: none; border-radius: var(--radius-sm); padding: 0;
  background: var(--color-accent); color: var(--color-bg);
  border: 2px dashed var(--color-bg);
  box-shadow: 0 0 14px 2px color-mix(in srgb, var(--color-accent) 40%, transparent);
}
.cuss-send-btn:hover { background: var(--color-accent-2); }
.cuss-send-btn:active { background: var(--color-accent); }
.cuss-send-glyph { font-size: 20px; line-height: 1; }
/* Fires when Enter is pressed on the textarea (see script.js) — the button
   itself never receives that keystroke, so without this it would sit
   there inert while a physical key visibly depresses. Also plays on a
   real mouse click, same class, since :active alone doesn't leave a
   visible trace once the mouse button is released. Pushed well past a
   micro-interaction (deep scale-down + a small overshoot on the way back)
   so it reads unmistakably as "this key was just pressed" even without a
   mouse involved. Duration must match SEND_KEY_PRESS_DURATION in script.js. */
@keyframes cuss-send-key-press {
  0% { transform: scale(1); }
  35% { transform: scale(0.72); }
  70% { transform: scale(1.08); }
  100% { transform: scale(1); }
}
.cuss-send-btn.is-pressed { animation: cuss-send-key-press 0.32s ease; }
.cuss-highlight-layer, .cuss-highlight-input {
  /* Bottom padding reserves room for the token counter chip pinned in this
     corner (see .cuss-token-budget) so typed text never runs under it. */
  position: absolute; inset: 0; margin: 0; padding: 16px 10px 22px; font: inherit; font-size: 14px; line-height: 1.5;
}
.cuss-highlight-layer {
  white-space: pre-wrap; word-wrap: break-word; overflow: hidden;
  color: var(--color-text); pointer-events: none;
}
.cuss-highlight-input {
  width: 100%; height: 100%; background: transparent; color: transparent;
  caret-color: var(--color-text); border: none; outline: none; resize: none; overflow: auto;
}
.cuss-highlight-input::placeholder { color: color-mix(in srgb, var(--color-text) 45%, transparent); }

/* Stance-select screen — covers the arena when a round opens, until the
   player picks a side. Blue for Affirm, red for Negate, matching the same
   hues used elsewhere (connective blue, curse red) for visual consistency.
   Also hosts "Entering the Chat" (.cuss-enter-stage) now — the two used to
   be separate overlays that crossfaded (a second screen hand-off, exactly
   the kind of seam a homepage-flash bug lives in; see playEnterThenOpen()
   in script.js). The stage animates and fades itself to invisible via its
   own existing keyframes (unchanged), then .cuss-stance-content fades in
   on this SAME element — nothing is ever swapped for a different screen. */
.cuss-stance-select {
  position: absolute; inset: 0; z-index: 10; background: var(--color-bg);
}
.cuss-stance-select[hidden] { display: none; }
.cuss-stance-content {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: var(--space-4); text-align: center;
  padding: var(--space-4);
  opacity: 1; transition: opacity 0.4s ease;
}
/* Suppressed (no transition, so it doesn't fade back in mid-animation)
   for exactly as long as the entrance is playing — see is-entering below. */
.cuss-stance-select.is-entering .cuss-stance-content { opacity: 0; transition: none; }
.cuss-stance-eyebrow {
  margin: 0; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.cuss-stance-motion {
  margin: 0; max-width: 60ch; font-size: clamp(18px, 3vw, 26px); font-style: italic; line-height: 1.4;
}
.cuss-difficulty-select { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.cuss-difficulty-eyebrow {
  margin: 0; font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
/* Ledger-row picker — same numbered-line-item language as the homepage's
   "How it works" steps (see .cuss-feature's fading top-rule), reused here
   instead of the equal bordered boxes this screen used to show. Only the
   contents/CSS of .cuss-difficulty-btn changed; the element itself keeps
   its id/class/data-difficulty untouched, so setDifficulty()'s querySelectorAll
   and .is-active toggling in script.js need no changes. */
.cuss-difficulty-buttons { display: flex; flex-direction: column; width: 100%; max-width: 440px; margin: 0 auto; }
.cuss-difficulty-btn {
  display: flex; align-items: baseline; gap: var(--space-3); width: 100%; text-align: left;
  padding: var(--space-2) var(--space-2); border: none; border-radius: var(--radius-sm);
  /* This is a bare <button>, not a .btn — without an explicit background
     here, the browser's native UA-stylesheet button background (a pale
     gray/white "buttonface") shows through instead of the page's dark
     background, since nothing else in this rule ever set one. That's what
     made Rookie/Chair render as pale unreadable boxes: only .is-active
     (Delegate) happened to set its own background-color, which is the
     only reason it looked correct. Regressed when the divider-line
     background (a repeating-gradient) was removed from here without a
     transparent replacement. */
  background: transparent;
  color: var(--color-text); cursor: pointer; font-family: inherit;
  transition: background-color 0.15s ease;
}
.cuss-difficulty-btn:hover { background-color: color-mix(in srgb, var(--color-text) 6%, transparent); }
.cuss-difficulty-num {
  flex: none; width: 20px; font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: 14px; color: var(--color-accent); font-feature-settings: 'tnum' 1;
}
.cuss-difficulty-text { display: flex; flex-direction: column; gap: 2px; }
.cuss-difficulty-btn-title { font-size: 14px; font-weight: var(--font-heading-weight); }
.cuss-difficulty-btn-sub { font-size: 10.5px; color: color-mix(in srgb, var(--color-text) 55%, transparent); }
.cuss-difficulty-btn.is-active { background-color: color-mix(in srgb, var(--color-accent) 10%, transparent); }
.cuss-difficulty-btn.is-active .cuss-difficulty-btn-title,
.cuss-difficulty-btn.is-active .cuss-difficulty-num { color: var(--color-accent); }

.cuss-stance-buttons { display: flex; gap: var(--space-4); flex-wrap: wrap; justify-content: center; margin-top: var(--space-2); }
/* Affirm/Negate keep their size and color-coding, but now differ in more
   than color: each reuses the exact avatar recipe from .cuss-anchor-avatar
   (the same lettered-circle mark that appears once the round actually
   starts), mirrored left/right — Affirm's mark leads, Negate's trails —
   the same left/right mirroring already used for the pre-round transcript
   anchor, so the picker, the anchor, and the real transcript all share one
   avatar convention instead of introducing a new shape just for this screen. */
.cuss-stance-btn {
  /* min(240px, 100%) instead of a hard 240px — .cuss-stance-buttons already
     wraps these onto their own line at narrow widths, but the fixed width
     never actually shrank with the viewport; this caps at 240px on room to
     spare and fills the available width instead of overflowing it when
     there isn't. */
  flex-direction: row; align-items: center; width: min(240px, 100%); height: auto;
  padding: 22px 22px; gap: var(--space-3);
  border-radius: var(--radius-lg); transition: transform 0.15s ease, background 0.15s ease;
}
.cuss-stance-btn:hover { transform: translateY(-2px); }
.cuss-stance-btn:disabled { opacity: 0.4; cursor: not-allowed; transform: none; }
.cuss-stance-avatar {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 38px; height: 38px; border-radius: 50%; border: 1.5px solid currentColor;
  font-family: var(--font-heading); font-weight: 700; font-size: 14px;
}
.cuss-stance-text { display: flex; flex-direction: column; gap: 4px; }
.cuss-stance-btn-title { font-size: 22px; font-weight: var(--font-heading-weight); letter-spacing: 0.02em; }
.cuss-stance-btn-sub { font-size: 12.5px; font-weight: 400; color: color-mix(in srgb, var(--color-text) 65%, transparent); }
.cuss-stance-affirm {
  border-color: oklch(0.72 0.15 250); color: oklch(0.72 0.15 250);
}
.cuss-stance-affirm:hover { background: color-mix(in srgb, oklch(0.72 0.15 250) 12%, transparent); }
.cuss-stance-affirm .cuss-stance-btn-title { text-shadow: 0 0 10px color-mix(in srgb, oklch(0.72 0.15 250) 40%, transparent); }
.cuss-stance-negate {
  flex-direction: row-reverse; text-align: right;
  border-color: oklch(0.63 0.22 25); color: oklch(0.63 0.22 25);
}
.cuss-stance-negate .cuss-stance-text { align-items: flex-end; }
.cuss-stance-negate:hover { background: color-mix(in srgb, oklch(0.63 0.22 25) 12%, transparent); }
.cuss-stance-negate .cuss-stance-btn-title { text-shadow: 0 0 10px color-mix(in srgb, oklch(0.63 0.22 25) 40%, transparent); }

.cuss-stance-confirm { display: flex; flex-direction: column; gap: 8px; }
.cuss-stance-confirm[hidden] { display: none; }
.cuss-stance-confirm-row {
  margin: 0; font-size: 20px; font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  opacity: 0; transform: translateY(6px); transition: opacity 0.3s ease, transform 0.3s ease;
}
.cuss-stance-confirm-row.is-visible { opacity: 1; transform: translateY(0); }
.cuss-stance-confirm-row.cuss-text-affirm { color: oklch(0.72 0.15 250); }
.cuss-stance-confirm-row.cuss-text-negate { color: oklch(0.63 0.22 25); }

/* Post-round filler-word recap — the player's own words from that round
   only, each paired with a stronger alternative. */
.cuss-recap { display: flex; flex-direction: column; gap: 6px; align-items: center; max-width: 46ch; }
.cuss-recap:empty { display: none; }
.cuss-recap-heading {
  margin: 0; font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
.cuss-recap-clean { margin: 0; font-size: 14px; color: color-mix(in srgb, var(--color-text) 75%, transparent); }
.cuss-recap-row {
  display: flex; align-items: baseline; justify-content: center; gap: 10px; flex-wrap: wrap;
  font-size: 14.5px;
}
.cuss-recap-from { color: var(--color-warn); font-weight: 600; }
.cuss-recap-arrow { color: color-mix(in srgb, var(--color-text) 40%, transparent); }
.cuss-recap-to { color: oklch(0.75 0.13 150); font-weight: 600; }

/* Round-result screen — plays once when a round ends (either side hits 0
   Credibility): the win/lose volley animation, then the round stats and
   Rematch button fade in on this same screen (see .cuss-result-stats
   below) rather than handing off to a separate screen. Same ping-pong-
   volley language as "Entering the Chat" (.cuss-enter-*): the two
   lip halves lifted from the logo mark volley the ball, then on the final
   exchange the winning side's lip returns it (pulses, stays solid) and the
   losing side's lip fades out as the ball flies past. Upper = player, lower
   = AI opponent, matching the health-bar order above. See
   playRoundResultTransition() in script.js. Reuses the exact --u scale-
   factor technique .cuss-enter-stage uses so this also scales down on small
   viewports instead of overflowing the arena card. */
.cuss-result-transition {
  position: absolute; inset: 0; z-index: 6; display: flex; flex-direction: column;
  align-items: center; justify-content: center; overflow-y: auto; scrollbar-gutter: stable;
  background: var(--color-bg); opacity: 0; pointer-events: none; transition: opacity 0.3s ease;
  padding: 6px var(--edge);
}
.cuss-result-transition[hidden] { display: none; }
.cuss-result-transition.playing-win, .cuss-result-transition.playing-lose { opacity: 1; pointer-events: auto; }
/* Same 65vmin/420px cap as .cuss-enter-stage ("Entering the Chat") so the
   lips mark reads as one consistent size everywhere it appears — --u
   (used by every lip/ball keyframe below) is derived from this the same
   way there, so matching this one value matches lip and ball size too. */
.cuss-result-stage {
  position: relative; flex: none; width: min(65vmin, 420px); height: min(65vmin, 420px);
  --u: calc(min(65vmin, 420px) / 520px);
}
.cuss-result-lip {
  position: absolute; left: 50%; top: 50%;
  width: calc(var(--u) * 170px); height: calc(var(--u) * 130px);
  margin-left: calc(var(--u) * -85px); margin-top: calc(var(--u) * -65px);
  opacity: 0;
}
.cuss-result-lip svg { width: 100%; height: 100%; display: block; }
.cuss-result-ball {
  position: absolute; left: 50%; top: 50%;
  width: calc(var(--u) * 14px); height: calc(var(--u) * 14px);
  margin-left: calc(var(--u) * -7px); margin-top: calc(var(--u) * -7px);
  border-radius: 50%; background: #8B5CF6;
  box-shadow: 0 0 18px 4px rgba(139, 92, 246, 0.6);
  opacity: 0;
}
/* Sits below the stage in normal flow now (not absolutely hung off it) so
   the stats block added below it (see .cuss-result-stats) can grow the
   screen naturally instead of overlapping the lips/ball. */
.cuss-result-verdict { flex: none; margin-top: -60px; text-align: center; opacity: 0; }
.cuss-result-rule-line { display: flex; align-items: center; justify-content: center; gap: 14px; margin: 0 0 8px; }
.cuss-result-rule { display: inline-block; height: 1px; width: 60px; background: currentColor; transform: scaleX(0); transform-origin: center; }
.cuss-result-verdict.line-drawn .cuss-result-rule { animation: cuss-result-rule-draw 0.5s ease forwards; }
@keyframes cuss-result-rule-draw { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.cuss-result-rule-text {
  font-family: var(--font-heading); font-size: 11px; letter-spacing: 0.2em; text-transform: uppercase;
}
.cuss-result-headline {
  margin: 0; font-family: var(--font-heading); font-weight: var(--font-heading-weight);
  font-size: clamp(26px, 5vw, 36px); letter-spacing: -0.01em;
}
.cuss-result-sub {
  margin: 4px 0 0; font-family: var(--font-heading); font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 55%, transparent);
}
/* Round stats + Rematch — folded onto this same screen instead of a
   separate .cuss-gameover screen (removed) that used to take over after
   this animation finished; that hand-off was itself a second screen
   transition (its own place for a flash-of-the-wrong-screen glitch, same
   family as the "Entering the Chat" bug) and read as a different, plainer
   screen stitched on after a more polished one. Fades in on its own,
   timed from playRoundResultTransition() to land shortly after the
   verdict rule-line finishes drawing in, not instantly with everything
   else. Reuses .cuss-trend/.cuss-recap exactly as before — same data,
   same markup, just a new parent and entrance. */
.cuss-result-stats {
  display: flex; flex-direction: column; align-items: center; gap: var(--space-2);
  margin-top: var(--space-3); opacity: 0; transform: translateY(8px);
  transition: opacity 0.4s ease, transform 0.4s ease;
}
.cuss-result-stats.is-visible { opacity: 1; transform: translateY(0); }
/* Solid accent-purple fill, same recipe as .cuss-cta-xl (the hero Chat
   button) just sized down for a secondary action on this screen rather
   than a marketing hero — a clear, unambiguous "this is Cussator" button
   instead of the previous screen's plain light box. */
.cuss-result-rematch {
  margin-top: 2px; font-size: 15px; font-weight: var(--font-heading-weight); padding: 11px 32px;
  background: var(--color-accent); color: var(--color-bg); border-color: transparent;
}
.cuss-result-rematch:hover { background: var(--color-accent-2); }
.cuss-result-rematch:active { background: var(--color-accent); }

/* Win: upper (player) lip returns the final volley, lower (AI) lip misses —
   same green already used elsewhere (e.g. .cuss-vocab), no new colors. */
.cuss-result-transition.playing-win .cuss-result-lip-upper { animation: cuss-result-upper-win 3.6s cubic-bezier(0.4,0,0.2,1) forwards; }
.cuss-result-transition.playing-win .cuss-result-lip-lower { animation: cuss-result-lower-win 3.6s cubic-bezier(0.4,0,0.2,1) forwards; }
.cuss-result-transition.playing-win .cuss-result-ball { animation: cuss-result-ball-win 3.6s cubic-bezier(0.45,0,0.55,1) forwards; }
.cuss-result-transition.playing-win .cuss-result-verdict { animation: cuss-result-reveal 3.6s ease forwards; color: oklch(0.75 0.13 150); }

@keyframes cuss-result-upper-win {
  0%   { transform: translate(0, 0) scale(1); opacity: 1; }
  15%  { transform: translate(0, calc(var(--u) * -150px)) scale(0.92); opacity: 0.9; }
  35%  { transform: translate(calc(var(--u) * -70px), calc(var(--u) * -150px)) scale(0.92); opacity: 0.9; }
  55%  { transform: translate(calc(var(--u) * 60px), calc(var(--u) * -150px)) scale(0.92); opacity: 0.9; }
  75%  { transform: translate(0, calc(var(--u) * -150px)) scale(1.15); opacity: 1; }
  85%  { transform: translate(0, calc(var(--u) * -150px)) scale(1); opacity: 1; }
  100% { transform: translate(0, calc(var(--u) * -150px)) scale(1); opacity: 0.3; }
}
@keyframes cuss-result-lower-win {
  0%   { transform: translate(0, 0) scale(1); opacity: 1; }
  15%  { transform: translate(0, calc(var(--u) * 150px)) scale(0.92); opacity: 0.9; }
  35%  { transform: translate(calc(var(--u) * -70px), calc(var(--u) * 150px)) scale(0.92); opacity: 0.9; }
  55%  { transform: translate(calc(var(--u) * 60px), calc(var(--u) * 150px)) scale(0.92); opacity: 0.9; }
  75%  { transform: translate(calc(var(--u) * 60px), calc(var(--u) * 150px)) scale(0.9); opacity: 0.6; }
  100% { transform: translate(calc(var(--u) * 60px), calc(var(--u) * 150px)) scale(0.8); opacity: 0.15; }
}
@keyframes cuss-result-ball-win {
  0%   { transform: translate(0, 0) scale(1); opacity: 0; }
  12%  { transform: translate(0, 0) scale(1); opacity: 1; }
  25%  { transform: translate(calc(var(--u) * -70px), calc(var(--u) * -120px)) scale(1); opacity: 1; }
  35%  { transform: translate(calc(var(--u) * -70px), calc(var(--u) * 120px)) scale(1); opacity: 1; }
  45%  { transform: translate(calc(var(--u) * 60px), calc(var(--u) * -120px)) scale(1); opacity: 1; }
  55%  { transform: translate(calc(var(--u) * 60px), calc(var(--u) * 120px)) scale(1); opacity: 1; }
  68%  { transform: translate(calc(var(--u) * 60px), calc(var(--u) * 340px)) scale(0.5); opacity: 0.5; }
  72%  { opacity: 0; }
  100% { opacity: 0; }
}

/* Lose: lower (AI) lip returns the final volley, upper (player) lip misses. */
.cuss-result-transition.playing-lose .cuss-result-lip-upper { animation: cuss-result-upper-lose 3.6s cubic-bezier(0.4,0,0.2,1) forwards; }
.cuss-result-transition.playing-lose .cuss-result-lip-lower { animation: cuss-result-lower-lose 3.6s cubic-bezier(0.4,0,0.2,1) forwards; }
.cuss-result-transition.playing-lose .cuss-result-ball { animation: cuss-result-ball-lose 3.6s cubic-bezier(0.45,0,0.55,1) forwards; }
.cuss-result-transition.playing-lose .cuss-result-verdict { animation: cuss-result-reveal 3.6s ease forwards; color: oklch(0.63 0.22 25); }

@keyframes cuss-result-upper-lose {
  0%   { transform: translate(0, 0) scale(1); opacity: 1; }
  15%  { transform: translate(0, calc(var(--u) * -150px)) scale(0.92); opacity: 0.9; }
  35%  { transform: translate(calc(var(--u) * -70px), calc(var(--u) * -150px)) scale(0.92); opacity: 0.9; }
  55%  { transform: translate(calc(var(--u) * 60px), calc(var(--u) * -150px)) scale(0.92); opacity: 0.9; }
  75%  { transform: translate(calc(var(--u) * -40px), calc(var(--u) * -150px)) scale(0.9); opacity: 0.6; }
  100% { transform: translate(calc(var(--u) * -40px), calc(var(--u) * -150px)) scale(0.8); opacity: 0.15; }
}
@keyframes cuss-result-lower-lose {
  0%   { transform: translate(0, 0) scale(1); opacity: 1; }
  15%  { transform: translate(0, calc(var(--u) * 150px)) scale(0.92); opacity: 0.9; }
  35%  { transform: translate(calc(var(--u) * -70px), calc(var(--u) * 150px)) scale(0.92); opacity: 0.9; }
  55%  { transform: translate(calc(var(--u) * 60px), calc(var(--u) * 150px)) scale(0.92); opacity: 0.9; }
  75%  { transform: translate(0, calc(var(--u) * 150px)) scale(1.15); opacity: 1; }
  85%  { transform: translate(0, calc(var(--u) * 150px)) scale(1); opacity: 1; }
  100% { transform: translate(0, calc(var(--u) * 150px)) scale(1); opacity: 0.3; }
}
@keyframes cuss-result-ball-lose {
  0%   { transform: translate(0, 0) scale(1); opacity: 0; }
  12%  { transform: translate(0, 0) scale(1); opacity: 1; }
  25%  { transform: translate(calc(var(--u) * -70px), calc(var(--u) * -120px)) scale(1); opacity: 1; }
  35%  { transform: translate(calc(var(--u) * -70px), calc(var(--u) * 120px)) scale(1); opacity: 1; }
  45%  { transform: translate(calc(var(--u) * 60px), calc(var(--u) * -120px)) scale(1); opacity: 1; }
  55%  { transform: translate(calc(var(--u) * 60px), calc(var(--u) * 120px)) scale(1); opacity: 1; }
  68%  { transform: translate(calc(var(--u) * -40px), calc(var(--u) * -340px)) scale(0.5); opacity: 0.5; }
  72%  { opacity: 0; }
  100% { opacity: 0; }
}

@keyframes cuss-result-reveal {
  0%, 60%  { opacity: 0; transform: translateY(6px); }
  78%      { opacity: 1; transform: translateY(0); }
  100%     { opacity: 1; transform: translateY(0); }
}

/* "Entering the Chat" — plays once when Chat is clicked, hosted directly on
   .cuss-stance-select (see above) rather than a separate overlay that used
   to crossfade into the round-setup screen underneath. Built from the same
   two lip paths as the logo mark (cussator-mark.svg), split so each half
   can move independently. --u is a unitless scale factor (current stage
   size ÷ the 520px size the motion was originally tuned at) — every
   distance below is `var(--u) * <original px>` so the whole animation
   scales proportionally on small viewports instead of overflowing or
   feeling out of place. Triggered by .is-entering on WHICHEVER container
   currently hosts a .cuss-enter-stage (see playEnterThenOpen() in
   script.js for the round entrance, playBagEnterThenOpen() for the Bag
   drawer's own copy) — the selector below matches any ancestor with that
   class, not just .cuss-stance-select, so both reuse the exact same
   animation/timing (ENTER_ANIM_DURATION). */
.cuss-enter-stage {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(65vmin, 420px); height: min(65vmin, 420px);
  --u: calc(min(65vmin, 420px) / 520px);
  pointer-events: none;
}
.cuss-enter-lip {
  position: absolute; left: 50%; top: 50%;
  width: calc(var(--u) * 170px); height: calc(var(--u) * 130px);
  margin-left: calc(var(--u) * -85px); margin-top: calc(var(--u) * -65px);
  opacity: 0;
}
.cuss-enter-lip svg { width: 100%; height: 100%; display: block; }
.is-entering .cuss-enter-lip-upper {
  animation: cuss-enter-upper-lip 2.2s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
.is-entering .cuss-enter-lip-lower {
  animation: cuss-enter-lower-lip 2.2s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}
@keyframes cuss-enter-upper-lip {
  0%   { transform: translate(0, 0) scale(1); opacity: 1; }
  20%  { transform: translate(0, calc(var(--u) * -150px)) scale(0.92); opacity: 0.9; }
  45%  { transform: translate(calc(var(--u) * -90px), calc(var(--u) * -150px)) scale(0.92); opacity: 0.9; }
  70%  { transform: translate(calc(var(--u) * 70px), calc(var(--u) * -150px)) scale(0.92); opacity: 0.9; }
  100% { transform: translate(0, calc(var(--u) * -150px)) scale(0.95); opacity: 0; }
}
@keyframes cuss-enter-lower-lip {
  0%   { transform: translate(0, 0) scale(1); opacity: 1; }
  20%  { transform: translate(0, calc(var(--u) * 150px)) scale(0.92); opacity: 0.9; }
  45%  { transform: translate(calc(var(--u) * -90px), calc(var(--u) * 150px)) scale(0.92); opacity: 0.9; }
  70%  { transform: translate(calc(var(--u) * 70px), calc(var(--u) * 150px)) scale(0.92); opacity: 0.9; }
  100% { transform: translate(0, calc(var(--u) * 150px)) scale(0.95); opacity: 0; }
}
.cuss-enter-ball {
  position: absolute; left: 50%; top: 50%;
  width: calc(var(--u) * 14px); height: calc(var(--u) * 14px);
  margin-left: calc(var(--u) * -7px); margin-top: calc(var(--u) * -7px);
  border-radius: 50%; background: #8B5CF6;
  box-shadow: 0 0 18px 4px rgba(139, 92, 246, 0.6);
  opacity: 0;
}
.is-entering .cuss-enter-ball {
  animation: cuss-enter-ball 2.2s cubic-bezier(0.45, 0, 0.55, 1) forwards;
}
@keyframes cuss-enter-ball {
  0%   { transform: translate(0, 0); opacity: 0; }
  20%  { transform: translate(0, 0); opacity: 1; }
  35%  { transform: translate(calc(var(--u) * -90px), calc(var(--u) * -120px)); }
  45%  { transform: translate(calc(var(--u) * -90px), calc(var(--u) * 120px)); }
  60%  { transform: translate(calc(var(--u) * 70px), calc(var(--u) * -120px)); }
  70%  { transform: translate(calc(var(--u) * 70px), calc(var(--u) * 120px)); }
  90%  { transform: translate(0, calc(var(--u) * -40px)); opacity: 1; }
  100% { transform: translate(0, 0) scale(0.3); opacity: 0; }
}
.cuss-enter-label {
  position: absolute; left: 0; right: 0; bottom: calc(var(--u) * -70px); text-align: center;
  font-family: var(--font-heading); font-size: 13px; letter-spacing: 0.18em;
  color: color-mix(in srgb, var(--color-text) 55%, transparent); opacity: 0;
}
.cuss-enter-label b { color: var(--color-text); font-weight: 600; }
.is-entering .cuss-enter-label {
  animation: cuss-enter-label-fade 2.2s ease-in-out forwards;
}
@keyframes cuss-enter-label-fade {
  0%, 25% { opacity: 0; }
  45% { opacity: 1; }
  85% { opacity: 1; }
  100% { opacity: 0; }
}

/* Vocabulary Scars — a persistent, cross-round view of the same filler
   data the post-round recap already computes (site/script.js accumulates
   it into localStorage as each argument is scored), so this page is just a
   different display of existing numbers, not a new tracker. Full-screen,
   same pattern as .cuss-arena. */
.cuss-scars {
  position: fixed; inset: 0; z-index: 100; display: flex; align-items: stretch; justify-content: center;
  padding: 0; background: var(--color-bg);
  opacity: 0; pointer-events: none; transition: opacity 0.2s ease;
}
.cuss-scars.is-open { opacity: 1; pointer-events: auto; }
.cuss-scars-inner {
  width: 100%; max-width: 720px; height: 100%; max-height: 100vh;
  display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4) var(--edge); overflow-y: auto;
}
.cuss-scars-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.cuss-scars-title { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 20px; }
.cuss-scars-sub {
  margin: 0; font-size: 13.5px; max-width: 60ch;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}
.cuss-scars-list { display: flex; flex-direction: column; gap: var(--space-3); padding-top: var(--space-2); }
.cuss-scars-list .cuss-recap-row { justify-content: flex-start; font-size: 15px; }

/* Connector Log — same full-screen panel pattern as Vocabulary Scars just
   above (own class namespace so either can be removed independently), but
   a positive tracker like the Bag rather than a corrective one: just a
   running use-count per connector, no suggested alternative. See
   recordConnectiveWords()/initConnectorLog() in script.js. */
.cuss-connector-log {
  position: fixed; inset: 0; z-index: 100; display: flex; align-items: stretch; justify-content: center;
  padding: 0; background: var(--color-bg);
  opacity: 0; pointer-events: none; transition: opacity 0.2s ease;
}
.cuss-connector-log.is-open { opacity: 1; pointer-events: auto; }
.cuss-connector-log-inner {
  width: 100%; max-width: 720px; height: 100%; max-height: 100vh;
  display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4) var(--edge); overflow-y: auto;
}
.cuss-connector-log-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.cuss-connector-log-title { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 20px; }
.cuss-connector-log-sub {
  margin: 0; font-size: 13.5px; max-width: 60ch;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}
.cuss-connector-log-list { display: flex; flex-direction: column; gap: var(--space-3); padding-top: var(--space-2); }
.cuss-connector-log-list .cuss-recap-row { justify-content: flex-start; font-size: 15px; }
/* Same blue already used for the live .cuss-connective highlight, so the
   word reads as the same category here as it did mid-round. */
.cuss-connector-word { color: oklch(0.72 0.15 250); font-weight: 600; }

/* Bag — the positive mirror of Vocabulary Scars just above: identical
   full-screen panel structure, but the word itself is styled in the same
   green already used for the live "vocab" highlight (.cuss-vocab) instead
   of Scars' filler-orange, so the trophy-case framing reads immediately
   even before the sub-copy is read. See initBag() in script.js. */
.cuss-bag {
  position: fixed; inset: 0; z-index: 100; display: flex; align-items: stretch; justify-content: center;
  padding: 0; background: var(--color-bg);
  opacity: 0; pointer-events: none; transition: opacity 0.2s ease;
}
.cuss-bag.is-open { opacity: 1; pointer-events: auto; }
.cuss-bag-inner {
  position: relative;
  width: 100%; max-width: 720px; height: 100%; max-height: 100vh;
  display: flex; flex-direction: column; gap: var(--space-3);
  padding: var(--space-4) var(--edge); overflow-y: auto;
}
/* Same "Entering the Chat" lips-paddle animation as opening a round (see
   .cuss-enter-stage above and playBagEnterThenOpen() in script.js), just
   hosted on this panel instead — the content fades in on this SAME
   element the instant it finishes, no separate screen to hand off to. */
.cuss-bag-content { opacity: 1; transition: opacity 0.4s ease; }
.cuss-bag.is-entering .cuss-bag-content { opacity: 0; transition: none; }
.cuss-bag-head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.cuss-bag-title { font-family: var(--font-heading); font-weight: var(--font-heading-weight); font-size: 20px; }
.cuss-bag-sub {
  margin: 0; font-size: 13.5px; max-width: 60ch;
  color: color-mix(in srgb, var(--color-text) 65%, transparent);
}
/* Collected words as a trading-card lineup — a row/grid of individual
   cards (word + "level", i.e. how many times it's actually landed) rather
   than a plain list, so the Bag reads as a collection to show off, not a
   log. Each card settles in with its own small pop (see .is-visible,
   staggered from renderBag() in script.js) instead of all appearing at
   once, echoing dealing out cards one at a time. */
.cuss-bag-list { display: flex; flex-wrap: wrap; gap: var(--space-3); padding-top: var(--space-2); }
.cuss-bag-card {
  width: 136px; display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: var(--space-3) var(--space-2); border-radius: var(--radius-md); text-align: center;
  background: color-mix(in srgb, oklch(0.75 0.13 150) 10%, var(--color-surface));
  border: 1px solid color-mix(in srgb, oklch(0.75 0.13 150) 35%, transparent);
  opacity: 0; transform: translateY(10px) scale(0.94);
  transition: opacity 0.3s ease, transform 0.3s cubic-bezier(.2, 1.4, .4, 1);
}
.cuss-bag-card.is-visible { opacity: 1; transform: translateY(0) scale(1); }
.cuss-bag-card-level {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.06em;
  color: color-mix(in srgb, oklch(0.75 0.13 150) 85%, var(--color-text));
  border: 1px solid color-mix(in srgb, oklch(0.75 0.13 150) 45%, transparent);
  border-radius: 999px; padding: 1px 8px;
}
/* Purely cosmetic — flags words that are also real MUN/diplomatic
   vocabulary (see MUN_TERMS in script.js). Accent purple rather than the
   card's green, so it reads as a distinct second tag next to the CEFR
   level pill above, not a variant of it. */
.cuss-bag-card-mun {
  font-size: 9.5px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--color-accent);
  border: 1px solid color-mix(in srgb, var(--color-accent) 45%, transparent);
  border-radius: 999px; padding: 1px 8px;
}
/* Purely cosmetic, same pattern as .cuss-bag-card-mun above — flags words
   also on the Academic Word List (see AWL_TERMS in script.js). Its own
   third color (the site's existing warn/amber token) so a word carrying
   both tags at once still reads as two distinct badges, not two of the
   same thing. */
.cuss-bag-card-awl {
  font-size: 9.5px; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--color-warn);
  border: 1px solid color-mix(in srgb, var(--color-warn) 45%, transparent);
  border-radius: 999px; padding: 1px 8px;
}
.cuss-bag-card-word { font-size: 16px; font-weight: 700; color: oklch(0.75 0.13 150); }
.cuss-bag-card-def { font-size: 11.5px; line-height: 1.35; color: color-mix(in srgb, var(--color-text) 65%, transparent); }

/* Round-end trend — this round's filler count against the player's own
   last-3-rounds average, pulled from the same localStorage history that
   feeds the homepage's real per-player stat tile. */
.cuss-trend { display: flex; flex-direction: column; gap: 4px; align-items: center; }
.cuss-trend:empty { display: none; }
.cuss-trend-count { margin: 0; font-size: 16px; font-weight: 600; }
.cuss-trend-note { margin: 0; font-size: 13.5px; }
.cuss-trend-down { color: oklch(0.75 0.13 150); }
.cuss-trend-up { color: oklch(0.63 0.22 25); }
.cuss-trend-flat { color: color-mix(in srgb, var(--color-text) 60%, transparent); }

@media (max-width: 640px) {
  .cuss-arena-inner { padding: var(--space-3); }
  .cuss-arena-form { flex-direction: column; align-items: stretch; }
  .cuss-scars-inner { padding: var(--space-3); }
  .cuss-connector-log-inner { padding: var(--space-3); }
  .cuss-bag-inner { padding: var(--space-3); }
}
