/*
 * Application-wide styles. Propshaft serves every file in this directory;
 * later files override earlier ones per the standard cascade.
 *
 * Built on the Mafia design system: a dark-purple "noir" identity — near-black
 * purple surfaces, one violet→magenta gradient stroke on the primary action,
 * gold reserved as a rare solid "insignia" (completed games, admin marker,
 * rematch CTA), pill buttons, and big condensed uppercase display type.
 * Token values are copied verbatim from the design system tokens
 * (colors / typography / spacing / effects); the component styles below are
 * this app's, written against the semantic aliases only.
 *
 * Theming: dark only. Noir is the identity — there is no light variant.
 */

@import url('https://fonts.googleapis.com/css2?family=Big+Shoulders+Display:wght@600;700;800;900&family=Manrope:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600;700&display=swap');

/* ============================================================
   MAFIA · COLOR TOKENS
   ============================================================ */

:root {
  color-scheme: dark;

  /* ---- Noir · purple-black neutral scale ---- */
  --noir-950: #07050D;
  --noir-900: #0E0918;  /* page background */
  --noir-850: #140E21;
  --noir-800: #1A1329;  /* raised surface / card */
  --noir-750: #211934;
  --noir-700: #2A2040;  /* default border */
  --noir-600: #392C55;  /* strong border */
  --noir-500: #4F3E77;  /* muted text on dark, hairlines */
  --noir-400: #7B6699;  /* subtle text, disabled */
  --noir-300: #A797BE;
  --noir-200: #CBC0DE;
  --noir-100: #E4DDEF;
  --noir-50:  #F7F4FC;  /* near-white text */

  /* ---- Violet · the brand stroke ---- */
  --violet-800: #3B0F82;
  --violet-700: #5B21B6;
  --violet-600: #7C3AED;
  --violet-500: #9455F5;  /* base brand accent */
  --violet-400: #AB7BFA;  /* hover / bright */
  --violet-300: #C4A6FF;
  --violet-200: #DDCBFF;
  --violet-100: #2A1B47;  /* dark tint, not pastel */

  /* ---- Magenta · gradient partner ---- */
  --magenta-600: #A21CAF;
  --magenta-500: #D946EF;
  --magenta-400: #E879F9;

  /* ---- Gold · insignia / luxury secondary ---- */
  --gold-600: #8A6414;
  --gold-500: #D4A72C;
  --gold-400: #E8C158;
  --gold-100: #332711;  /* dark tint */

  /* ---- Semantic ---- */
  --green-600: #15803D;
  --green-500: #22C55E;
  --green-100: #10281C;

  --red-600:   #B91C3C;
  --red-500:   #E11D48;
  --red-100:   #350F19;

  --blue-600:  #4C69D6;
  --blue-500:  #6C8CFF;
  --blue-100:  #171D3A;

  /* ---- Semantic aliases — components reference these, not the scale ---- */
  --text-strong:    var(--noir-50);
  --text-body:      var(--noir-100);
  --text-muted:     var(--noir-300);
  --text-subtle:    var(--noir-400);
  --text-inverse:   var(--noir-900);
  --text-accent:    var(--violet-300);
  --text-link:      var(--violet-300);
  --text-on-accent: #FFFFFF;
  --text-on-strong: var(--noir-900);

  --surface-page:    var(--noir-900);
  --surface-raised:  var(--noir-800);
  --surface-sunken:  var(--noir-950);
  --surface-tint:    var(--noir-750);
  --surface-accent:  var(--violet-500);
  --surface-accent-tint: var(--violet-100);
  --surface-inverse: var(--noir-50);
  --surface-strong:  var(--gold-400); /* "gold object" — the one non-violet solid chip */
  --surface-overlay: rgba(7, 5, 13, 0.72);

  --line:          var(--noir-700);
  --line-subtle:   var(--noir-750);
  --line-strong:   var(--noir-600);
  --line-accent:   var(--violet-500);
  --focus-ring:    var(--violet-400);

  --success:        var(--green-500);
  --success-strong:  var(--green-600);
  --success-tint:    var(--green-100);
  --warning:         var(--gold-500);
  --warning-strong:  var(--gold-600);
  --warning-tint:    var(--gold-100);
  --danger:          var(--red-500);
  --danger-strong:   var(--red-600);
  --danger-tint:     var(--red-100);
  --info:            var(--blue-500);
  --info-strong:     var(--blue-600);
  --info-tint:       var(--blue-100);

  --gradient-primary:       linear-gradient(135deg, var(--violet-600), var(--magenta-600));
  --gradient-primary-hover: linear-gradient(135deg, var(--violet-500), var(--magenta-500));
  --gradient-primary-press: linear-gradient(135deg, var(--violet-700), var(--violet-800));
  --gradient-noir:  linear-gradient(180deg, var(--noir-850) 0%, var(--noir-950) 100%);
  --gradient-gold:  linear-gradient(135deg, var(--gold-400), var(--gold-600));

  --select-chevron: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23A797BE' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
}

