/* ---------------------------------------------------------------------------
   Party Mode skin for the core app.

   When Party Mode is on, <html> carries data-party="on" (set before first
   paint by the head script, kept in step by app.js). The page becomes the
   same gameshow set as the TV wall and the takeovers: electric violet stage,
   slow sunburst, marquee bulbs, Archivo display type, and white "podium"
   cards with ink outlines and hard offset shadows.

   How it holds together:
   - The stage areas (masthead, control bar, main, tab bar) swap the text and
     line tokens to light-on-violet values.
   - Every surface that sits on the stage (cards, inputs, chips, meters...)
     restores the scheme's own tokens, captured at :root as --sf-*, so
     everything inside a card reads exactly as it does without Party Mode.
   - Party colours (--p-*) are untouched, so the data stays honest.
   The wall (.wall.pm-on) and takeovers style themselves in party-mode.css.
   --------------------------------------------------------------------------- */

:root[data-party="on"] {
  --pm-stage: #3613c9;
  --pm-stage-2: #2b0ca6;
  --pm-deep: #1c0670;
  --pm-ink: #14072e;
  --pm-yellow: #ffd23f;
  --pm-pink: #ff3e8a;
  --pm-cyan: #3fe3ff;
  --pm-soft: #ddd4ff;
  --pm-display: "Archivo", "IBM Plex Sans", sans-serif;

  /* Light cards: cool the warm neutrals towards the set's violet. */
  --bg: #f6f4ff;
  --surface-2: #f5f2ff;
  --surface-3: #ebe6ff;
  --line: #e1dbf7;
  --line-strong: #c4b9ee;
  --ink: #14072e;
  --body: #2b2250;
  --muted: #5e5690;
  --empty: #e8e3fa;
  --accent: #d1135f;
  --accent-soft: #ffe8f1;
  --on-accent: #fff;

  --r-card: 14px;
  --r: 9px;
  --pm-line: 2.5px;
  --pm-drop: 6px;
}
:root[data-party="on"][data-scheme="dark"] {
  /* Dark cards: deep violet rather than warm black. */
  --bg: #0f0430;
  --surface: #1a0b48;
  --surface-2: #211156;
  --surface-3: #2b1a6b;
  --line: #33227a;
  --line-strong: #4f3c9c;
  --ink: #ffffff;
  --body: #e4defc;
  --muted: #b3a8e6;
  --empty: #2a1a66;
  --accent: #ff6aa6;
  --accent-soft: #3a0f35;
  --on-accent: #1a0418;
}

/* Capture the card palette (whatever the scheme) before the stage overrides it. */
:root[data-party="on"] {
  --sf-bg: var(--bg);
  --sf-surface: var(--surface);
  --sf-surface-2: var(--surface-2);
  --sf-surface-3: var(--surface-3);
  --sf-line: var(--line);
  --sf-line-strong: var(--line-strong);
  --sf-ink: var(--ink);
  --sf-body: var(--body);
  --sf-muted: var(--muted);
  --sf-accent: var(--accent);
  --sf-accent-soft: var(--accent-soft);
  --sf-on-accent: var(--on-accent);
}