/* ============================================================
   MAFIA · TYPOGRAPHY, SPACING & EFFECTS TOKENS
   ============================================================ */

:root {
  /* Big Shoulders Display: bold condensed poster face — a Chicago-newspaper,
     back-room-headline feel for wordmark + display type. Manrope: a rounded-
     terminal geometric sans for body/UI. JetBrains Mono: stat blocks, timers,
     event logs. */
  --font-display: "Big Shoulders Display", "Oswald", sans-serif;
  --font-sans: "Manrope", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SF Mono", "Menlo", monospace;

  --weight-regular:  400;
  --weight-medium:   500;
  --weight-semibold: 600;
  --weight-bold:     700;
  --weight-black:    800;
  --weight-display:  900;

  --text-2xs:  11px;
  --text-xs:   12px;
  --text-sm:   13px;
  --text-base: 15px;   /* app body default */
  --text-md:   17px;
  --text-lg:   20px;
  --text-xl:   24px;
  --text-2xl:  30px;
  --text-3xl:  38px;
  --text-4xl:  48px;
  --text-5xl:  64px;
  --text-6xl:  84px;

  --leading-none:    1;
  --leading-tight:   1.08;
  --leading-snug:    1.25;
  --leading-normal:  1.5;
  --leading-relaxed: 1.65;

  --tracking-tight:  -0.02em;
  --tracking-snug:   -0.01em;
  --tracking-normal: 0em;
  --tracking-wide:   0.02em;
  --tracking-label:  0.09em;   /* mono overline labels */

  --space-0-5: 2px;
  --space-1:   4px;
  --space-1-5: 6px;
  --space-2:   8px;
  --space-2-5: 10px;
  --space-3:   12px;
  --space-4:   16px;
  --space-5:   20px;
  --space-6:   24px;
  --space-8:   32px;
  --space-10:  40px;
  --space-12:  48px;
  --space-16:  64px;
  --space-20:  80px;
  --space-24:  96px;

  --width-prose:   680px;
  --width-content: 1120px;
  --sidebar-width: 260px;

  --control-sm: 34px;
  --control-md: 44px;
  --control-lg: 52px;

  --gap-inline:    var(--space-2);
  --gap-stack:     var(--space-4);
  --pad-card:      var(--space-6);
  --pad-control-x: var(--space-5);
  --page-gutter:   var(--space-6);

  /* Rounded, confident — corners run noticeably larger than a typical SaaS
     grid; buttons round all the way to a pill. */
  --radius-xs:   6px;
  --radius-sm:   10px;   /* inputs */
  --radius-md:   14px;   /* callouts, flashes */
  --radius-lg:   20px;   /* cards, panels */
  --radius-xl:   28px;   /* large panels, modals */
  --radius-pill: 999px;  /* buttons, badges */

  --border-hair:  1px;
  --border-thick: 2px;
  --border-mark:  3px;   /* the warning callout's left bar */

  /* Dark surfaces need deep, near-black shadows, plus one violet glow
     reserved for the primary action and focus states — nothing else glows. */
  --shadow-xs: 0 1px 2px rgba(0,0,0,.45);
  --shadow-sm: 0 2px 6px rgba(0,0,0,.5), 0 1px 2px rgba(0,0,0,.35);
  --shadow-md: 0 8px 24px -6px rgba(0,0,0,.6), 0 2px 6px rgba(0,0,0,.4);
  --shadow-lg: 0 20px 48px -12px rgba(0,0,0,.65), 0 8px 16px -8px rgba(0,0,0,.45);
  --shadow-glow: 0 0 0 1px rgba(148,85,245,.4), 0 0 28px rgba(148,85,245,.38);
  --shadow-focus: 0 0 0 3px rgba(148,85,245,.35), 0 0 0 1px var(--violet-400);

  --ease-out:    cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); /* press feedback only */
  --dur-fast: 130ms;
  --dur-base: 200ms;
  --dur-slow: 320ms;
}

/* ============================================================
   BASE
   ============================================================ */

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--surface-page);
  color: var(--text-body);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  -webkit-font-smoothing: antialiased;
}

/* Display headings are the one deliberate uppercase — driven by the
   condensed poster face, not a copy rule. */
h1, h2, h3 {
  color: var(--text-strong);
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
  text-transform: uppercase;
}

h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-lg); }

p { color: var(--text-body); }

a {
  color: var(--text-link);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
  transition: color var(--dur-fast) var(--ease-out);
}
a:hover { color: var(--violet-200); }
a:focus-visible { outline: none; border-radius: var(--radius-xs); box-shadow: var(--shadow-focus); }

.text-muted { color: var(--text-muted); }
small { font-size: var(--text-xs); }

/* ============================================================
   HEADER
   ============================================================ */

.site-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  padding: var(--space-3) var(--space-6);
  background: var(--surface-raised);
  border-bottom: var(--border-hair) solid var(--line);
}

.site-header .brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2-5);
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: var(--text-lg);
  text-transform: uppercase;
  letter-spacing: var(--tracking-tight);
  color: var(--text-strong);
  text-decoration: none;
}

/* The fedora-and-shades mark — the brand stroke lives in its gradient. */
.site-header .brand img {
  width: 30px;
  height: 30px;
  display: block;
}

.site-header nav {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-4);
}

.site-header nav a {
  color: var(--text-muted);
  text-decoration: none;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}
.site-header nav a:hover { color: var(--text-strong); }

.nav-email {
  color: var(--text-subtle);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
}

.locale-switcher select {
  width: auto;
  height: var(--control-sm);
  padding: 0 var(--space-6) 0 var(--space-2-5);
  font-size: var(--text-xs);
}

/* ============================================================
   LAYOUT
   ============================================================ */

.container {
  max-width: var(--width-content);
  margin: 0 auto;
  padding: var(--space-8) var(--page-gutter);
}

.flash {
  padding: var(--space-3) var(--space-4);
  border: var(--border-hair) solid;
  border-radius: var(--radius-md);
  margin-bottom: var(--space-4);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}
.flash-notice { background: var(--success-tint); border-color: var(--success-strong); color: var(--success); }
.flash-alert { background: var(--danger-tint); border-color: var(--danger-strong); color: var(--danger); }

/* ============================================================
   FORMS
   ============================================================ */

.field { margin-bottom: var(--space-4); }
.field label {
  display: block;
  margin-bottom: var(--space-1-5);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--text-body);
}
.field small {
  display: block;
  margin-top: var(--space-1-5);
  color: var(--text-muted);
}

/* Input with its action button attached on one line (type a name, then add) */
.field-row {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  max-width: 24rem;
}
.field-row input { flex: 1; min-width: 0; }
.field-row .btn { flex-shrink: 0; }

input[type="text"], input[type="email"], input[type="password"],
input[type="number"], textarea, select {
  width: 100%;
  max-width: 24rem;
  height: var(--control-md);
  padding: 0 var(--space-3);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  color: var(--text-strong);
  background: var(--surface-raised);
  border: var(--border-hair) solid var(--line-strong);
  border-radius: var(--radius-sm);
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}

textarea { height: auto; min-height: 96px; padding: var(--space-2-5) var(--space-3); line-height: var(--leading-normal); resize: vertical; }

::placeholder { color: var(--text-subtle); }

input:hover, textarea:hover, select:hover { border-color: var(--noir-500); }

input:focus, textarea:focus, select:focus {
  outline: none;
  border-color: var(--focus-ring);
  box-shadow: var(--shadow-focus);
}

select {
  appearance: none;
  background-image: var(--select-chevron);
  background-repeat: no-repeat;
  background-position: right var(--space-2-5) center;
  padding-right: var(--space-8);
  cursor: pointer;
}