/* ---------- The set ---------- */
:root[data-party="on"] body {
  background:
    radial-gradient(ellipse 80% 45% at 50% 100%, #ff3e8a55, transparent 70%),
    radial-gradient(ellipse 90% 70% at 50% 40%, transparent 50%, #12045288),
    var(--pm-stage);
  background-attachment: fixed;
  isolation: isolate;
}
:root[data-party="on"][data-scheme="dark"] body {
  background:
    radial-gradient(ellipse 80% 45% at 50% 100%, #ff3e8a3a, transparent 70%),
    radial-gradient(ellipse 90% 70% at 50% 40%, transparent 45%, #08011faa),
    var(--pm-deep);
  background-attachment: fixed;
}
:root[data-party="on"] body::before {
  content: "";
  position: fixed;
  z-index: -1;
  left: 50%;
  top: 100%;
  width: 260vmax;
  height: 260vmax;
  margin: -130vmax 0 0 -130vmax;
  background: repeating-conic-gradient(
    from 0deg,
    #ffffff0e 0deg 7deg,
    transparent 7deg 14deg
  );
  animation: pm-spin 240s linear infinite;
  will-change: transform;
  pointer-events: none;
}

/* Stage areas: light text and glassy lines straight on the violet. */
:root[data-party="on"] .masthead,
:root[data-party="on"] .fstrip,
:root[data-party="on"] .controlbar,
:root[data-party="on"] main,
:root[data-party="on"] .tabbar {
  --bg: var(--pm-ink);
  --surface: #ffffff;
  --surface-2: #ffffff14;
  --surface-3: #ffffff24;
  --line: #ffffff2e;
  --line-strong: #ffffff55;
  --ink: #ffffff;
  --body: #f1edff;
  --muted: var(--pm-soft);
  --accent: var(--pm-yellow);
  --accent-soft: #ffd23f26;
  --on-accent: var(--pm-ink);
}

/* Surfaces on the stage: back to the card palette. */
:root[data-party="on"]
  :is(
    .card,
    .countdown span,
    .count-meter,
    .mini-stats div,
    .pulse-cell,
    .chip,
    .button:not(.ghost, .primary),
    .search,
    .seat-list,
    .signin-nudge,
    .stepper,
    .rc-pick,
    .rc-stats > div,
    .pace-target,
    .replay-chip,
    .hx-tip,
    select,
    input,
    textarea
  ) {
  --bg: var(--sf-bg);
  --surface: var(--sf-surface);
  --surface-2: var(--sf-surface-2);
  --surface-3: var(--sf-surface-3);
  --line: var(--sf-line);
  --line-strong: var(--sf-line-strong);
  --ink: var(--sf-ink);
  --body: var(--sf-body);
  --muted: var(--sf-muted);
  --accent: var(--sf-accent);
  --accent-soft: var(--sf-accent-soft);
  --on-accent: var(--sf-on-accent);
}
:root[data-party="on"] main {
  color: var(--body);
}
/* main hands its light text colour down as a value, so surfaces take theirs back. */
/* Zero specificity: it only beats inheritance, never a component's own colour. */
:where(:root[data-party="on"])
  :where(
    .card,
    .help-card,
    .countdown span,
    .count-meter,
    .mini-stats div,
    .pulse-cell,
    .chip,
    .button:not(.ghost, .primary),
    .search,
    .seat-list,
    .signin-nudge,
    .stepper,
    .rc-pick,
    .rc-stats > div,
    .pace-target,
    .replay-chip,
    .hx-tip
  ) {
  color: var(--body);
}
/* Button surfaces inherit through the base button rule, so name them. */
:root[data-party="on"] :is(.chip, .rc-pick, .replay-chip):not(.on) {
  color: var(--ink);
}
:where(:root[data-party="on"]) :where(select, input, textarea) {
  color: var(--ink);
}

/* The forecast strip under the masthead: part of the ink bar. */
:root[data-party="on"] .fstrip {
  background: color-mix(in srgb, var(--pm-ink) 92%, transparent);
  border-bottom: 0;
  color: var(--pm-soft);
}
:root[data-party="on"] .fstrip b {
  color: var(--pm-yellow);
}
:root[data-party="on"] .fs-kicker {
  color: #fff;
  font-style: italic;
  font-weight: 800;
}

/* ---------- Masthead: the ink bar over the set ---------- */
:root[data-party="on"] .masthead {
  background: var(--pm-ink);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-bottom: 0;
  box-shadow: inset 0 -4px 0 var(--pm-pink);
  color: #fff;
}
:root[data-party="on"] .brand-text {
  font-family: var(--pm-display);
  font-stretch: 78%;
  font-weight: 900;
  font-style: italic;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  font-size: 16px;
  line-height: 1;
}
:root[data-party="on"] .brand-text small {
  font-family: var(--font);
  font-style: normal;
  font-stretch: 100%;
  text-transform: none;
  font-weight: 600;
  margin-top: 3px;
  color: var(--pm-yellow);
}
:root[data-party="on"] .brand-mark {
  background: var(--pm-yellow);
  border-radius: 6px;
  transform: skew(-10deg);
}
:root[data-party="on"] .brand-mark i {
  background: var(--pm-ink);
}
:root[data-party="on"] .brand-mark i:nth-child(2) {
  background: var(--pm-pink);
}
/* The nav scrolls sideways, so it clips: give the active tab's skew and offset
   shadow room inside it, and take the same back outside so nothing moves. */
:root[data-party="on"] .nav {
  padding: 5px 6px 6px 4px;
  margin: -5px 0 -6px 4px;
}
:root[data-party="on"] .nav button {
  font-weight: 700;
  color: var(--pm-soft);
}
:root[data-party="on"] .nav button:hover {
  color: #fff;
  background: #ffffff1c;
}
:root[data-party="on"] .nav button.on {
  color: var(--pm-ink);
  background: var(--pm-yellow);
  box-shadow: 3px 3px 0 var(--pm-pink);
  transform: skew(-8deg);
  border-radius: 6px;
}
:root[data-party="on"] .nav button.on > * {
  transform: skew(8deg);
}
:root[data-party="on"] .clock {
  font-family: var(--pm-display);
  font-stretch: 75%;
  font-weight: 900;
  font-style: italic;
  font-size: 17px;
  color: var(--pm-yellow);
}
:root[data-party="on"] .status-pill {
  background: #ffffff1c;
  color: #fff;
}
:root[data-party="on"] .status-pill.live {
  background: var(--pm-pink);
  color: #fff;
}
:root[data-party="on"] .status-pill.rehearsal {
  background: var(--pm-yellow);
  color: var(--pm-ink);
}
:root[data-party="on"] .masthead .icon-button {
  background: #ffffff1c;
  color: #fff;
}
:root[data-party="on"] .masthead .button.ghost:hover,
:root[data-party="on"] .masthead .icon-button:hover {
  background: #ffffff30;
}
:root[data-party="on"] .party-toggle.on {
  background: var(--pm-pink);
  border-color: var(--pm-pink);
  color: #fff;
  transform: skew(-8deg);
}
:root[data-party="on"] .party-toggle.on:hover {
  background: #ff5c9d;
  border-color: #ff5c9d;
}
:root[data-party="on"] .party-toggle.on > * {
  transform: skew(8deg);
}

/* ---------- Control bar: the lower third, with chasing bulbs ---------- */
:root[data-party="on"] .controlbar {
  position: relative;
  background: var(--pm-stage-2);
  border-bottom: 0;
  padding-bottom: 12px;
}
:root[data-party="on"][data-scheme="dark"] .controlbar {
  background: #170552;
}
:root[data-party="on"] .controlbar::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 12px;
  --bulb: radial-gradient(
    circle,
    var(--pm-yellow) 0 3px,
    #ffd23f55 3.5px 5px,
    transparent 5.5px
  );
  background: var(--bulb) 0 50% / 24px 12px repeat-x;
  animation: pm-chase 1.2s steps(2) infinite;
  pointer-events: none;
}
:root[data-party="on"] .source-note strong {
  font-family: var(--pm-display);
  font-stretch: 80%;
  font-weight: 900;
  font-style: italic;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--pm-yellow);
}
:root[data-party="on"] .play {
  background: var(--pm-yellow);
  color: var(--pm-ink);
}
:root[data-party="on"] .play.on {
  background: var(--pm-pink);
  color: #fff;
}
:root[data-party="on"] .controlbar input[type="range"] {
  accent-color: var(--pm-yellow);
}

/* ---------- Display type ---------- */
:root[data-party="on"]
  :is(.headline, .page-head h1, .detail-head h1, .loading h1) {
  font-family: var(--pm-display);
  font-stretch: 72%;
  font-weight: 900;
  font-style: italic;
  text-transform: uppercase;
  letter-spacing: -0.005em;
  line-height: 0.9;
  color: #fff;
  text-shadow: 0.05em 0.05em 0 var(--pm-pink);
}
:root[data-party="on"] .headline {
  font-size: clamp(40px, 5.6vw, 76px);
  max-width: 22ch;
}
:root[data-party="on"] :is(.page-head h1, .detail-head h1) {
  font-size: clamp(36px, 5.4vw, 68px);
}
:root[data-party="on"] :is(.hero-sub, .page-head p) {
  color: var(--pm-soft);
  font-weight: 500;
}
:root[data-party="on"] .card h2 {
  font-family: var(--pm-display);
  font-stretch: 78%;
  font-weight: 900;
  font-style: italic;
  text-transform: uppercase;
  letter-spacing: 0;
  font-size: 22px;
  line-height: 1;
}

/* Kickers become slugs: yellow on the stage, ink inside cards. */
:root[data-party="on"] .kicker {
  display: inline-block;
  width: fit-content;
  font-family: var(--pm-display);
  font-stretch: 85%;
  font-weight: 900;
  font-style: italic;
  letter-spacing: 0.06em;
  padding: 4px 10px 3px;
  border-radius: 3px;
  transform: skew(-10deg);
  background: var(--pm-yellow);
  color: var(--pm-ink);
}
:root[data-party="on"] main > * > .kicker,
:root[data-party="on"] :is(.hero, .page-head, .loading) .kicker {
  box-shadow: 3px 3px 0 var(--pm-pink);
}
:root[data-party="on"] .card .kicker {
  margin-bottom: 4px;
  background: var(--ink);
  color: var(--surface);
  font-size: 10px;
}

/* ---------- Podium cards ---------- */
:root[data-party="on"] .card {
  border: var(--pm-line) solid var(--pm-ink);
  box-shadow: var(--pm-drop) var(--pm-drop) 0 var(--pm-ink);
}
:root[data-party="on"][data-scheme="dark"] .card {
  border-color: #000;
  box-shadow: var(--pm-drop) var(--pm-drop) 0 #07011a;
}
/* The headline cards on Tonight get the pink drop, as the wall's monitors do. */
:root[data-party="on"] :is(.card-r61, .card-chamber) {
  box-shadow:
    var(--pm-drop) var(--pm-drop) 0 var(--pm-pink),
    var(--pm-drop) var(--pm-drop) 0 var(--pm-line) var(--pm-ink);
}
/* Hard shadows eat into the gaps, so the set spaces cards a little wider.
   Cards inside a grid keep their row alignment (no stacked margin). */
:root[data-party="on"] main {
  --pm-gap: 24px;
}
:root[data-party="on"]
  :is(.card, .grid-main, .pulse)
  + :is(.card, .grid-main):not(.grid-main > *, .grid-stack > *, .lab > *) {
  margin-top: var(--pm-gap);
}
:root[data-party="on"] :is(.grid-main, .grid-stack, .lab) {
  gap: var(--pm-gap);
}
@media (max-width: 860px) {
  :root[data-party="on"] main {
    --pm-gap: 18px;
  }
}

/* The countdown: a gameshow clock. */
:root[data-party="on"] .countdown span {
  border: var(--pm-line) solid var(--pm-ink);
  background: var(--pm-yellow);
  color: var(--pm-ink);
  box-shadow: 4px 4px 0 var(--pm-ink);
  font-weight: 800;
}
:root[data-party="on"] .countdown b {
  font-family: var(--pm-display);
  font-stretch: 75%;
  font-weight: 900;
  font-style: italic;
  font-size: 40px;
  color: var(--pm-ink);
}
:root[data-party="on"] :is(.count-meter, .mini-stats div, .pulse-cell) {
  border: var(--pm-line) solid var(--pm-ink);
  box-shadow: 4px 4px 0 var(--pm-ink);
}

/* ---------- Buttons ---------- */
:root[data-party="on"] .button.primary {
  background: var(--pm-yellow);
  border: var(--pm-line) solid var(--pm-ink);
  color: var(--pm-ink);
  font-weight: 800;
  box-shadow: 4px 4px 0 var(--pm-ink);
}
:root[data-party="on"] .button.primary:hover {
  filter: none;
  background: #ffdc66;
}
:root[data-party="on"] .button.primary:active {
  transform: translate(2px, 2px);
  box-shadow: 2px 2px 0 var(--pm-ink);
}
:root[data-party="on"] main .button:not(.ghost, .primary) {
  border: var(--pm-line) solid var(--pm-ink);
  box-shadow: 3px 3px 0 var(--pm-ink);
}
:root[data-party="on"] main .button.ghost {
  color: var(--ink);
}
:root[data-party="on"] .pm-hero-button.on {
  background: var(--pm-pink);
  border: var(--pm-line) solid var(--pm-ink);
  color: #fff;
  box-shadow: 4px 4px 0 var(--pm-ink);
}
:root[data-party="on"] .pm-hero-button.on:hover {
  background: #ff5c9d;
  border-color: var(--pm-ink);
}

/* ---------- Phones: the tab bar is the ink bar too ---------- */
:root[data-party="on"] .tabbar {
  background: var(--pm-ink);
  border-top: 0;
  box-shadow: inset 0 4px 0 var(--pm-pink);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
:root[data-party="on"] .tabbar button {
  color: var(--pm-soft);
}
:root[data-party="on"] .tabbar button.on {
  color: var(--pm-yellow);
}

/* ---------- Overlays ---------- */
:root[data-party="on"] .help-card {
  border: var(--pm-line) solid var(--pm-ink);
  box-shadow: 8px 8px 0 var(--pm-pink);
}
:root[data-party="on"] .help-card h2 {
  font-family: var(--pm-display);
  font-stretch: 78%;
  font-weight: 900;
  font-style: italic;
  text-transform: uppercase;
}
:root[data-party="on"] .toast {
  background: var(--pm-ink);
  color: #fff;
  border: var(--pm-line) solid var(--pm-yellow);
  box-shadow: 5px 5px 0 var(--pm-pink);
}
:root[data-party="on"] :focus-visible {
  outline-color: var(--pm-cyan);
}
:root[data-party="on"] .card :focus-visible {
  outline-color: var(--sf-accent);
}

@media (max-width: 860px) {
  :root[data-party="on"] .card {
    --pm-drop: 4px;
  }
  :root[data-party="on"] .countdown b {
    font-size: 32px;
  }
}
@media (prefers-reduced-motion: reduce) {
  :root[data-party="on"] body::before,
  :root[data-party="on"] .controlbar::after {
    animation: none !important;
  }
}

/* ---------- The TV wall ---------- */
/* The wall's data scenes sit in monitors on the set (party-mode.css). Give the
   monitors the same deep violet as the app's dark Party Mode cards, rather
   than the warm black of the plain wall. Party colours are unchanged. */
.wall.pm-on {
  --bg: #0f0430;
  --surface: #1a0b48;
  --surface-2: #211156;
  --surface-3: #2b1a6b;
  --line: #33227a;
  --line-strong: #4f3c9c;
  --ink: #ffffff;
  --body: #e4defc;
  --muted: #b3a8e6;
  --empty: #2a1a66;
  --accent: #ff6aa6;
  --accent-soft: #3a0f35;
  --on-accent: #1a0418;
}
/* The monitor frame takes room the plain wall uses for content, so data
   scenes run a touch smaller inside it and still fit the screen. */
.wall.pm-on
  .w-scene:not(
    [data-scene="party"],
    [data-scene="hot-races"],
    [data-scene="chriswatch"]
  ) {
  --u: calc(min(1vw, 1.78vh) * 0.9);
}
/* The two tallest scenes need a little more off to clear the frame. */
.wall.pm-on .w-scene[data-scene="seat"] {
  --u: calc(min(1vw, 1.78vh) * 0.8);
}
.wall.pm-on .w-scene[data-scene="bubble"] {
  --u: calc(min(1vw, 1.78vh) * 0.72);
}
/* Seat names get the set's display type, like the other scene titles. */
.wall.pm-on .w-dive-head h1 {
  font-family: var(--pm-display, "Archivo", sans-serif);
  font-stretch: 74%;
  font-weight: 900;
  font-style: italic;
  text-transform: uppercase;
  letter-spacing: 0;
}
/* National scene: the scoreboard says who is short or over, so the subtitle
   steps aside and the headline sets smaller, leaving the wheel room to read. */
.wall.pm-on .w-scene[data-scene="national"] .w-sub {
  display: none;
}
.wall.pm-on .w-scene[data-scene="national"] .w-headline {
  font-size: calc(var(--u) * 3.1);
}

/* ---------- Faces ----------
   Every face carries the illustrated portrait when one exists (app.js face()).
   Under Party Mode it replaces the official photo or initials, on a disc
   tinted with the party colour so the cutout reads as a contestant badge. */
:root[data-party="on"] .face.has-pm-face {
  background: color-mix(in srgb, var(--c, var(--muted)) 26%, var(--sf-surface, #fff));
}
:root[data-party="on"] .face.has-pm-face > :not(.pm-face) {
  display: none;
}
:root[data-party="on"] .face.has-pm-face > .pm-face {
  display: block;
}