input[type="checkbox"] {
  width: 16px;
  height: 16px;
  margin: 0 var(--space-1) 0 0;
  vertical-align: -2px;
  accent-color: var(--surface-accent);
  cursor: pointer;
}
input[type="checkbox"]:focus-visible { outline: none; box-shadow: var(--shadow-focus); border-radius: var(--radius-xs); }

input[type="radio"] {
  width: 16px;
  height: 16px;
  margin: 0;
  flex-shrink: 0;
  accent-color: var(--surface-accent);
  cursor: pointer;
}
input[type="radio"]:focus-visible { outline: none; box-shadow: var(--shadow-focus); border-radius: 50%; }

/* Stacked radio options (game setup: role reveals) */
.radio-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  border: 0;
  margin: 0;
  padding: 0;
}
.radio-group legend {
  padding: 0;
  margin-bottom: var(--space-2);
  font-size: var(--text-sm);
  color: var(--text-muted);
}
.radio-option {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  cursor: pointer;
  color: var(--text-muted);
  transition: color var(--dur-fast) var(--ease-out);
}
.radio-option input[type="radio"] { margin-top: 2px; }
.radio-option:hover { color: var(--text-strong); }
.radio-option:has(input:checked) { color: var(--text-strong); }

.form-errors {
  background: var(--danger-tint);
  border: var(--border-hair) solid var(--danger-strong);
  border-radius: var(--radius-md);
  color: var(--danger);
  font-size: var(--text-sm);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
}
.form-errors ul { margin: 0; padding-left: var(--space-5); }

/* ============================================================
   BUTTONS
   ============================================================ */

/* Keep the hidden attribute authoritative: display rules on .btn (and
   anything else) must not resurrect an element JS has hidden. */
[hidden] {
  display: none !important;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  height: var(--control-md);
  padding: 0 var(--pad-control-x);
  font-family: var(--font-sans);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  letter-spacing: var(--tracking-snug);
  white-space: nowrap;
  border: var(--border-hair) solid var(--line-strong);
  border-radius: var(--radius-pill);
  background: var(--surface-raised);
  color: var(--text-strong);
  cursor: pointer;
  text-decoration: none;
  user-select: none;
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out), transform var(--dur-fast) var(--ease-spring);
}

.btn:hover { background: var(--surface-tint); color: var(--text-strong); }
/* Press scales the control — a small, game-ish tactility. No color-only press states. */
.btn:active { transform: scale(0.97); }
.btn:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.btn[disabled] { opacity: 0.42; pointer-events: none; }

/* The one gradient action per view. */
.btn-primary {
  background: var(--gradient-primary);
  border-color: transparent;
  color: var(--text-on-accent);
  box-shadow: var(--shadow-sm);
}
.btn-primary:hover { background: var(--gradient-primary-hover); color: var(--text-on-accent); }
.btn-primary:active { background: var(--gradient-primary-press); }

/* Tinted, not solid — destructive actions stay distinct from the one
   gradient primary without competing with it. */
.btn-danger {
  background: var(--danger-tint);
  border-color: var(--red-100);
  color: var(--danger-strong);
}
.btn-danger:hover { background: var(--red-100); color: var(--danger); }

/* Gold — celebratory only (rematch CTA). The medallion, not a second brand. */
.btn-gold {
  background: var(--gradient-gold);
  border-color: transparent;
  color: var(--text-on-strong);
  box-shadow: var(--shadow-sm);
}
.btn-gold:hover { background: var(--gold-400); color: var(--text-on-strong); }

.btn-link {
  background: none;
  border: none;
  color: var(--text-muted);
  padding: 0;
  height: auto;
  cursor: pointer;
  font: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
}
.btn-link:hover { color: var(--text-strong); background: none; }
.btn-link:focus-visible { outline: none; border-radius: var(--radius-xs); box-shadow: var(--shadow-focus); }

/* ============================================================
   CARDS & TABLES
   ============================================================ */

.card {
  background: var(--surface-raised);
  border: var(--border-hair) solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  padding: var(--pad-card);
  margin-bottom: var(--space-5);
}

.card h2, .card h3 { margin-top: 0; }

.auth-card {
  max-width: 26rem;
  margin: var(--space-12) auto;
  background: var(--surface-raised);
  border: var(--border-hair) solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  padding: var(--space-8);
}

/* Passkey alternative on the login card, set off from the password form. */
.passkey-login {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: var(--border-hair) solid var(--line);
}

table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }

th {
  text-align: left;
  padding: var(--space-2) var(--space-3);
  border-bottom: var(--border-hair) solid var(--line-strong);
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
}

td {
  text-align: left;
  padding: var(--space-2-5) var(--space-3);
  border-bottom: var(--border-hair) solid var(--line-subtle);
}

tbody tr:last-child td { border-bottom: none; }

summary { cursor: pointer; }
summary:hover { color: var(--text-strong); }

/* ============================================================
   BADGES
   ============================================================ */

.badge {
  display: inline-flex;
  align-items: center;
  padding: var(--space-1) var(--space-2-5);
  border-radius: var(--radius-pill);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  line-height: var(--leading-snug);
  white-space: nowrap;
}

.badge-setup { background: var(--surface-tint); color: var(--noir-200); }
.badge-night { background: var(--info-tint); color: var(--info); }
.badge-dawn { background: var(--warning-tint); color: var(--warning); }
.badge-day { background: var(--success-tint); color: var(--success); }
.badge-voting { background: var(--surface-accent-tint); color: var(--text-accent); }
/* Finished games wear the gold — a medallion resting on the noir. */
.badge-completed { background: var(--surface-strong); color: var(--text-on-strong); }

.badge-alive { background: var(--success-tint); color: var(--success); }
.badge-dead { background: var(--danger-tint); color: var(--danger); }
.badge-effect { background: var(--warning-tint); color: var(--warning); }

/* GM roster's one-use ability tracker: lit while the use is unspent,
   grayed out (but still present) once it's gone. */
.badge-ability { background: var(--info-tint); color: var(--info); }
.badge-ability.badge-spent {
  background: var(--surface-tint);
  color: var(--text-muted);
  opacity: 0.55;
}

/* ============================================================
   GAME SCREENS
   ============================================================ */

/* The single left-bar accent in the system — matching the source app's
   soft warn-not-block callout. */
.warning-box {
  background: var(--warning-tint);
  border: var(--border-hair) solid var(--gold-600);
  border-left: var(--border-mark) solid var(--warning);
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  margin-bottom: var(--space-4);
  font-size: var(--text-sm);
  color: var(--warning);
}

.actions-row {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  flex-wrap: wrap;
  margin: var(--space-4) 0;
}

.night-dead-role { opacity: 0.6; font-style: italic; }

/* GM tools: one row per tool — controls on the left, that tool's hint on
   the right. New tools slot in as additional .gm-tool rows. */
.gm-tool {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  padding: var(--space-4) 0;
  border-top: var(--border-hair) solid var(--line-subtle);
}
.gm-tool:first-of-type { border-top: none; margin-top: var(--space-2); padding-top: 0; }
.gm-tool:last-of-type { padding-bottom: 0; }

.gm-tool-controls {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin: 0;
}
.gm-tool-controls select, .gm-tool-controls input[type="text"] {
  width: auto;
  flex: 1;
  min-width: 0;
}

.gm-tool-hint {
  flex: 1;
  min-width: 220px;
  margin: 0;
  font-size: var(--text-xs);
  color: var(--text-muted);
  text-align: left;
}

/* Event log day dividers: each game day opens with a quiet mono overline
   (inherited from the base th voice) over a hairline, so the GM can scan
   day boundaries at a glance. */
.event-log-day th {
  padding-top: var(--space-5);
  border-bottom: var(--border-hair) solid var(--line-subtle);
}
tbody .event-log-day:first-child th { padding-top: var(--space-2); }

/* Deck builder (setup's "Deal roles" card): the GM fills a deck of one
   card per player. Each team stakes its color once, via --team custom
   properties, and the slot chips / role dots read from them. */
.team-town { --team: var(--info); --team-tint: var(--info-tint); }
.team-mafia { --team: var(--danger); --team-tint: var(--danger-tint); }
.team-neutral { --team: var(--text-accent); --team-tint: var(--surface-accent-tint); }

.deck-status {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin: var(--space-4) 0 var(--space-2);
}
.deck-meter {
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  color: var(--text-strong);
}
.deck-status-text {
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--text-muted);
}
.deck-status-text.is-full { color: var(--success); }

/* The tray: one card-back chip per player, filled chips wear their
   team's color. Chips persist in the DOM so refills ripple across. */
.deck-tray {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin-bottom: var(--space-5);
}
.deck-slot {
  width: 17px;
  height: 26px;
  border: var(--border-hair) dashed var(--line-strong);
  border-radius: var(--radius-xs);
  background: var(--surface-sunken);
  transition: background var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
}
.deck-slot.is-filled {
  border: var(--border-thick) solid var(--team);
  background: var(--team-tint);
}

.deck-roles {
  display: flex;
  flex-direction: column;
  gap: var(--space-1-5);
  margin-bottom: var(--space-4);
  max-width: 26rem;
}
.deck-role { display: flex; align-items: center; gap: var(--space-2-5); }
.deck-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--team);
  flex-shrink: 0;
}
.deck-role-name { flex: 1; min-width: 0; }
.deck-role .deck-dot, .deck-role .deck-role-name { transition: opacity var(--dur-fast) var(--ease-out); }
.deck-role.is-zero .deck-dot, .deck-role.is-zero .deck-role-name { opacity: 0.45; }
.deck-fill { flex-shrink: 0; }
.deck-fill[disabled] { opacity: 0.42; pointer-events: none; }

.deck-stepper { display: flex; align-items: center; gap: var(--space-1); }
.deck-step {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--control-sm);
  height: var(--control-sm);
  border: var(--border-hair) solid var(--line-strong);
  border-radius: var(--radius-pill);
  background: var(--surface-raised);
  color: var(--text-strong);
  font-family: var(--font-mono);
  font-size: var(--text-md);
  line-height: var(--leading-none);
  cursor: pointer;
  user-select: none;
  transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out),
              transform var(--dur-fast) var(--ease-spring);
}
.deck-step:hover { background: var(--surface-tint); }
.deck-step:active { transform: scale(0.94); }
.deck-step:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.deck-step[disabled] { opacity: 0.42; pointer-events: none; }

.deck-stepper input[type="number"] {
  width: 3.4rem;
  height: var(--control-sm);
  padding: 0;
  text-align: center;
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  -moz-appearance: textfield;
}
.deck-stepper input[type="number"]::-webkit-outer-spin-button,
.deck-stepper input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ============================================================
   PUBLIC LIVE PAGE
   ============================================================ */

/* The page scales with the screen, and everything must fit in one
   viewport — no scrolling at any reasonable size. Every type size takes
   the smaller of a width-based and a height-based measure, and the
   roster additionally divides the height left under the heading block
   by its own row count (set as a CSS var by the template). */
.live-body {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

.container.live-page {
  max-width: none;
  width: 100%;
  /* auto vertical margins center the page but, unlike justify-content:
     center on the body, never clip the top if content does overflow */
  margin: auto;
  padding: clamp(var(--space-3), 2vh, var(--space-8)) var(--page-gutter);
  text-align: center;
}

.live-page h1 {
  font-size: clamp(var(--text-xl), min(2.5vw, 5vh), var(--text-5xl));
  margin: 0 0 0.15em;
}

.live-page p {
  font-size: clamp(var(--text-base), min(2vw, 3.5vh), var(--text-4xl));
  margin: 0.35em 0;
}
.live-page .text-muted { font-size: clamp(var(--text-sm), min(1.6vw, 3vh), var(--text-3xl)); }

/* The one full-bleed treatment: large display type, no image behind it.
   Height-capped so a short, wide screen can't let the banner push the
   roster off the bottom. */
.live-page .phase-banner {
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  text-transform: uppercase;
  font-size: clamp(var(--text-2xl), min(6.5vw, 13vh), 150px);
  letter-spacing: var(--tracking-tight);
  line-height: var(--leading-tight);
  color: var(--text-strong);
  margin: 0.1em 0;
}

.live-roster {
  list-style: none;
  padding: 0;
  margin: 0.6em 0 0;
  display: grid;
  /* Never more than two columns: single file on phones, side-by-side
     once there's room. */
  grid-template-columns: 1fr;
  --live-rows: var(--live-rows-1col, 8);
  /* Height the heading block (title, day, banner, announcement, page
     padding) occupies above the roster; the banner term tracks its
     clamp above, the rest is covered by the fixed-ish allowance. */
  --live-chrome: calc(min(6.5vw, 13vh) * 1.5 + clamp(150px, 22vh, 320px));
  gap: 0.7em;
  /* Each row costs ~3.8em: 1.5em box padding + ~1.5em line + 0.7em gap
     + border slack. Split the leftover height across the rows, never
     exceeding the width-based poster size, and never dropping below
     legibility. */
  font-size: clamp(
    var(--text-xs),
    min(max(2.1vw, var(--text-base)),
        calc((100dvh - var(--live-chrome)) / var(--live-rows) / 3.8)),
    54px
  );
}

@media (min-width: 800px) {
  .live-roster {
    grid-template-columns: repeat(2, 1fr);
    --live-rows: var(--live-rows-2col, 4);
  }
}

/* Big rosters go two-up at every width — ten one-column rows plus the
   banner is the most even a phone can fit without scrolling. */
.live-roster.packed {
  grid-template-columns: repeat(2, 1fr);
  --live-rows: var(--live-rows-2col, 4);
}

.live-roster li {
  background: var(--surface-raised);
  border: var(--border-hair) solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs);
  padding: 0.75em 1.1em;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5em;
  font-size: inherit;
}
.live-roster li.dead { opacity: 0.55; }
.live-roster li.dead > span:first-child { text-decoration: line-through; }

.live-page .badge { font-size: 0.62em; padding: 0.28em 0.85em; }

/* ============================================================
   MOBILE
   ============================================================ */

@media (max-width: 640px) {
  .container { padding: var(--space-4) var(--space-3); }

  .site-header {
    padding: var(--space-2) var(--space-3);
    flex-wrap: wrap;
  }
  .nav-email { display: none; }

  .card { padding: var(--space-4); }
  .auth-card { margin: var(--space-4) auto; padding: var(--space-5); }

  h1 { font-size: var(--text-2xl); }

  /* Full-width inputs and comfortable tap targets */
  input[type="text"], input[type="email"], input[type="password"],
  textarea, select {
    max-width: 100%;
    width: 100%;
    height: var(--control-lg);
  }
  textarea { height: auto; }
  td select { width: 100%; }
  .actions-row input[type="text"], .actions-row select { width: auto; flex: 1; min-width: 0; }
  .field-row { max-width: 100%; }
  .field-row input[type="text"] { width: auto; }
  .btn { height: var(--control-lg); padding: 0 var(--space-5); }
  .btn-link { height: auto; }
  .deck-step { width: var(--control-md); height: var(--control-md); }
  .deck-stepper input[type="number"] { width: 3.4rem; height: var(--control-md); }
  .site-header select { height: var(--control-sm); }

  /* Tables scroll sideways instead of breaking the page */
  table {
    display: block;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }
  th, td { padding: var(--space-2) var(--space-2); }
}

@media (prefers-reduced-motion: reduce) {
  a, .btn, input, textarea, select, .deck-step, .deck-slot { transition: none; }
}

/* ============================================================
   ADMIN
   ============================================================ */

/* Subscription-status badges reuse the semantic tints. */
.badge-trialing { background: var(--info-tint); color: var(--info); }
.badge-active { background: var(--success-tint); color: var(--success); }
.badge-past_due { background: var(--warning-tint); color: var(--warning); }
.badge-canceled { background: var(--danger-tint); color: var(--danger); }

/* The admin marker wears the gold insignia, like badge-completed. */
.badge-admin { background: var(--surface-strong); color: var(--text-on-strong); }

/* IPs, timestamps, event types: data, set in the mono data voice. */
.admin-mono {
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  color: var(--text-muted);
}

/* Label/value pairs on the account detail card; labels echo table headers. */
.admin-details {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: var(--space-2-5) var(--space-6);
  margin: 0;
}
.admin-details dt {
  font-family: var(--font-mono);
  font-size: var(--text-2xs);
  font-weight: var(--weight-medium);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-muted);
  align-self: center;
}
.admin-details dd { margin: 0; }

/* Day/phase section headings inside the game event timeline. */
.admin-timeline h3 {
  margin: var(--space-6) 0 var(--space-2);
  padding-top: var(--space-3);
  border-top: var(--border-hair) solid var(--line-subtle);
}
