/* CheerKeeper — Judge App prototype
   Light theme, arena-legible. Two-level surface system: a light-gray app
   canvas with pure-white cards that carry BOTH a shadow and a hairline
   border, so separation survives glare and cheap tablet screens.
   Purple #6B4E9E — the value in --purple below, and the one the real
   CheerKeeper app uses — is reserved for active tab, primary Submit, and
   confirmed-state reinforcement, never for suggested values. This line
   previously quoted a different hex that was never the token's value and
   never what rendered; the token is and always was the source of truth. */

:root {
  /* ============================================================
     REAL CheerKeeper tokens, read from ~/cheerkeeper/cheerkeeper-app
       fonts   app/_layout.tsx  -> @expo-google-fonts/montserrat
       rest    src/utils/constants.ts (the app's design-system file)
       tab bar app/(tabs)/_layout.tsx
     Values marked "derived" are not in the app source; they exist only
     where the prototype needs a step the app doesn't define, or where an
     app colour fails WCAG AA as small text.
     ============================================================ */

  /* -- font: Montserrat, the five weights the app actually loads -- */
  --font: 'Montserrat', -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --w-light: 300;
  --w-regular: 400;
  --w-medium: 500;
  --w-semibold: 600;
  --w-bold: 700;

  /* -- colours: constants.ts `colors` -- */
  --purple:       #6B4E9E;   /* primaryPurple */
  --purple-ink:   #3D2963;   /* deepPurple    */
  --purple-light: #9B7BC7;   /* lightPurple   */
  --orange:       #F5A623;   /* orange / warning */
  --blue:         #4A90D9;
  --coral:        #E85A5A;   /* coral / error / red */
  --white:        #FFFFFF;
  --light-gray:   #F5F5F5;   /* app page background */
  --medium-gray:  #424242;   /* label + muted text  */
  --dark-gray:    #4A4A4A;   /* heading text        */
  --success:      #4CAF50;

  /* -- surfaces -- */
  --bg:        #F5F5F5;      /* lightGray, the app's scroll background */
  --bg-sunk:   #ECECEC;      /* derived */
  --surface:   #FFFFFF;
  --surface-2: #FAFAFA;      /* derived */
  --hairline:  #E5E5E5;      /* tab-bar + card borders in the app */
  --hairline-2:#DCDCDC;      /* derived */
  --purple-soft: #F0EDF7;    /* the app's lavender tint */
  --purple-soft-2: #F5F0FF;  /* second lavender seen in components */
  --purple-line: #D8CCE9;    /* derived from lightPurple */

  /* -- text -- */
  --text:   #4A4A4A;         /* darkGray  ~9.0:1 */
  --text-2: #424242;         /* mediumGray ~10.4:1 */
  --text-3: #6E6E6E;         /* derived, ~5.1:1 — still AA */
  --text-muted: #757575;     /* derived; 4.61:1 on white — the AA floor,
                                used where something must read clearly
                                secondary (inactive segmented tab) */

  /* -- semantic. The raw app colours are fills; the -ink values are
        darkened derivations so small text clears AA 4.5:1. -- */
  --good:   #2E7D32;  --good-fill: #4CAF50;  --good-bg: #EDF7EE;  --good-line: #B7DFB9;
  /* One step darker again, for SMALL UPPERCASE green text on --good-bg.
     --good clears AA there at 4.67:1, but only just, and 10px semibold with
     letter-spacing reads thin at that ratio. This lands at 7.17:1 (AAA) and
     stays in the same green family. Deliberately a separate token: --good
     itself is load-bearing for the sync chip, status chip, submit button
     and meter, none of which should shift. */
  --good-ink: #1B5E20;
  --warn:   #8A5A00;  --warn-fill: #F5A623;  --warn-bg: #FDF3E0;  --warn-line: #EFD5A3;
  --danger: #B3352F;  --danger-fill: #E85A5A; --danger-bg: #FDEDED; --danger-line: #F3C6C6;

  /* -- spacing scale: constants.ts `spacing` -- */
  --sp-xs: 4px; --sp-sm: 8px; --sp-md: 12px; --sp-lg: 16px; --sp-xl: 24px; --sp-xxl: 32px;

  /* -- radius: constants.ts `borderRadius` -- */
  --r-sm: 4px; --r-md: 8px; --r-lg: 12px; --r-xl: 16px; --r-full: 9999px;

  /* -- type scale: constants.ts `fontSize` -- */
  --fs-xs: 10px; --fs-sm: 12px; --fs-md: 14px; --fs-lg: 16px;
  --fs-xl: 18px; --fs-xxl: 20px; --fs-xxxl: 24px; --fs-title: 32px;

  /* -- card: SingleEventShortcut.tsx
        white, radius lg, shadow #000 0/1 blur4 @5%, no border by default.
        The prototype adds a hairline so cards survive arena glare. -- */
  --e1: 0 1px 4px rgba(0, 0, 0, 0.05);
  --e2: 0 2px 8px rgba(0, 0, 0, 0.07);
  --e3: 0 6px 18px rgba(61, 41, 99, 0.14), 0 1px 3px rgba(0, 0, 0, 0.06);

  /* iOS-style record red — not part of the app palette, but a record
     control that isn't red reads as something else entirely. */
  --record-red: #E0352B;
  --record-red-deep: #B8261E;

  --tap: 56px;
  --pad: 16px;

  /* -- notch insets, resolved in ONE place --
     env() is isolated here rather than written inline inside a shorthand
     like `padding: calc(16px + env(...)) 24px 16px`. Safari has historically
     dropped a whole shorthand it cannot parse, which would take the top
     padding with it and collapse the inset to nothing. A custom property
     fails soft — it just resolves to the 0px fallback — and it gives the
     headless tests something they can override to simulate a real device. */
  --sat: env(safe-area-inset-top, 0px);
  --sab: env(safe-area-inset-bottom, 0px);
  /* Landscape on a notched phone insets the sides too. The drawer's white
     must still reach the true screen edge, so only its CONTENT pads. */
  --sal: env(safe-area-inset-left, 0px);
  --sar: env(safe-area-inset-right, 0px);
}

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

/* Several hideable elements below are flex/grid, which beats the UA
   [hidden] rule. Make `hidden` mean hidden, everywhere. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  /* WHITE, deliberately. With apple-mobile-web-app-status-bar-style set to
     black-translucent the web view now renders BEHIND the clock/wifi/battery,
     and that band picks up the document background. A gray body would paint
     a gray strip there — which is exactly the reported bug. The light-gray
     canvas lives on the screen containers instead, never on the document. */
  background: #ffffff;
  color: var(--text);
  font-family: var(--font);
  font-size: var(--fs-lg);
  font-weight: var(--w-regular);
  line-height: 1.4;
  overflow-x: hidden;
  -webkit-text-size-adjust: 100%;
}
button { font-family: inherit; color: inherit; }

/* ---- NO TAP FEEDBACK, ANYWHERE ----
   There is deliberately not one `:active` rule in this stylesheet. Every
   control used to repaint on press — keypad keys and step buttons flashed
   purple, pills and icon buttons dimmed to ~50%, rows and popover items lit
   lavender, submit darkened — and on a fast-moving scoring pass that whole
   layer read as the screen flickering under the thumb.
   Confirmation is audio + haptic (cue.js); the visible answer is the thing
   that actually changed — a dot filling, a value moving, a toast. If a new
   control needs press feedback, that is the bar it has to clear.

   `:disabled` opacity and `.is-standby` are NOT this: they are persistent
   states, not responses to a tap. The two `:focus` rings on text inputs
   stay for keyboard accessibility. */

/* The canvas colour rides on the screens, not on body — see the note above. */
.screen { display: none; background: var(--bg); }
body[data-screen="home"]  #screen-home  { display: flex; flex-direction: column; min-height: 100dvh; }
body[data-screen="judge"] #screen-judge { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
body[data-screen="score"] #screen-score { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
body[data-screen="producer"] #screen-producer { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
body[data-screen="review"] #screen-review { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
/* The awards spine — same skeleton as the verify review, so a producer
   moving between them never re-learns the screen. */
body[data-screen="live"]    #screen-live    { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
/* The hall coordinator's tablet. Same skeleton, and deliberately NOT a
   console screen: `coordinator` is absent from CONSOLE_SCREENS, so the
   desktop admin shell never wraps it however wide the device is. */
body[data-screen="coordinator"] #screen-coordinator { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
body[data-screen="pdetail"] #screen-pdetail { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
body[data-screen="master"]  #screen-master  { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
body[data-screen="awards"]  #screen-awards  { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
body[data-screen="coach"] #screen-coach { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
body[data-screen="family"] #screen-family { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
/* position: relative so the floating FILTERS pill anchors to the screen
   rather than to the viewport. */
body[data-screen="famsched"] #screen-famsched { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; position: relative; }
body[data-screen="famdetail"] #screen-famdetail { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }
body[data-screen="cadetail"] #screen-cadetail { display: flex; flex-direction: column; height: 100dvh; overflow: hidden; }


/* ============================================================
   ENTRY — event code, judge name, judge code.
   Lives entirely in the bottom sheet; there is no sign-in screen.
   ============================================================ */
/* Plain full-width name rows — text only, no icon, not a tile. */
.name-list { display: flex; flex-direction: column; gap: var(--sp-sm); margin-bottom: var(--sp-sm); }
.name-row {
  display: block; width: 100%; text-align: left; cursor: pointer;
  min-height: var(--tap); padding: var(--sp-md) var(--sp-lg);
  border: 1px solid var(--hairline); border-radius: var(--r-lg);
  background: var(--surface);
  font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text);
}

/* -- code keypad, shared by both code steps -- */
.pin-dots { display: flex; gap: var(--sp-md); justify-content: center; margin-bottom: var(--sp-sm); }
.pin-dot {
  width: 14px; height: 14px; border-radius: var(--r-full);
  border: 1px solid var(--purple-line); background: var(--surface);
}
.pin-dot.is-filled { background: var(--purple); border-color: var(--purple); transform: scale(1.15); }
.pin-keys { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-sm); width: 100%; max-width: 300px; margin: 0 auto; }
.pin-key {
  min-height: 60px; border-radius: var(--r-lg); border: 1px solid var(--hairline);
  background: var(--surface); box-shadow: var(--e1);
  font-size: var(--fs-xxxl); font-weight: var(--w-medium); color: var(--text); cursor: pointer;
}
.pin-key.is-back { font-size: var(--fs-xl); color: var(--text-2); background: var(--surface-2); }
.pin-hint { margin: 0 0 var(--sp-md); font-size: var(--fs-sm); font-weight: var(--w-regular); color: var(--text-2); text-align: center; }


/* ============================================================
   JUDGE AREA — white top strip
   ============================================================ */
.judge-top {
  flex: none; z-index: 20; position: relative;
  display: flex; align-items: center; gap: var(--sp-sm);
  background: var(--surface);
  border-bottom: 1px solid var(--hairline);
  padding: calc(8px + var(--sat)) var(--pad) 8px;
}
.judge-top-title {
  /* centred against the strip, not against the space left over by the
     controls, so it stays put as the right slot changes width */
  position: absolute; left: 0; right: 0; margin: 0;
  top: calc(var(--sat) + 8px);
  text-align: center; pointer-events: none;
  font-size: var(--fs-xl); font-weight: var(--w-bold); color: var(--text); letter-spacing: -0.2px;
}
.judge-top-right { margin-left: auto; display: flex; align-items: center; gap: var(--sp-sm); z-index: 1; }

/* Bare controls — hamburger, back chevron, share. No box: the main app
   draws these as glyphs alone, and a boxed control directly under the
   status bar read as a rectangle around the phone clock. */
.icon-btn {
  flex: none; width: 34px; height: 34px; border: none; background: none;
  cursor: pointer; display: grid; place-items: center; color: var(--text);
  z-index: 1; padding: 0;
}
.burger-glyph { display: flex; flex-direction: column; gap: 4px; }
.burger-glyph span { display: block; width: 18px; height: 2px; border-radius: 1px; background: var(--text); }
/* SVG so it optically centres against the title — the ‹ character sits
   high in its em box and read as sitting above the event name */
.chev-left { width: 24px; height: 24px; display: block; color: var(--text); }

/* Change role — a plain text label with a small chevron, like the main
   app's date and hall controls. No outline, no filled pill. */
.role-pill {
  flex: none; display: inline-flex; align-items: center; gap: 3px;
  min-height: 34px; padding: 5px 2px; border: none; background: none;
  color: var(--purple); font-size: var(--fs-md); font-weight: var(--w-semibold);
  cursor: pointer; max-width: 190px;
}
.role-pill-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* one chevron glyph for every dropdown — role, date, room — at the main
   app's size rather than a small rotated angle-quote */
.chev-down { flex: none; width: 18px; height: 18px; display: block; }

.sync-chip {
  flex: none; border-radius: 999px; padding: 5px 11px;
  font-size: 11.5px; font-weight: 700; cursor: pointer;
  border: 1px solid var(--hairline); background: var(--surface-2); color: var(--text-2);
}
.sync-chip[data-state="synced"]  { background: var(--good-bg);   border-color: var(--good-line);   color: var(--good); }
.sync-chip[data-state="syncing"] { background: var(--warn-bg);   border-color: var(--warn-line);   color: var(--warn); }
.sync-chip[data-state="offline"] { background: var(--danger-bg); border-color: var(--danger-line); color: var(--danger); }

.status-chip {
  display: inline-block; font-size: 10.5px; font-weight: var(--w-bold);
  letter-spacing: 0.4px; padding: 3px 8px; border-radius: 7px;
  border: 1px solid var(--hairline); background: var(--surface); color: var(--text-2);
  white-space: nowrap;
}
.status-chip[data-status="upnow"]     { background: var(--purple-soft); border-color: var(--purple-line); color: var(--purple-ink); }
.status-chip[data-status="scored"]    { background: var(--warn-bg);     border-color: var(--warn-line);   color: var(--warn); }
.status-chip[data-status="submitted"] { background: var(--good-bg);     border-color: var(--good-line);   color: var(--good); }

/* ---- panels ---- */
.panels { flex: 1 1 auto; min-height: 0; position: relative; }
.panel { display: none; height: 100%; }
body[data-tab="sessions"] #jtab-sessions,
body[data-tab="status"]   #jtab-status,
body[data-tab="me"]       #jtab-me { display: flex; flex-direction: column; }

.panel-scroll { gap: 14px; padding: 14px; overflow-y: auto; -webkit-overflow-scrolling: touch; }
/* The Sessions tab holds two levels; `view` decides which one is mounted. */
#jtab-sessions > .panel-scroll { display: none; flex: 1 1 auto; min-height: 0; flex-direction: column; }
body[data-view="sessions"] #sessionCards,
body[data-view="perf"]     #perfWrap { display: flex; }
/* The list rows carry their own hairlines, so the wrap adds no padding */
#perfWrap { padding: 0; gap: 0; }

/* ---- cards ---- */
.card {
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--e1); padding: 9px var(--sp-md);
}
.card.is-focus { box-shadow: var(--e3); }
.card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 7px; flex-wrap: wrap; }
/* the app's uppercase section label: 10px semibold, 1px tracking, mediumGray */
.section-label, .card-title, .total-label, .confirm-eyebrow {
  margin: 0; font-size: var(--fs-xs); font-weight: var(--w-semibold);
  text-transform: uppercase; letter-spacing: 1px; color: var(--text-2);
}
.card-note { flex: 1 1 auto; font-size: 11.5px; color: var(--text-2); min-width: 0; }
.card-foot { margin: 10px 0 0; font-size: 11.5px; color: var(--text-2); line-height: 1.45; }
.empty-line { margin: 4px 0; font-size: 13.5px; color: var(--text-2); line-height: 1.45; }


/* ============================================================
   Cockpit — running total
   ============================================================ */
.total-card {
  flex: none;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--e2);
  padding: 7px 12px 8px;
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 10px;
}
.total-main { min-width: 0; }
.total-label {
  display: block; font-size: 11px; font-weight: var(--w-bold);
  text-transform: uppercase; letter-spacing: 0.9px; color: var(--text-2);
}
.total-value {
  display: block; font-size: 34px; font-weight: var(--w-bold); line-height: 1.04;
  letter-spacing: -1.4px; font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1; color: var(--text);
}
.total-card.is-submitted .total-value { color: var(--good); }
.total-side { display: flex; gap: 6px; align-items: flex-start; }
.stat-tile {
  display: block; text-align: center;
  background: var(--surface-2); border: 1px solid var(--hairline);
  border-radius: 10px; padding: 2px 8px; min-width: 78px;
}
.stat-tile em { display: block; font-style: normal; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-2); }
.stat-tile b { display: block; font-size: 14px; font-weight: var(--w-bold); font-variant-numeric: tabular-nums; }

.total-flag {
  grid-column: 1 / -1;
  display: flex; align-items: center; gap: 6px;
  margin-top: 4px; padding: 4px 9px; border-radius: 9px;
  font-size: 11.5px; font-weight: 700;
}
.total-flag.is-pending { background: var(--warn-bg);  border: 1px solid var(--warn-line);  color: var(--warn); }
.total-flag.is-ready   { background: var(--purple-soft); border: 1px solid var(--purple-line); color: var(--purple-ink); }
.chip-glyph { width: 13px; height: 13px; flex: none; }


/* ============================================================
   Cockpit — difficulty (pre-staged, three states)
   ============================================================ */
.diff-card { flex: none; }
.diff-card .card-title { flex: none; }
.diff-card .card-note { flex-basis: 100%; order: 3; margin-top: 1px; }
.confirm-all {
  flex: none; margin-left: auto; min-height: 34px; padding: 6px 12px;
  border-radius: 10px; border: 1px solid var(--purple);
  background: var(--purple); color: #FFFFFF;
  font-size: 12.5px; font-weight: var(--w-bold); cursor: pointer;
}
.confirm-all.is-done {
  background: var(--good-bg); border-color: var(--good-line); color: var(--good);
}
.diff-rows { display: flex; flex-direction: column; gap: 6px; }

/* Two rows so the caption name and its state chip get the full width —
   squeezing them beside the stepper clipped both. The Confirm/revert
   action spans both rows, giving it a 56x88 target. */
.diff-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--tap);
  grid-template-areas: "label act" "stepper act";
  align-items: center; gap: 2px 10px;
  padding: 4px 4px 4px 9px; border-radius: 12px;
  border: 1px solid var(--hairline); background: var(--surface-2);
}
.diff-row .diff-label { grid-area: label; }
.diff-row .stepper { grid-area: stepper; }
.diff-row .diff-act { grid-area: act; }
/* three states carry weight + icon + text + border — never colour alone */
/* State is carried by fill + chip + numeral weight. Never by a heavier,
   recoloured or one-sided border — every border here is the same hairline. */
.diff-row.is-suggested  { background: var(--surface); }
.diff-row.is-confirmed  { background: var(--purple-soft); box-shadow: var(--e1); }
.diff-row.is-overridden { background: var(--warn-bg);    box-shadow: var(--e1); }

.diff-label { display: flex; align-items: center; gap: 8px; min-width: 0; }
.diff-cat { font-size: 15px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.state-chip {
  display: inline-flex; align-items: center; gap: 4px;
  align-self: flex-start;
  font-size: 10.5px; font-weight: var(--w-bold); letter-spacing: 0.3px;
  padding: 2px 7px; border-radius: 6px; white-space: nowrap;
}
.state-chip.state-suggested  { background: var(--bg-sunk);     border: 1px solid var(--hairline); color: var(--text-2); }
.state-chip.state-confirmed  { background: var(--purple-soft); border: 1px solid var(--purple-line); color: var(--purple-ink); }
.state-chip.state-overridden { background: var(--warn-bg);     border: 1px solid var(--warn-line);   color: var(--warn); }

.diff-act {
  width: var(--tap); height: 100%; min-height: var(--tap);
  border-radius: var(--r-lg); cursor: pointer;
  display: grid; place-items: center;
  border: 1px solid var(--hairline); background: var(--surface);
  box-shadow: var(--e1);
}
.diff-act .act-glyph { font-size: 22px; line-height: 1; font-weight: 700; }
.diff-act.is-confirm   { border-color: var(--purple); background: var(--purple); color: #FFFFFF; }
.diff-act.is-confirmed { border-color: var(--good-line); background: var(--good-bg); color: var(--good); box-shadow: none; }
.diff-act.is-revert    { border-color: var(--warn-line); background: var(--warn-bg); color: var(--warn); }
.diff-act:disabled { opacity: 0.4; box-shadow: none; }

/* Collapsed review state — one line, and the height goes to execution. */
.diff-summary {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; min-height: 52px; padding: 8px 10px;
  border-radius: 12px; border: 1px solid var(--hairline);
  background: var(--purple-soft); cursor: pointer; text-align: left;
  box-shadow: var(--e1);
}
.sum-main { min-width: 0; }
.sum-total { display: block; font-size: var(--fs-xxl); font-weight: var(--w-bold); font-variant-numeric: tabular-nums; line-height: 1.1; }
.sum-cats { display: block; font-size: 11.5px; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.diff-summary .state-chip { flex: none; }



/* ============================================================
   Cockpit — execution (the focused block)
   ============================================================ */
/* sized to content — leftover height collects once, below the aux row */
.exec-card { flex: none; display: flex; flex-direction: column; }
/* Stood down while difficulty is under review — still usable, just not
   the loudest thing on the screen. */
.exec-card.is-compact { flex: none; }
.exec-card.is-compact .stepper-lg .step-btn { width: var(--tap); height: var(--tap); font-size: 28px; }
.exec-card.is-compact .stepper-lg .step-value { min-height: var(--tap); font-size: 30px; }
.exec-card.is-compact .exec-hint { display: none; }
.exec-card.is-compact .exec-stage { gap: 4px; }


/* ============================================================
   Segmented caption tabs
   ============================================================ */
/* One connected control: a shared track with flush segments. The divider
   is a pseudo-element, not a border, so the single-hairline rule holds. */
.caption-pager {
  display: flex; align-items: stretch;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--r-md);
  overflow: hidden;
  margin-bottom: 6px;
}
.caption-pager.is-single { display: none; }

.pager-btn {
  position: relative; flex: 1 1 0; min-width: 0;
  min-height: 38px; padding: 4px 8px; cursor: pointer;
  border: none; background: transparent;
  display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 5px;
}
.pager-btn + .pager-btn::after {
  content: ''; position: absolute; left: 0; top: 7px; bottom: 7px;
  width: 1px; background: var(--hairline);
}
/* solid brand fill + white text — the two states must be obvious at a
   glance, not two near-identical light tints */
.pager-btn.is-active { background: var(--purple); }
/* no rule against a fill meeting a divider — just hide the seam */
.pager-btn.is-active::after,
.pager-btn.is-active + .pager-btn::after { background: transparent; }

.pager-mark { flex: none; width: 12px; height: 12px; border-radius: var(--r-full); position: relative; }
.pager-mark[data-state="suggested"] { border: 1px solid var(--hairline-2); background: var(--surface); }
.pager-mark[data-state="confirmed"], .pager-mark[data-state="overridden"] {
  border: 1px solid transparent; background-color: var(--purple);
}
.pager-mark[data-state="overridden"] { background-color: var(--warn-fill); }
.pager-mark[data-state="confirmed"]::after,
.pager-mark[data-state="overridden"]::after {
  content: ''; position: absolute; inset: 0;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M3 8.4l3.3 3.3L13 4.8' fill='none' stroke='%23fff' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 9px 9px no-repeat;
}
/* inactive segment keeps its white background; only the text is muted, and
   muted hard enough that the solid-purple active segment dominates */
.pager-label {
  font-size: var(--fs-sm); font-weight: var(--w-semibold); color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.pager-btn.is-active .pager-label,
.pager-btn.is-active .pager-value { color: var(--white); font-weight: var(--w-bold); }
.pager-btn.is-active .pager-sep { color: rgba(255, 255, 255, 0.72); }
/* on the filled segment the marker drops its disc — the tick reads white */
.pager-btn.is-active .pager-mark[data-state="confirmed"],
.pager-btn.is-active .pager-mark[data-state="overridden"] { background-color: transparent; }
.pager-btn.is-active .pager-mark[data-state="suggested"] {
  border-color: rgba(255, 255, 255, 0.85); background: transparent;
}
.pager-sep { flex: none; color: var(--text-3); font-size: var(--fs-sm); }
.pager-value { flex: none; font-size: var(--fs-md); font-weight: var(--w-bold); font-variant-numeric: tabular-nums; color: var(--text-muted); }

.ctx-chevron { flex: none; font-size: var(--fs-xxl); color: var(--text-3); margin-left: 2px; }


/* ============================================================
   Record button — iOS-style: red disc, ghosted white mic
   ============================================================ */
.record-btn {
  position: relative; flex: none;
  width: 40px; height: 40px; border-radius: var(--r-full);
  background: var(--record-red);
  border: 1px solid var(--hairline);
  display: grid; place-items: center; cursor: pointer;
  box-shadow: var(--e1);
}
.record-btn:disabled { opacity: 0.45; }
.record-mic {
  width: 18px; height: 18px; display: block;
  background-color: #FFFFFF; opacity: 0.92;
  -webkit-mask: url('icons/microphone.svg') center / contain no-repeat;
  mask: url('icons/microphone.svg') center / contain no-repeat;
}

/* aux-row voice trigger carries the record disc inline */
.aux-btn.aux-record { flex-direction: row; gap: var(--sp-sm); }
.aux-record .aux-text { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }


/* ============================================================
   Cockpit — execution stage + steppers
   ============================================================ */
.exec-stage {
  /* top-aligned and tight — centring pushed big empty gaps around the stepper */
  flex: none; display: flex; flex-direction: column; gap: 5px;
}
/* which caption the number belongs to, sat directly on top of the control */
.exec-caption {
  margin: 2px 0 0; text-align: center;
  font-size: 11px; font-weight: var(--w-bold);
  text-transform: uppercase; letter-spacing: 1.2px; color: var(--purple);
}
.exec-hint { margin: 0; text-align: center; font-size: 11.5px; color: var(--text-2); line-height: 1.3; }

.stepper { display: flex; align-items: stretch; gap: 10px; }
.step-btn {
  flex: none; border-radius: var(--r-lg); cursor: pointer;
  border: 1px solid var(--hairline); background: var(--surface);
  color: var(--purple); font-weight: var(--w-medium); line-height: 1;
  display: grid; place-items: center; box-shadow: var(--e1);
}
.step-btn:disabled { opacity: 0.35; box-shadow: none; }
.step-value {
  flex: 1 1 auto; display: grid; place-items: center;
  border-radius: var(--r-lg); background: var(--surface);
  border: 1px solid var(--hairline);
  font-variant-numeric: tabular-nums; cursor: pointer;
  min-width: 0; padding: 0 4px;
}
.step-value:disabled { cursor: default; }
.stepper-lg .step-btn { width: 62px; height: 62px; font-size: 30px; }
.stepper-lg .step-value { min-height: 62px; font-size: 34px; font-weight: var(--w-bold); letter-spacing: -0.8px; font-feature-settings: "tnum" 1; }
.stepper-sm .step-btn { width: var(--tap); height: var(--tap); font-size: 26px; }
.stepper-sm .step-value { min-height: var(--tap); width: 74px; flex: none; font-size: var(--fs-xxl); font-feature-settings: "tnum" 1; }
.diff-value.state-suggested  { font-weight: var(--w-medium); color: var(--text-3); }
.diff-value.state-confirmed,
.diff-value.state-overridden { font-weight: var(--w-bold); color: var(--text); }


/* ============================================================
   Cockpit — deduction official's card
   ============================================================ */
.ded-cockpit { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.panel-score { justify-content: flex-start; }
.ded-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; }
.ded-key {
  min-height: var(--tap); border-radius: var(--r-lg); cursor: pointer;
  border: 1px solid var(--hairline); background: var(--surface); color: var(--danger);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  padding: 6px; box-shadow: var(--e1);
}
.ded-key:disabled { opacity: 0.4; box-shadow: none; }
.ded-key-label { font-size: 13.5px; font-weight: var(--w-semibold); }
.ded-key-val { font-size: var(--fs-sm); font-weight: var(--w-bold); font-variant-numeric: tabular-nums; }

.taken-list {
  /* about five rows, then it scrolls on its own so the apply buttons and
     the header above never move */
  max-height: 288px; overflow-y: auto; -webkit-overflow-scrolling: touch;
  display: flex; flex-direction: column; gap: 6px;
}
.taken-list .taken-row { flex: none; }

.ded-taken { margin-top: 10px; flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; }
.taken-row {
  display: flex; align-items: center; gap: 9px;
  background: var(--surface-2); border: 1px solid var(--hairline);
  border-radius: var(--r-md); padding: 8px 10px;
}
.taken-main { flex: 1 1 auto; min-width: 0; }
.taken-label { display: block; font-size: var(--fs-md); font-weight: var(--w-semibold); }
.taken-label .via {
  font-style: normal; font-size: var(--fs-xs); font-weight: var(--w-bold);
  color: var(--purple-ink); background: var(--purple-soft);
  border-radius: var(--r-sm); padding: 1px 5px; margin-left: 5px;
}
.taken-note { display: block; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.35; margin-top: 2px; }
.taken-time { display: block; font-size: 11px; color: var(--text-2); margin-top: 1px; }
.taken-amt { flex: none; font-size: var(--fs-lg); font-weight: var(--w-bold); color: var(--danger); font-variant-numeric: tabular-nums; }
.taken-x {
  flex: none; width: 40px; height: 40px; border-radius: var(--r-md);
  border: 1px solid var(--hairline); background: var(--surface);
  color: var(--text-2); font-size: var(--fs-xl); cursor: pointer;
}


/* ============================================================
   Cockpit — aux row + submit dock
   ============================================================ */
.aux-row { flex: none; display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.aux-row.is-single { grid-template-columns: 1fr; }
.aux-btn {
  min-height: 52px; border-radius: var(--r-lg); cursor: pointer;
  border: 1px solid var(--hairline); background: var(--surface); box-shadow: var(--e1);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  padding: 6px 8px;
}
.aux-label { font-size: var(--fs-md); font-weight: var(--w-semibold); }
.aux-sub { font-size: 11.5px; color: var(--text-2); font-weight: var(--w-medium); }

.submit-dock {
  display: flex; flex-direction: column; gap: 8px; flex: none;
  background: var(--surface); border-top: 1px solid var(--hairline);
  padding: 9px var(--pad) calc(9px + var(--sab));
  box-shadow: 0 -3px 14px rgba(16, 18, 24, 0.08);
}
.submit-btn {
  width: 100%; min-height: 58px; border-radius: var(--r-lg); cursor: pointer;
  border: none; background: var(--purple); color: var(--white);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  box-shadow: var(--e2); padding: 6px 12px;
}
.submit-main { font-size: var(--fs-lg); font-weight: var(--w-semibold); }
.submit-done { font-size: 11.5px; font-weight: var(--w-medium); opacity: 0.92; }
.submit-btn.is-blocked { background: var(--bg-sunk); color: var(--text-2); box-shadow: none; }
.submit-btn.is-next { background: var(--good); }


/* ============================================================
   SCORING DRILL-IN — performance-detail chrome around the cockpit.
   One viewport, no scroll: strip + one white card + dock, and no
   bottom nav underneath.
   ============================================================ */
.detail-top {
  flex: none; z-index: 20; position: relative;
  display: flex; align-items: center; gap: var(--sp-sm);
  background: var(--surface); border-bottom: 1px solid var(--hairline);
  padding: calc(8px + var(--sat)) var(--sp-md) 8px;
}
/* Left-aligned, not centred: the role pill and share icon take enough of
   the right side that a centred title would run under them at 402px. */
.detail-top-title {
  flex: 1 1 auto; min-width: 0; margin: 0;
  font-size: var(--fs-lg); font-weight: var(--w-bold); color: var(--text);
  letter-spacing: -0.2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.detail-top-right { margin-left: auto; display: flex; align-items: center; gap: 6px; z-index: 1; }
/* the back control and the event title share one centred line */
.detail-top .icon-btn { width: 30px; height: 34px; }
.detail-top .detail-top-title { align-self: center; }

.score-wrap { flex: 1 1 auto; min-height: 0; padding: 10px 12px; display: flex; align-items: flex-start; }
/* The white card that holds every scoring control. It shrink-wraps its
   content — growing it to fill left a dead band between the score control
   and the aux row. It can still shrink (and the deduction list scroll)
   when a role's cockpit is taller than the viewport. */
.score-card {
  flex: 0 1 auto; width: 100%; max-height: 100%;
  display: flex; flex-direction: column; gap: 6px;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-xl); box-shadow: var(--e2); padding: 10px;
  overflow: hidden;
}
.perf-head {
  flex: none; display: grid; grid-template-columns: 1fr auto; align-items: center;
  gap: 2px 8px; padding-bottom: 7px;
  /* a rule element would need extra markup; a shadow keeps it hairline */
  box-shadow: inset 0 -1px 0 var(--hairline);
}
.perf-head-team {
  font-size: var(--fs-xl); font-weight: var(--w-bold); color: var(--text); letter-spacing: -0.2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.perf-head-meta {
  grid-column: 1 / 2; font-size: 11.5px; color: var(--text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.perf-head .status-chip { grid-column: 2 / 3; grid-row: 1 / 3; }

/* the cockpit sits inside the card, so its own cards drop a level */
.score-card .card { box-shadow: none; background: var(--surface-2); }
.score-card .card.is-focus { box-shadow: var(--e1); background: var(--surface); }
.score-card .total-card { box-shadow: none; background: var(--surface-2); }
/* The execution card shrink-wraps its content: centring the stage inside a
   grown card opened big empty gaps directly above and below the stepper.
   Leftover height goes to the gap before the aux row instead. */
.score-card .exec-card { flex: none; }
.score-card .ded-cockpit {
  flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
}
.score-card .ded-taken { flex: 0 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; }


/* ============================================================
   Bottom tab bar
   ============================================================ */
.tab-bar {
  flex: none; display: flex;
  background: var(--white); border-top: 1px solid var(--hairline);
  padding-bottom: max(var(--sab), 6px);
}
.tab-btn {
  position: relative; flex: 1 1 0; min-height: 56px;
  border: none; background: none; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  color: var(--medium-gray); padding: 6px 2px;
}
.tab-btn.is-active { color: var(--purple); }
.tab-indicator {
  position: absolute; top: 0; left: 50%; transform: translateX(-50%);
  width: 30px; height: 3px; border-radius: 0 0 3px 3px; background: transparent;
}
.tab-btn.is-active .tab-indicator { background: var(--purple); }
/* ICON SLOT — swap the files in ./icons/ (or repoint TAB_ICONS in app.js) */
.tab-icon {
  width: 22px; height: 22px; display: block;
  background-color: currentColor;
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
}
.tab-label { font-size: 9px; font-weight: var(--w-semibold); letter-spacing: 0; line-height: 1.1; text-align: center; }
.tab-btn.is-active .tab-label { font-weight: var(--w-bold); }


/* ============================================================
   TAB: sessions — level 1, session cards
   ============================================================ */
.sessions-intro { flex: none; }
.sessions-event { margin: 2px 0 0; font-size: var(--fs-xxl); font-weight: var(--w-bold); color: var(--text); letter-spacing: -0.2px; }
.sessions-venue { margin: 2px 0 0; font-size: var(--fs-sm); color: var(--text-2); }

.session-cards { gap: 10px; }
.session-card {
  display: flex; flex-direction: column; gap: 7px; width: 100%; flex: none;
  padding: 12px; text-align: left; cursor: pointer;
  border: 1px solid var(--hairline); border-radius: var(--r-lg);
  background: var(--surface); box-shadow: var(--e1);
}
/* Active state = the same hairline, in purple. The card stays white like
   every other one; a filled card read as a different kind of row. */
.session-card.is-current {
  border-color: var(--purple);
  box-shadow: var(--e2);
}
.session-card-head { display: flex; align-items: center; gap: 8px; }
.session-card-title { flex: 1 1 auto; min-width: 0; font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text); }
.session-card-meta { font-size: var(--fs-sm); color: var(--text-2); }
.session-card-foot {
  display: flex; align-items: center; justify-content: space-between;
  font-size: var(--fs-sm); color: var(--text-2);
}
.session-card-go {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: var(--fs-sm); font-weight: var(--w-bold); color: var(--purple);
}
.session-card-go .row-chev { width: 15px; height: 15px; }

.meter-track { display: block; height: 9px; border-radius: var(--r-full); background: var(--bg-sunk); overflow: hidden; border: 1px solid var(--hairline); }
.meter-fill { display: block; height: 100%; background: var(--purple); transition: width 0.35s ease; }
.meter-fill.is-done { background: var(--good); }


/* ============================================================
   PERFORMANCE LIST — the attendee list, one level down
   ============================================================ */
.plist-head {
  display: none; flex: none; z-index: 20;
  background: var(--surface); border-bottom: 1px solid var(--hairline);
  padding: calc(8px + var(--sat)) var(--pad) 8px;
}
/* One level down inside Sessions, this chrome replaces the strip */
body[data-tab="sessions"][data-view="perf"] .plist-head { display: block; }
/* Scoped to the judge screen: the producer console reuses .judge-top for
   the same chrome, and a stale data-view="perf" left over from a judge
   session would otherwise hide the console's strip outright. */
body[data-screen="judge"][data-tab="sessions"][data-view="perf"] .judge-top { display: none; }

.plist-bar { display: flex; align-items: center; gap: var(--sp-sm); }
.plist-bar-spacer { flex: 1 1 auto; }
/* The same day + room controls above the session list. */
.scope-bar {
  display: none; flex: none;
  align-items: center; justify-content: space-between; gap: var(--sp-sm);
  background: var(--surface); border-bottom: 1px solid var(--hairline);
  padding: 0 var(--pad) 4px;
}
body[data-screen="judge"][data-tab="sessions"][data-view="sessions"] .scope-bar { display: flex; }

/* Date popover — a small anchored menu, like the main app's date dropdown */
.pop-scrim { position: fixed; inset: 0; z-index: 60; background: transparent; }
.popover {
  position: fixed; z-index: 61; min-width: 200px; max-width: 260px;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: 0 6px 20px rgba(16, 18, 24, 0.18);
  padding: 5px; overflow: hidden;
}
.pop-row {
  display: block; width: 100%; text-align: left; cursor: pointer;
  border: none; background: none; border-radius: var(--r-md);
  padding: 10px 12px; min-height: 44px;
}
.pop-label { display: block; font-size: var(--fs-md); font-weight: var(--w-medium); color: var(--text); }
.pop-meta { display: block; font-size: 11.5px; color: var(--text-2); margin-top: 1px; }
/* selected day reads bold purple, matching the main app */
.pop-row.is-selected .pop-label { color: var(--purple); font-weight: var(--w-bold); }

/* Date and room sit on one row with equal air above and below, so both are
   a comfortable tap target and their labels + chevrons line up. */
.plist-pills {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-sm); margin-top: 4px;
}
/* plain text labels with a chevron, no pill */
.meta-pill {
  display: inline-flex; align-items: center; gap: 4px; cursor: pointer;
  border: none; background: none; min-width: 0;
  padding: 9px 0; min-height: 40px;
  font-size: var(--fs-md); font-weight: var(--w-regular); color: var(--text-2);
  line-height: 1.2;
}
.meta-pill span:first-child { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
#plRoom, #sxRoom { font-weight: var(--w-medium); color: var(--text); }

.plist-search { display: flex; align-items: center; gap: var(--sp-sm); margin-top: 8px; }
.search-input {
  flex: 1 1 auto; min-width: 0; -webkit-appearance: none; appearance: none;
  border: 1px solid var(--hairline); border-radius: var(--r-md);
  background: var(--light-gray); padding: 9px var(--sp-md);
  font-family: inherit; font-size: var(--fs-md); color: var(--text);
}
.search-input:focus { outline: none; box-shadow: 0 0 0 3px rgba(107, 78, 158, 0.16); }
.compact-toggle {
  flex: none; width: 40px; height: 38px; border-radius: var(--r-md); cursor: pointer;
  border: 1px solid var(--hairline); background: var(--light-gray);
  display: grid; place-items: center;
}
.compact-toggle[aria-pressed="true"] { background: var(--purple-soft); }
/* a list glyph, not a second hamburger — the back arrow is right above it */
.rows-glyph { display: flex; flex-direction: column; gap: 3px; align-items: flex-end; }
.rows-glyph i {
  display: block; width: 12px; height: 2px; border-radius: 1px; background: var(--text-2);
  position: relative;
}
.rows-glyph i::before {
  content: ''; position: absolute; left: -6px; top: 0;
  width: 2px; height: 2px; border-radius: 1px; background: inherit;
}
.compact-toggle[aria-pressed="true"] .rows-glyph i { background: var(--purple); }

/* Each performance is its own separated rounded card, matching the main
   app's schedule list — not a flat hairline-divided row. */
.perf-list {
  list-style: none; margin: 0;
  padding: 10px 12px 96px;
  display: flex; flex-direction: column; gap: 10px;
}
.perf-session-head {
  margin: 2px 2px 0;
  font-size: var(--fs-xs); font-weight: var(--w-semibold); letter-spacing: 1px;
  text-transform: uppercase; color: var(--text-2);
}
.perf-row {
  display: flex; align-items: stretch; width: 100%;
  padding: 0; cursor: pointer; text-align: left;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--e1); overflow: hidden;
}
/* same treatment for the routine that is up now — purple hairline, white
   card, no fill */
.perf-row.is-current { border-color: var(--purple); box-shadow: var(--e2); }
.perf-row.is-submitted { background: var(--surface-2); }
/* gray block on the left, flush to the card edge and full card height */
.perf-time {
  flex: none; width: 68px; align-self: stretch;
  background: var(--light-gray);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
/* the time block keeps the standard gray, like every other row */
.perf-time-num { font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--text); font-variant-numeric: tabular-nums; }
.perf-time-period { font-size: var(--fs-xs); color: var(--text-2); text-transform: uppercase; }
.perf-info { flex: 1 1 auto; min-width: 0; padding: 12px 8px 12px var(--sp-md); }
.perf-team { display: block; font-size: var(--fs-lg); font-weight: var(--w-bold); color: var(--text); }
.perf-row.is-current .perf-team { color: var(--purple); }
.perf-division { display: block; font-size: var(--fs-sm); color: var(--text-2); }
.perf-org { display: block; font-size: var(--fs-xs); font-weight: var(--w-semibold); color: var(--text-2); letter-spacing: 0.5px; }
.perf-actions { flex: none; display: flex; align-items: center; }
.perf-chev { flex: none; display: grid; place-items: center; width: 30px; color: var(--medium-gray); }
.row-chev { width: 18px; height: 18px; display: block; }

/* density toggle: same cards, less air */
.perf-list.is-compact { gap: 7px; }
.perf-list.is-compact .perf-info { padding-top: 7px; padding-bottom: 7px; }
.perf-list.is-compact .perf-org { display: none; }

.perf-empty { padding: var(--sp-xl) var(--pad); }

/* floating FILTERS pill */
.filters-pill {
  display: none; position: absolute; left: 50%; transform: translateX(-50%);
  bottom: calc(62px + max(var(--sab), 6px) + 22px);
  z-index: 30; align-items: center; gap: var(--sp-sm); cursor: pointer;
  padding: 11px var(--sp-xl); border-radius: 24px;
  border: 1px solid var(--hairline); background: var(--surface);
  box-shadow: 0 2px 15px rgba(0, 0, 0, 0.2);
}
body[data-screen="judge"][data-tab="sessions"][data-view="perf"] .filters-pill { display: flex; }
.filters-text { font-size: var(--fs-sm); font-weight: var(--w-semibold); color: var(--text); letter-spacing: 0.5px; }
.filters-glyph { display: flex; flex-direction: column; gap: 3px; width: 16px; }
.filters-glyph i { display: block; height: 2px; border-radius: 1px; background: var(--text); }
.filters-glyph i:first-child { width: 16px; }
.filters-glyph i:last-child { width: 10px; }


/* ============================================================
   TAB: status
   ============================================================ */
.status-list { display: flex; flex-direction: column; gap: 10px; }
.status-row {
  display: flex; flex-direction: column; gap: 5px;
  border: 1px solid var(--hairline); border-radius: var(--r-md);
  background: var(--surface-2); padding: 10px;
}
.status-row.is-current { background: var(--purple-soft); }
.status-row-top { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.status-row-title { font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--text); }
.status-row-count { flex: none; font-size: 13.5px; font-weight: var(--w-bold); color: var(--text-2); font-variant-numeric: tabular-nums; }
.status-row-meta { font-size: 11.5px; color: var(--text-2); }

.kv-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin-top: 12px; }
.kv { background: var(--surface-2); border: 1px solid var(--hairline); border-radius: var(--r-md); padding: 7px 9px; min-width: 0; }
.kv em { display: block; font-style: normal; font-size: var(--fs-xs); font-weight: var(--w-semibold); text-transform: uppercase; letter-spacing: 0.5px; color: var(--text-2); }
.kv b { display: block; font-size: 13.5px; font-weight: var(--w-semibold); overflow-wrap: anywhere; }

.ref-list { display: flex; flex-direction: column; gap: 7px; }
.ref-row {
  display: flex; align-items: center; gap: 10px;
  background: var(--surface-2); border: 1px solid var(--hairline);
  border-radius: var(--r-md); padding: 9px 10px;
}
.ref-row.is-mine { background: var(--purple-soft); }
.ref-main { flex: 1 1 auto; min-width: 0; }
.ref-main b { display: block; font-size: var(--fs-md); font-weight: var(--w-semibold); }
.ref-main em { display: block; font-style: normal; font-size: 11.5px; color: var(--text-2); }
.ref-val { flex: none; font-size: 13.5px; font-weight: var(--w-bold); font-variant-numeric: tabular-nums; }
.ref-val.ref-neg { color: var(--danger); }


/* ============================================================
   TAB: me
   ============================================================ */
.identity { display: flex; align-items: center; gap: 12px; }
.id-initials {
  flex: none; width: 52px; height: 52px; border-radius: var(--r-lg);
  background: var(--purple); color: var(--white);
  display: grid; place-items: center; font-size: var(--fs-xl); font-weight: var(--w-bold); letter-spacing: 0.4px;
}
.id-main { display: flex; flex-direction: column; min-width: 0; }
.id-main b { font-size: var(--fs-xl); font-weight: var(--w-bold); }
.id-main em { font-style: normal; font-size: 12.5px; color: var(--text-2); }

.queue-list { list-style: none; margin: 12px 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.queue-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  background: var(--surface-2); border: 1px solid var(--hairline);
  border-radius: var(--r-md); padding: 8px 10px;
}
.queue-main b { display: block; font-size: var(--fs-md); font-weight: var(--w-semibold); }
.queue-main em { display: block; font-style: normal; font-size: 11.5px; color: var(--text-2); font-variant-numeric: tabular-nums; }
.queue-state { flex: none; font-size: 11.5px; font-weight: var(--w-bold); }
.queue-row.is-synced .queue-state { color: var(--good); }
.queue-row.is-queued { background: var(--warn-bg); }
.queue-row.is-queued .queue-state { color: var(--warn); }

.pref-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; min-height: var(--tap); padding: 10px 12px;
  border: 1px solid var(--hairline); background: var(--surface-2);
  border-radius: var(--r-lg); cursor: pointer; text-align: left;
}
.pref-main { min-width: 0; }
.pref-label { display: block; font-size: var(--fs-lg); font-weight: var(--w-semibold); }
.pref-sub { display: block; font-size: var(--fs-sm); color: var(--text-2); }
.pref-state {
  flex: none; font-size: 12.5px; font-weight: var(--w-bold);
  padding: 5px 12px; border-radius: var(--r-full);
  background: var(--purple-soft); border: 1px solid var(--hairline); color: var(--purple-ink);
}

.ghost-btn {
  flex: 1 1 auto; min-height: 50px; border-radius: var(--r-lg); cursor: pointer;
  border: 1px solid var(--hairline); background: var(--surface);
  font-size: var(--fs-md); font-weight: var(--w-semibold); padding: 8px 10px;
}
.ghost-btn.wide { width: 100%; flex: none; margin-top: 10px; }
.accent-btn {
  flex: 1 1 auto; min-height: 50px; border-radius: var(--r-lg); cursor: pointer;
  border: 1px solid var(--purple); background: var(--purple); color: var(--white);
  font-size: var(--fs-md); font-weight: var(--w-bold); padding: 8px 10px;
}
.accent-btn:disabled { background: var(--bg-sunk); border-color: var(--hairline); color: var(--text-3); }
.danger-btn {
  width: 100%; min-height: 50px; border-radius: var(--r-lg); cursor: pointer; margin-top: 10px;
  border: 1px solid var(--hairline); background: var(--danger-bg); color: var(--danger);
  font-size: var(--fs-lg); font-weight: var(--w-bold);
}


/* ============================================================
   Bottom sheets
   ============================================================ */
.sheet-scrim {
  position: fixed; inset: 0; z-index: 40;
  background: rgba(16, 18, 24, 0.44);
  opacity: 0; transition: opacity 0.22s ease;
}
.sheet-scrim.is-open { opacity: 1; }
.sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  background: var(--surface);
  border-radius: 22px 22px 0 0;
  /* roomier than the old 10/16 — content was sitting tight against the
     sheet edges; the X hangs at this same inset, like the Filters sheet */
  /* the bottom keeps a floor of its own so a short sheet still opens
     comfortably up from the edge instead of hugging it */
  padding: var(--sp-xl) var(--sp-xl) calc(var(--sp-xl) + max(var(--sab), 14px));
  box-shadow: 0 -12px 34px rgba(16, 18, 24, 0.22);
  transform: translateY(100%);
  transition: transform 0.24s cubic-bezier(0.32, 0.72, 0, 1);
  max-height: 90dvh; overflow-y: auto;
}
.sheet.is-open { transform: translateY(0); }

/* CENTRED DIALOG — the same sheet, re-anchored. A bottom sheet spanning a
   1440px console reads as a drawer, not as "are you sure?", so a confirm
   that has to carry weight sits in the middle instead. Scrim, Escape,
   tap-outside and the open/close easing all still come from .sheet above. */
.sheet.is-dialog {
  top: 50%; bottom: auto; left: 50%; right: auto;
  width: min(460px, calc(100vw - 2 * var(--sp-xl)));
  max-height: min(84dvh, 620px);
  border-radius: var(--r-xl);
  padding: var(--sp-xl);
  box-shadow: 0 18px 48px rgba(16, 18, 24, 0.24);
  /* settles the last few px upward, mirroring the sheet's own entrance */
  transform: translate(-50%, calc(-50% + 10px));
}
.sheet.is-dialog.is-open { transform: translate(-50%, -50%); }
/* pulled back up now that the sheet carries a full padding inset */
.sheet-grab { width: 40px; height: 4px; border-radius: 2px; background: var(--hairline); margin: -14px auto 14px; }

/* Shared modal header: optional back chevron, title block, X top-right.
   The X matches the main app's Filters sheet — a bare 24px glyph in
   darkGray at the sheet's own padding inset, no box. */
.sheet-head { display: flex; align-items: flex-start; gap: var(--sp-sm); margin-bottom: var(--sp-md); }
.sheet-head-text { flex: 1 1 auto; min-width: 0; }
.sheet-head .sheet-sub { margin-bottom: 0; }
.sheet-back, .sheet-x {
  /* 44px target with the glyph optically at the sheet's padding inset —
     the main app gets the same reach from a 24px icon plus hitSlop 10 */
  flex: none; width: 44px; height: 44px; cursor: pointer;
  border: none; background: none; padding: 0;
  display: grid; place-items: center; line-height: 1;
  margin: -10px -10px -10px 0;
}
.sheet-back { color: var(--purple); font-size: 32px; font-weight: var(--w-light); margin: -10px 0 -10px -10px; }
.sheet-x { color: var(--text); font-size: 30px; font-weight: var(--w-light); }

/* Room / location picker rows — a check on the active one */
.pick-list { display: flex; flex-direction: column; gap: var(--sp-sm); }
.pick-row {
  display: flex; align-items: center; gap: var(--sp-md); width: 100%;
  min-height: var(--tap); padding: var(--sp-md); cursor: pointer; text-align: left;
  border: 1px solid var(--hairline); border-radius: var(--r-lg);
  background: var(--surface);
}
.pick-row.is-selected { background: var(--purple-soft); box-shadow: var(--e2); }
.pick-main { flex: 1 1 auto; min-width: 0; }
.pick-title { display: block; font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text); }
.pick-row.is-selected .pick-title { color: var(--purple-ink); }
.pick-meta { display: block; font-size: var(--fs-sm); color: var(--text-2); }
.pick-check {
  flex: none; width: 24px; height: 24px; border-radius: var(--r-full);
  display: grid; place-items: center; border: 1px solid var(--hairline);
  background: var(--surface); color: transparent; font-size: var(--fs-sm); font-weight: var(--w-bold);
}
.pick-row.is-selected .pick-check { background: var(--purple); border-color: var(--purple); color: var(--white); }

/* Change-role modal — one modal, three entry points */
.role-list { display: flex; flex-direction: column; gap: var(--sp-sm); }
.role-row {
  display: flex; align-items: center; gap: var(--sp-md); width: 100%;
  min-height: var(--tap); padding: var(--sp-md); cursor: pointer; text-align: left;
  border: 1px solid var(--hairline); border-radius: var(--r-lg);
  background: var(--surface);
}
.role-row.is-selected { background: var(--purple-soft); box-shadow: var(--e2); }
.role-row-main { flex: 1 1 auto; min-width: 0; }
.role-row-title { display: block; font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text); }
.role-row-meta { display: block; font-size: var(--fs-sm); color: var(--text-2); }
.role-row-check {
  flex: none; width: 24px; height: 24px; border-radius: var(--r-full);
  display: grid; place-items: center; border: 1px solid var(--hairline);
  background: var(--surface); color: transparent; font-size: var(--fs-sm); font-weight: var(--w-bold);
}
.role-row.is-selected .role-row-check { background: var(--purple); border-color: var(--purple); color: var(--white); }

/* Settings sheet rows */
.pref-stack { display: flex; flex-direction: column; gap: var(--sp-sm); }
.pref-go { flex: none; font-size: var(--fs-xxl); color: var(--purple); line-height: 1; }
.sheet-title { margin: 0 0 3px; font-size: var(--fs-xxl); font-weight: var(--w-bold); color: var(--text); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.sheet-sub { margin: 0 0 14px; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.45; }
.sheet-label { margin: 16px 0 8px; font-size: var(--fs-xs); font-weight: var(--w-semibold); text-transform: uppercase; letter-spacing: 1px; color: var(--text-2); }
.sim-tag {
  font-size: var(--fs-xs); font-weight: var(--w-bold); text-transform: uppercase; letter-spacing: 0.5px;
  background: var(--purple-soft); border: 1px solid var(--hairline);
  color: var(--purple-ink); padding: 2px 7px; border-radius: var(--r-sm);
}
.sheet-rows { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.sheet-rows li {
  display: grid; grid-template-columns: 1fr auto; align-items: baseline; gap: 4px 10px;
  background: var(--surface-2); border: 1px solid var(--hairline);
  border-radius: var(--r-md); padding: 9px 11px;
}
.sheet-rows li span { font-size: var(--fs-lg); font-weight: var(--w-semibold); }
.sheet-rows li b { font-size: var(--fs-xl); font-variant-numeric: tabular-nums; }
.sheet-rows li em { grid-column: 1 / -1; font-style: normal; font-size: 11.5px; color: var(--text-2); }
.sheet-rows li.empty span { color: var(--text-2); font-weight: var(--w-regular); }
.sheet-total {
  display: flex; justify-content: space-between; align-items: baseline;
  border-top: 1px solid var(--hairline); padding-top: 10px; margin-bottom: 12px;
}
.sheet-total span { font-size: var(--fs-md); color: var(--text-2); }
.sheet-total strong { font-size: 30px; font-weight: var(--w-bold); font-variant-numeric: tabular-nums; }
.sheet-warn {
  margin: 0 0 14px; font-size: 12.5px; line-height: 1.5;
  color: var(--warn); background: var(--warn-bg); border: 1px solid var(--hairline);
  border-radius: var(--r-md); padding: 10px 11px;
}
.sheet-actions { display: flex; gap: 10px; margin-top: 6px; align-items: stretch; }
/* secondary keeps its label on one line; primary takes the rest and reads
   at the same size as the main Submit button */
.sheet-actions .ghost-btn.sheet-cancel { flex: 0 0 auto; white-space: nowrap; padding: 8px 16px; }
.sheet-submit { flex: 1 1 auto; min-height: 56px; }
.sheet-submit .submit-main { font-size: var(--fs-lg); font-weight: var(--w-semibold); }

.kp-display {
  background: var(--surface-2); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); padding: 12px; text-align: center; margin-bottom: 6px;
}
.kp-display span { font-size: 36px; font-weight: var(--w-bold); font-variant-numeric: tabular-nums; letter-spacing: -1px; }
.kp-display span.is-ghost { color: var(--text-3); font-weight: var(--w-medium); }
.kp-display span.is-bad { color: var(--danger); }
.kp-msg { margin: 0 0 12px; font-size: var(--fs-sm); color: var(--text-2); text-align: center; }
.kp-keys { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 14px; }
.kp-key {
  min-height: 56px; border-radius: var(--r-lg); cursor: pointer;
  border: 1px solid var(--hairline); background: var(--surface);
  font-size: var(--fs-xxxl); font-weight: var(--w-medium); box-shadow: var(--e1);
}

.corr-pick { display: flex; flex-direction: column; gap: 7px; margin-bottom: 8px; }
.corr-option {
  display: flex; justify-content: space-between; align-items: center; gap: 10px;
  min-height: 50px; padding: 10px 12px;
  border: 1px solid var(--hairline); background: var(--surface-2);
  border-radius: var(--r-lg); font-size: var(--fs-lg); font-weight: var(--w-semibold); cursor: pointer; text-align: left;
}
.corr-option b { font-variant-numeric: tabular-nums; font-size: var(--fs-xl); }
.corr-stepper { margin-bottom: 10px; }
.corr-stepper .step-value { cursor: default; }
.corr-delta-line { margin: 0 0 6px; text-align: center; font-size: var(--fs-xl); color: var(--text-2); font-variant-numeric: tabular-nums; }
.corr-delta-line b { color: var(--purple); font-size: var(--fs-xxl); }
.corr-delta-line .arrow { color: var(--warn); margin: 0 6px; }
.corr-remove-note {
  margin: 0 0 10px; font-size: var(--fs-md); color: var(--danger);
  background: var(--danger-bg); border: 1px solid var(--hairline);
  border-radius: var(--r-md); padding: 10px 11px;
}
.corr-log { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.corr-row {
  display: flex; flex-direction: column; gap: 3px;
  background: var(--warn-bg); border: 1px solid var(--hairline);
  border-radius: var(--r-md); padding: 10px;
}
.corr-target { font-size: var(--fs-md); font-weight: var(--w-semibold); }
.corr-delta { display: flex; align-items: center; gap: 8px; font-variant-numeric: tabular-nums; }
.corr-delta .from { text-decoration: line-through; color: var(--text-2); font-size: var(--fs-xl); }
.corr-delta .arrow { color: var(--warn); font-weight: var(--w-bold); }
.corr-delta .to { color: var(--purple); font-size: var(--fs-xl); font-weight: var(--w-bold); }
.corr-reason { font-size: var(--fs-sm); font-style: italic; }
.corr-status { font-size: 11px; color: var(--warn); font-weight: var(--w-bold); }


/* ============================================================
   Voice note — three stages, Voice Memos style
   ============================================================ */

/* -- stage 1: ready -- */
.rec-ready { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: var(--sp-sm) 0 var(--sp-md); }
.record-btn.record-xl { width: 76px; height: 76px; }
.record-xl .record-mic { width: 32px; height: 32px; }
.rec-ready-label {
  margin: 0; font-size: var(--fs-xs); font-weight: var(--w-bold);
  text-transform: uppercase; letter-spacing: 1.2px; color: var(--text-2);
}
/* Caps at roughly five rows and scrolls inside itself, so the Ready
   button, the header and Done never move as recordings pile up. */
.rec-list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 7px;
  max-height: 350px; overflow-y: auto; -webkit-overflow-scrolling: touch;
}
.rec-row { flex: none; }
.rec-row {
  display: flex; align-items: center; gap: 10px;
  background: var(--surface-2); border: 1px solid var(--hairline);
  border-radius: var(--r-md); padding: 9px 10px;
}
.rec-main { flex: 1 1 auto; min-width: 0; }
.rec-title { display: block; font-size: var(--fs-md); font-weight: var(--w-medium); line-height: 1.3; }
.rec-meta { display: block; font-size: 11px; color: var(--text-2); margin-top: 2px; }
.rec-dur { flex: none; font-size: var(--fs-sm); color: var(--text-2); font-variant-numeric: tabular-nums; }
.rec-x {
  flex: none; width: 30px; height: 30px; border-radius: var(--r-md);
  border: 1px solid var(--hairline); background: var(--surface);
  color: var(--text-2); font-size: var(--fs-lg); cursor: pointer;
}
.rec-empty { margin: 0; }

/* -- stage 2: recording. Timer, waveform, Stop. Nothing else. -- */
.rec-live { display: flex; flex-direction: column; align-items: center; gap: var(--sp-md); padding: var(--sp-sm) 0 var(--sp-xs); }
.rec-live-title {
  margin: 0; font-size: var(--fs-xs); font-weight: var(--w-bold);
  text-transform: uppercase; letter-spacing: 1.2px; color: var(--record-red);
}
.rec-timer {
  margin: 0; font-size: 40px; font-weight: var(--w-light); color: var(--text);
  font-variant-numeric: tabular-nums; letter-spacing: -1px; line-height: 1;
}
.rec-wave {
  width: 100%; height: 74px; display: flex; align-items: center; justify-content: center;
  gap: 2px; overflow: hidden;
}
.rec-wave i { flex: none; width: 3px; border-radius: 2px; background: var(--record-red); }
.stop-btn {
  width: 68px; height: 68px; border-radius: var(--r-full); cursor: pointer;
  border: 1px solid var(--hairline); background: var(--surface);
  display: grid; place-items: center; box-shadow: var(--e2);
}
.stop-square { width: 26px; height: 26px; border-radius: 5px; background: var(--record-red); }
.rec-live-hint {
  margin: 0; min-height: 34px; text-align: center;
  font-size: 12.5px; color: var(--text-2); line-height: 1.35;
}

/* -- stage 3: detail -- */
.audio-note {
  display: flex; align-items: center; gap: 10px;
  background: var(--surface-2); border: 1px solid var(--hairline);
  border-radius: var(--r-md); padding: 8px 10px;
}
.audio-play {
  flex: none; width: 36px; height: 36px; border-radius: var(--r-md);
  border: 1px solid var(--hairline); background: var(--surface);
  color: var(--purple); font-size: var(--fs-md); cursor: pointer;
}
.wave { flex: 1 1 auto; display: flex; align-items: center; gap: 2px; height: 28px; }
.wave i { flex: 1 1 auto; background: var(--purple-line); border-radius: 2px; min-width: 2px; }
.audio-dur { flex: none; font-size: var(--fs-sm); color: var(--text-2); font-variant-numeric: tabular-nums; }

.transcript-label { display: block; margin: 12px 0 5px; font-size: var(--fs-xs); font-weight: var(--w-semibold); text-transform: uppercase; letter-spacing: 1px; color: var(--text-2); }
.transcript {
  width: 100%; border: 1px solid var(--hairline); border-radius: var(--r-lg);
  background: var(--surface); padding: 10px 12px;
  font-family: inherit; font-size: var(--fs-lg); line-height: 1.4; color: var(--text); resize: vertical;
}
.transcript:focus { outline: none; box-shadow: 0 0 0 3px rgba(107, 78, 158, 0.16); }

.parse-out {
  margin-top: 10px; padding: 10px 12px; border-radius: var(--r-lg);
  background: var(--surface-2); border: 1px solid var(--hairline);
  display: flex; flex-direction: column; gap: 4px;
}
.parse-hit { font-size: var(--fs-sm); color: var(--text-2); }
.parse-def { font-size: var(--fs-lg); font-weight: var(--w-bold); }
.parse-def b { color: var(--danger); font-variant-numeric: tabular-nums; }
.parse-warn { font-size: var(--fs-sm); color: var(--warn); }
.parse-none { font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text-2); }
.parse-sub { font-size: var(--fs-sm); color: var(--text-2); }
.parse-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.parse-chip {
  border: 1px solid var(--hairline); background: var(--danger-bg); color: var(--danger);
  border-radius: var(--r-md); padding: 8px 10px; font-size: var(--fs-sm); font-weight: var(--w-semibold); cursor: pointer;
}
/* three equal actions — capturing the note is the point, applying a
   deduction is one option, not a hero button */
.capture-actions { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-top: 12px; }
.capture-actions .ghost-btn {
  flex: none; width: 100%; min-height: 48px; padding: 8px 6px;
  font-size: 13px; white-space: nowrap;
}
.ghost-btn.is-primary {
  background: var(--purple); border-color: var(--purple); color: var(--white);
  font-weight: var(--w-bold);
}
.ghost-btn:disabled { opacity: 0.45; }



/* ============================================================
   Toast
   ============================================================ */
/* The cue layer that used to live here is gone. It painted a tinted
   full-screen pulse on every tap — purple for tick/commit, green for a
   submit, red for any warning — which read as the screen flashing. Every
   confirmation is now audio + haptic; the only visual feedback is the
   toast below and the deliberate sheet/drawer transitions. */

@media (prefers-reduced-motion: reduce) {
  .sheet, .drawer, .sheet-scrim, .drawer-scrim { transition: none; }
}

/* toast sits at the TOP — out of the thumb path and clear of the dock */
.toast {
  position: fixed; left: 50%;
  top: calc(var(--sat) + 10px);
  transform: translateX(-50%) translateY(-16px);
  opacity: 0; visibility: hidden;
  background: #1B1D24; color: var(--white);
  /* small and out of the way — it confirms, it doesn't announce */
  padding: 7px 13px; border-radius: var(--r-md);
  font-size: var(--fs-sm); font-weight: var(--w-medium); line-height: 1.3;
  box-shadow: 0 6px 18px rgba(16, 18, 24, 0.26);
  transition: transform 0.25s ease, opacity 0.25s ease, visibility 0.25s;
  z-index: 100; max-width: calc(100vw - 96px); text-align: center;
  pointer-events: none;   /* never eat a tap */
}
.toast.show { transform: translateX(-50%) translateY(0); opacity: 1; visibility: visible; }
/* The toast stays pointer-events:none above so it can never eat a tap.
   The action inside it is the one live thing, opted back in deliberately.
   Same hairline weight as everything else, drawn in the toast's own
   palette because it sits on the toast's own dark surface. */
.toast-act {
  pointer-events: auto; cursor: pointer;
  margin-left: 6px; padding: 3px 9px;
  border: 1px solid rgba(255, 255, 255, 0.38); border-radius: var(--r-sm);
  background: transparent; color: var(--white); font-family: var(--font);
  font-size: var(--fs-sm); font-weight: var(--w-bold);
  letter-spacing: 0.4px; text-transform: uppercase;
}

@media (max-height: 720px) {
  .total-value { font-size: 30px; }
  .stepper-lg .step-btn { width: 58px; height: 58px; }
  .stepper-lg .step-value { min-height: 58px; font-size: 30px; }
}


/* ============================================================
   HOST APP (attendee) + slide-in menu — mirrors the app's AppDrawer
   ============================================================ */
.home-bar {
  flex: none; display: flex; align-items: center; gap: var(--sp-md);
  background: var(--surface); border-bottom: 1px solid var(--hairline);
  padding: calc(var(--sp-md) + var(--sat)) var(--pad) var(--sp-md);
}
/* The home bar's menu control is the same .icon-btn + .burger-glyph the
   judge and producer strips use. It used to be a bespoke 40px rounded box
   with its own border, which read as the only boxed control in the app. */
.home-logo { height: 20px; width: auto; }
.home-bar-spacer { flex: none; width: 34px; }
.home-body { flex: 1 1 auto; padding: var(--sp-lg) var(--pad); display: flex; flex-direction: column; gap: var(--sp-sm); }
.home-card { padding: var(--sp-md); }
.home-card-title { margin: 0 0 2px; font-size: var(--fs-xl); font-weight: var(--w-bold); color: var(--text); }
.home-card-meta { margin: 0; font-size: var(--fs-sm); color: var(--text-2); }
.home-card-note { margin: var(--sp-sm) 0 0; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.45; }
.home-card-when { margin: var(--sp-sm) 0 0; font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--purple-ink); }
.home-section { margin: var(--sp-md) 0 var(--sp-xs); }
.home-section:first-child { margin-top: 0; }

.drawer-scrim {
  /* Plain viewport cover. It used to be stretched to -240px so it could
     never leave a band above the drawer — but a fixed element with a
     negative top paints into the safe area, which is what put the gray
     strip above the logo in the first place. */
  position: fixed; inset: 0; z-index: 80;
  background: rgba(0, 0, 0, 0.4);
  opacity: 0; transition: opacity 0.26s ease;
}
.drawer-scrim.is-open { opacity: 1; }
.drawer {
  position: fixed; left: 0; top: 0; bottom: 0; z-index: 90;
  width: 85%; max-width: 340px;                 /* AppDrawer: windowWidth * 0.85 */
  background: var(--surface);
  box-shadow: 2px 0 10px rgba(0, 0, 0, 0.15);   /* AppDrawer shadow */
  transform: translateX(-100%);
  transition: transform 0.32s cubic-bezier(0.32, 0.72, 0, 1);
  /* No top padding: the head owns the safe-area inset now, so its white
     runs to the very top edge instead of starting below a bare strip. */
  padding: 0 0 calc(var(--sp-lg) + var(--sab));
  /* MUST stay visible: overflow:auto here made the drawer a clipping
     container, which silently swallowed the white bleed below. Scrolling
     lives on .drawer-scroll instead. */
  overflow: visible;
  display: flex; flex-direction: column;
}
/* THE NOTCH BAND, painted white unconditionally.
   Three separate things have to be white for the top of the drawer to look
   right on a notched device: the drawer's own fill, the head's fill, and
   whatever sits in the inset band itself. Relying on the head's top PADDING
   to cover the band is the fragile part — padding only paints if the
   padding parsed, and it pushes the wordmark down rather than pulling white
   up. So this pseudo-element covers the band explicitly: from 240px above
   the drawer (overscroll headroom on iOS) down THROUGH the inset. Even if
   every other rule here failed, nothing grey can reach the strip above the
   wordmark. */
.drawer::before {
  content: ''; position: absolute; left: 0; right: 0;
  bottom: calc(100% - var(--sat));
  height: calc(240px + var(--sat));
  background: var(--surface);
}
.drawer.is-open { transform: translateX(0); }
/* The head IS the white strip at the top of the drawer. It starts flush at
   the drawer's top edge and absorbs the safe-area inset in its own padding,
   so white runs unbroken from the very top of the screen down to the
   hairline under the wordmark. The inset used to sit on .drawer's padding
   instead, which left the head floating below a separate bare strip. */
.drawer-head {
  flex: none; background: var(--surface);
  padding: calc(var(--sp-lg) + var(--sat)) var(--sp-xl) var(--sp-lg) calc(var(--sp-xl) + var(--sal));
  border-bottom: 1px solid var(--hairline); margin-bottom: var(--sp-md);
}
.drawer-logo { height: 22px; width: auto; }
/* the only scrolling region — keeps the drawer itself from clipping */
.drawer-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.drawer-body { padding: 0 var(--sp-lg) 0 calc(var(--sp-lg) + var(--sal)); }
/* Settings sits at the bottom of the drawer, as it does in the main app */
.drawer-foot {
  flex: none; padding: var(--sp-sm) var(--sp-lg) 0 calc(var(--sp-lg) + var(--sal));
  box-shadow: inset 0 1px 0 var(--hairline);
}
/* Which build the device is actually running. Deliberately quiet — it is
   a diagnostic, not information anyone reads on purpose. */
.drawer-build {
  margin: 2px 0 0 var(--sp-sm);
  font-size: var(--fs-xs); color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.drawer-section { margin: var(--sp-md) 0 var(--sp-xs) var(--sp-sm); }
.drawer-item {
  display: flex; align-items: center; gap: var(--sp-sm);
  width: 100%; text-align: left; cursor: pointer;
  padding: var(--sp-md) var(--sp-sm); margin-bottom: 2px;
  border: none; background: none; border-radius: var(--r-md);
}
.drawer-item.is-active { background: var(--purple-soft); }
.drawer-glyph {
  flex: none; width: 20px; height: 20px; margin-right: var(--sp-sm);
  background-color: var(--text-2);
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
}
.drawer-item.is-active .drawer-glyph { background-color: var(--purple); }
.drawer-text { flex: 1 1 auto; min-width: 0; }
.drawer-label { display: block; font-size: var(--fs-md); font-weight: var(--w-medium); color: var(--text); }
.drawer-item.is-active .drawer-label { font-weight: var(--w-semibold); color: var(--purple-ink); }
.drawer-note { display: block; font-size: 11px; color: var(--text-2); margin-top: 1px; }
.drawer-lock {
  display: block; width: 15px; height: 15px; background-color: var(--text-3);
  -webkit-mask: var(--icon) center / contain no-repeat;
  mask: var(--icon) center / contain no-repeat;
}
.drawer-dot { flex: none; width: 7px; height: 7px; border-radius: var(--r-full); background: var(--purple); }

/* Judge drawer: event context above the navigation, nothing else. The exit
   is on the Me tab and is deliberately not repeated here. */
.drawer-context {
  padding: 0 var(--sp-sm) var(--sp-md);
  box-shadow: inset 0 -1px 0 var(--hairline);
}
.drawer-event { margin: var(--sp-xs) 0 0; font-size: var(--fs-lg); font-weight: var(--w-bold); color: var(--text); }
.drawer-event-meta { margin: 2px 0 0; font-size: 11.5px; color: var(--text-2); line-height: 1.4; }

/* difficulty badge — lives on the Difficulty header, not the total card */
.diff-badge {
  flex: none; display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--fs-xs); font-weight: var(--w-semibold); letter-spacing: 0.3px;
  padding: 3px 8px; border-radius: var(--r-full); white-space: nowrap;
  border: 1px solid var(--hairline);
}
.diff-badge.is-pending { background: var(--warn-bg); color: var(--warn); }
.diff-badge.is-ready   { background: var(--purple-soft); color: var(--purple-ink); }
.chip-glyph { width: 13px; height: 13px; flex: none; }

.state-chip.state-overridden { background: var(--warn-bg); border: 1px solid var(--hairline); color: var(--warn); }


/* ============================================================
   First-step wayfinding — restored
   (lost in the stylesheet rebuild: the JS was still adding these
   classes, so a class-based test passed while nothing rendered)
   ============================================================ */
/* Muted, never disabled — every control stays live for a judge who
   knows what they're doing. */
/* de-emphasis only — no transition, so the change is instant, not a fade */
.is-standby { opacity: 0.5; }
.is-standby:focus-within { opacity: 1; }

/* The pulsing purple ring that used to sit on this button is gone with the
   rest of the flashes. The button is already solid purple and the only
   thing blocking submit, so it does not need to throb to be found. */


/* ============================================================
   Session — centred performance-detail layout
   ============================================================ */
.detail-card { text-align: center; padding: var(--sp-lg) var(--sp-md) var(--sp-md); }
.detail-eyebrow { margin: 0 0 var(--sp-sm); }
.detail-title {
  margin: 0; font-size: var(--fs-xxxl); font-weight: var(--w-bold);
  color: var(--text); letter-spacing: -0.3px; line-height: 1.15;
}
.detail-sub { margin: var(--sp-xs) 0 0; font-size: var(--fs-md); font-weight: var(--w-regular); color: var(--text-2); }
.detail-hero {
  margin: var(--sp-md) 0 var(--sp-lg);
  font-size: 30px; font-weight: var(--w-bold); color: var(--purple);
  letter-spacing: -0.5px; font-variant-numeric: tabular-nums;
}
/* a rule element, not a one-sided border — keeps the single-border rule */
.detail-rule { border: none; height: 1px; background: var(--hairline); margin: 0; width: 100%; }
/* paired cells two-per-row; long values span the full width */
.detail-grid { display: grid; grid-template-columns: 1fr 1fr; }
.detail-cell { position: relative; padding: var(--sp-md) var(--sp-sm); min-width: 0; }
.detail-cell.is-wide { grid-column: 1 / -1; }
/* vertical hairline between a pair — a pseudo-element, not a border */
.detail-cell.has-rule::after {
  content: ''; position: absolute; right: 0; top: 10px; bottom: 10px;
  width: 1px; background: var(--hairline);
}
.detail-grid .detail-rule { grid-column: 1 / -1; }
.detail-label {
  display: block; font-size: var(--fs-xs); font-weight: var(--w-semibold);
  text-transform: uppercase; letter-spacing: 1px; color: var(--text-2);
  margin-bottom: 3px;
}
.detail-value {
  display: block; font-size: var(--fs-lg); font-weight: var(--w-semibold);
  color: var(--text); line-height: 1.3;
}


/* ============================================================
   PRODUCER CONSOLE
   The producer's desktop view. Same tokens, same single hairline
   weight, same white-card-on-gray-canvas surface system as the judge
   app — only the density and the pointer target sizes change.

   Nothing here transitions or changes on :active. The console is
   read-only in this round, and the no-flash rule applies to the
   desktop view exactly as it does to the handheld one.
   ============================================================ */

/* ---- white top strip ----
   The element carries BOTH .judge-top and .pc-top, so the white fill, the
   single hairline below, the bare hamburger and the centred title all come
   from the judge area's own rules. .pc-top only re-proportions the strip
   for a desktop viewport: taller, wider gutters, no safe-area inset. */
.pc-top {
  /* height + the inset, NOT height alone: this rule used to be
     `padding: 0 var(--sp-xl)`, which overrode .judge-top's safe-area top
     padding and put the title and hamburger under the clock the moment the
     inset became non-zero. Same trap as the drawer head. */
  height: calc(60px + var(--sat));
  padding: var(--sat) calc(var(--sp-xl) + var(--sar)) 0 calc(var(--sp-xl) + var(--sal));
  gap: var(--sp-md);
}
.pc-top-title {
  /* .judge-top-title already pins this across the strip and centres the
     text; on the taller desktop bar it also has to centre vertically, and
     it must start BELOW the safe-area band or it sits under the clock. */
  top: var(--sat); bottom: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-md); font-weight: var(--w-bold);
  letter-spacing: 1.5px; color: var(--purple-ink);
}
/* The way back out. Deliberately quiet — it is not a pipeline action. */
.pc-exit {
  flex: none; cursor: pointer;
  padding: 8px var(--sp-lg); border-radius: var(--r-full);
  border: 1px solid var(--hairline); background: var(--surface);
  font-size: var(--fs-sm); font-weight: var(--w-semibold);
  letter-spacing: 0.2px; color: var(--text-2);
}

/* ---- event + day context ---- */
.pc-context {
  flex: none; display: flex; align-items: stretch;
  background: var(--surface); border-bottom: 1px solid var(--hairline);
}
.pc-context-block { padding: var(--sp-md) var(--sp-xl); min-width: 0; }
.pc-context-block + .pc-context-block { border-left: 1px solid var(--hairline); }
.pc-context-value {
  margin: 5px 0 0; font-size: var(--fs-xl); font-weight: var(--w-semibold);
  color: var(--text); line-height: 1.25;
}
.pc-context-meta { margin: 2px 0 0; font-size: var(--fs-sm); color: var(--text-2); }

/* ---- board canvas ---- */
.pc-main {
  flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
  gap: var(--sp-sm); padding: var(--sp-lg) var(--sp-xl) var(--sp-xl);
  background: var(--bg);
}
.pc-main-head { flex: none; display: flex; align-items: baseline; gap: var(--sp-md); }
.pc-main-note { margin: 0; font-size: var(--fs-sm); color: var(--text-2); }
/* Arena state, sitting beside the pipeline note rather than inside the
   board — it is context for the lanes, not a fourth lane. Same chip
   grammar and the same token trios as .fm-live and .status-chip. */
.pc-live {
  margin: 0 0 0 auto; padding: 4px 11px; border-radius: var(--r-full);
  border: 1px solid var(--hairline); background: var(--surface-2); color: var(--text-2);
  font-size: var(--fs-xs); font-weight: var(--w-bold);
  letter-spacing: 0.6px; text-transform: uppercase; white-space: nowrap;
}
.pc-live[data-live="ondeck"] {
  background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn);
}
.pc-live[data-live="performing"] {
  background: var(--purple-soft); border-color: var(--purple); color: var(--purple-ink);
}

/* One bordered board, lanes divided by the same hairline — so the three
   lanes read as one pipeline rather than three stacked cards. */
.pc-board {
  flex: 1 1 auto; min-height: 0;
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--e1); overflow: hidden;
}
.pc-lane { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.pc-lane + .pc-lane { border-left: 1px solid var(--hairline); }

.pc-lane-head {
  flex: none; display: flex; align-items: center; gap: var(--sp-sm);
  padding: var(--sp-md) var(--sp-lg);
  background: var(--surface); border-bottom: 1px solid var(--hairline);
}
/* Direction marker — makes the three lanes read left-to-right as a flow. */
.pc-lane-chev { width: 12px; height: 12px; flex: none; color: var(--text-3); margin-left: -4px; }
.pc-lane-head .section-label { flex: 1 1 auto; }
.pc-count {
  flex: none; min-width: 24px; padding: 2px 7px; text-align: center;
  border-radius: var(--r-full); border: 1px solid var(--hairline);
  background: var(--bg); color: var(--text-3);
  font-size: var(--fs-sm); font-weight: var(--w-semibold);
  font-variant-numeric: tabular-nums;
}
.pc-count.is-on {
  background: var(--purple-soft); border-color: var(--purple-line);
  color: var(--purple-ink);
}

/* The lane body is the sunk canvas the white cards sit on. It is the ONLY
   thing that scrolls — the page itself never does. */
.pc-lane-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--sp-md);
  padding: var(--sp-md); background: var(--bg);
}

/* ---- session card ---- */
.pc-card {
  flex: none;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--e1);
  padding: var(--sp-md) var(--sp-lg);
}
/* A Computed card is a real <button>, so it needs the UA button styling
   reset back to card. Same trick .session-card uses in the judge app. */
.pc-card-open {
  display: block; width: 100%; text-align: left;
  font: inherit; color: inherit; cursor: pointer;
}
/* "Review ›" — the judge app's own open affordance, not a boxed button:
   the card itself is the target. */
.pc-card-go {
  flex: none; display: inline-flex; align-items: center; gap: 3px;
  font-size: var(--fs-sm); font-weight: var(--w-bold); color: var(--purple);
}
.pc-card-go .row-chev { width: 15px; height: 15px; }

.pc-card-top { display: flex; align-items: baseline; gap: var(--sp-sm); }
.pc-card-title {
  margin: 0; flex: 1 1 auto; min-width: 0;
  font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text);
  line-height: 1.3;
}
.pc-card-time {
  flex: none; font-size: var(--fs-sm); color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.pc-card-meta { margin: 6px 0 0; font-size: var(--fs-md); color: var(--text-2); }
/* Routine count on the left, the release action on the right. One row, so
   adding the button costs the card ~10px rather than a whole new band. */
.pc-card-foot {
  margin: 8px 0 0; min-height: 30px;
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-sm);
}
.pc-card-count { font-size: var(--fs-sm); color: var(--text-3); }

/* ---- release actions ----
   Verify is an internal checkpoint: bordered, quiet, reversible in spirit.
   Publish pushes results to families, so it takes the solid primary fill —
   the same weight the judge app gives its Submit. No :active state on
   either, per the no-tap-feedback rule at the top of this file. */
.pc-act {
  flex: none; cursor: pointer;
  padding: 6px 14px; border-radius: var(--r-full);
  border: 1px solid var(--purple-line); background: var(--surface);
  color: var(--purple); font-size: var(--fs-sm); font-weight: var(--w-semibold);
  letter-spacing: 0.2px; white-space: nowrap;
}
.pc-act.is-publish {
  border-color: var(--purple); background: var(--purple); color: var(--white);
}

/* Terminal state. Reuses the lavender the judge app already means
   "confirmed" by, so published reads as settled rather than as a control. */
.pc-tag {
  flex: none; display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 10px; border-radius: var(--r-full);
  border: 1px solid var(--purple-line); background: var(--purple-soft);
  color: var(--purple-ink); font-size: var(--fs-sm); font-weight: var(--w-semibold);
  white-space: nowrap;
}
.pc-tag-check { width: 11px; height: 11px; flex: none; }

/* ---- empty lane ---- */
/* No box and no dashed rule: an empty lane should recede, and a second
   border weight would break the hairline rule to say nothing. */
.pc-empty { margin: auto; padding: var(--sp-lg); text-align: center; }
.pc-empty-title {
  margin: 0; font-size: var(--fs-md); font-weight: var(--w-medium); color: var(--text-3);
}
.pc-empty-line {
  margin: 5px 0 0; font-size: var(--fs-sm); color: var(--text-muted);
  line-height: 1.45; max-width: 24ch; margin-inline: auto;
}

/* Short viewports: the release action added a row to every card, and on a
   720px-tall laptop that pushed the 4th card in a full lane below the fold.
   Trim the padding rather than let a lane scroll — the whole point of the
   board is seeing the day's pipeline at once. */
@media (max-height: 820px) {
  .pc-lane-body { padding: var(--sp-sm); gap: var(--sp-sm); }
  .pc-card { padding: var(--sp-sm) var(--sp-md); }
  .pc-card-meta { margin-top: 4px; }
  .pc-card-foot { margin-top: 6px; min-height: 26px; }
  .pc-main { padding: var(--sp-md) var(--sp-xl) var(--sp-lg); }
}

/* Very short viewports — a 720p laptop leaves ~610px once browser chrome
   is taken out. Reclaim it from the chrome around the board, not from the
   board, so a full lane of four still lands above the fold. */
@media (max-height: 700px) {
  .pc-top { height: calc(52px + var(--sat)); }
  .pc-context-block { padding-block: var(--sp-sm); }
  .pc-context-value { font-size: var(--fs-lg); }
  .pc-main { padding-top: var(--sp-sm); gap: 4px; }
  .pc-card-meta { font-size: var(--fs-sm); margin-top: 3px; }
  .pc-card-foot { margin-top: 5px; min-height: 24px; }
}

/* The last reclaim, so a 1280x720 window with tabs and an address bar still
   shows a full lane. Everything trimmed here is chrome, never a card. */
@media (max-height: 640px) {
  .pc-lane-head { padding: var(--sp-sm) var(--sp-lg); }
  .pc-lane-body { gap: 6px; }
  .pc-main { padding-bottom: var(--sp-md); }
  .pc-card-title { font-size: var(--fs-md); }
}

/* Narrow screens keep all three lanes — the pipeline IS the three-across
   relationship — and just tighten up around them. */
@media (max-width: 720px) {
  .pc-top { padding-inline: calc(var(--sp-lg) + var(--sal)) calc(var(--sp-lg) + var(--sar)); }
  .pc-context-block { padding-inline: var(--sp-lg); }
  .pc-main { padding: var(--sp-md) var(--sp-lg) var(--sp-lg); }
  .pc-lane-head { padding: var(--sp-sm) var(--sp-md); }
  .pc-lane-body { padding: var(--sp-sm); gap: var(--sp-sm); }
  .pc-card { padding: var(--sp-sm) var(--sp-md); }
  .pc-card-top { flex-wrap: wrap; }
  /* count and action stack rather than overflow when the lane gets narrow */
  .pc-card-foot { flex-wrap: wrap; gap: 6px; }
  .pc-act, .pc-tag { padding-inline: 10px; }
}


/* ============================================================
   VERIFY REVIEW DRILL-IN
   Same skeleton as the scoring cockpit — fixed strip, fixed dock,
   one scrolling region between them — proportioned for a desktop
   viewport. No :active anywhere, per the policy at the top.
   ============================================================ */
/* .detail-top supplies the white fill, the hairline and the bare chevron;
   this only re-proportions it, exactly as .pc-top does for the console. */
/* Same inset trap as .pc-top — see the note there. */
.pcr-top {
  height: calc(60px + var(--sat));
  padding: var(--sat) calc(var(--sp-xl) + var(--sar)) 0 calc(var(--sp-xl) + var(--sal));
  gap: var(--sp-md);
}
.pcr-top .icon-btn { width: 34px; height: 34px; }
.pcr-top .detail-top-title { font-size: var(--fs-xl); }
/* Where this session sits in the pipeline, so the drill-in never floats
   free of the board it came from. */
.pcr-stage {
  flex: none; padding: 4px 12px; border-radius: var(--r-full);
  border: 1px solid var(--hairline); background: var(--bg);
  color: var(--text-3); font-size: var(--fs-xs); font-weight: var(--w-semibold);
  text-transform: uppercase; letter-spacing: 1px;
}

.pcr-main {
  flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
  gap: var(--sp-sm); padding: var(--sp-lg) var(--sp-xl) var(--sp-md);
  background: var(--bg);
}
.pcr-head { flex: none; display: flex; align-items: baseline; gap: var(--sp-md); }
.pcr-note { margin: 0; font-size: var(--fs-sm); color: var(--text-2); }

/* THE only scrolling region on this screen. */
.pcr-scroll {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--sp-sm);
  padding-right: 2px;   /* keeps the shadow off the scrollbar */
}

/* ---- ranked result row ---- */
.pcr-row {
  flex: none; display: flex; align-items: center; gap: var(--sp-lg);
  padding: var(--sp-md) var(--sp-lg);
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--e1);
}
/* Placement reads as a rank, not a control — no fill, just the numeral. */
.pcr-place {
  flex: none; width: 30px; text-align: center;
  font-size: var(--fs-xl); font-weight: var(--w-bold); color: var(--purple-ink);
  font-variant-numeric: tabular-nums;
}
/* The top three carry the brand purple; the rest stay quiet, so a glance
   finds the podium without the list turning into a colour chart. */
.pcr-row:not(.is-podium) .pcr-place { color: var(--text-3); font-weight: var(--w-semibold); }
.pcr-info { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.pcr-team {
  font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pcr-meta {
  font-size: var(--fs-sm); color: var(--text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pcr-score {
  flex: none; font-size: var(--fs-xxl); font-weight: var(--w-bold);
  color: var(--text); font-variant-numeric: tabular-nums; letter-spacing: -0.3px;
}

/* ---- fixed dock ----
   Mirrors .submit-dock: white, hairline above, lifted off the canvas. */
.pcr-dock {
  flex: none; display: flex; align-items: center; gap: var(--sp-xl);
  background: var(--surface); border-top: 1px solid var(--hairline);
  padding: var(--sp-md) var(--sp-xl);
  box-shadow: 0 -3px 14px rgba(16, 18, 24, 0.08);
}
.pcr-dock-note {
  flex: 1 1 auto; margin: 0; max-width: 62ch;
  font-size: var(--fs-sm); color: var(--text-2); line-height: 1.45;
}
/* The commitment on this screen, so it takes the primary fill the judge
   app gives Submit. */
.pcr-verify {
  flex: none; cursor: pointer; min-height: 46px; padding: 0 var(--sp-xxl);
  border: none; border-radius: var(--r-lg);
  background: var(--purple); color: var(--white);
  font-size: var(--fs-lg); font-weight: var(--w-semibold); box-shadow: var(--e2);
}

@media (max-height: 700px) {
  .pcr-top { height: calc(52px + var(--sat)); }
  .pcr-main { padding: var(--sp-md) var(--sp-xl) var(--sp-sm); }
  .pcr-row { padding: var(--sp-sm) var(--sp-lg); }
  .pcr-dock { padding: var(--sp-sm) var(--sp-xl); }
  .pcr-verify { min-height: 42px; }
}
@media (max-width: 720px) {
  .pcr-top { padding-inline: calc(var(--sp-lg) + var(--sal)) calc(var(--sp-lg) + var(--sar)); }
  .pcr-dock { padding-inline: var(--sp-lg); }
  .pcr-main { padding: var(--sp-md) var(--sp-lg) var(--sp-sm); }
  .pcr-row { gap: var(--sp-md); padding: var(--sp-sm) var(--sp-md); }
  .pcr-dock { flex-wrap: wrap; gap: var(--sp-sm); }
  .pcr-dock-note { flex: 1 1 100%; }
  .pcr-verify { flex: 1 1 auto; }
}


/* ============================================================
   COACH APP
   Handheld proportions — a coach reads this in the stands, not at
   a desk — so the strip is the judge area's unmodified .judge-top.
   On a wide screen the column centres rather than stretching a
   phone layout across 1440px.
   ============================================================ */
.ca-head {
  flex: none; background: var(--surface);
  border-bottom: 1px solid var(--hairline);
  padding: var(--sp-md) var(--pad);
}
.ca-head-inner, .ca-list { width: 100%; max-width: 560px; margin-inline: auto; }
.ca-head-note { margin: 4px 0 0; font-size: var(--fs-sm); color: var(--text-2); }

/* The only scrolling region: strip and header stay put. */
.ca-scroll {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  background: var(--bg); padding: var(--sp-md) var(--pad) var(--sp-xl);
}
.ca-list { display: flex; flex-direction: column; gap: var(--sp-sm); }

.ca-card {
  flex: none;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--e1);
  padding: var(--sp-md);
}
.ca-card-top { display: flex; align-items: baseline; gap: var(--sp-sm); }
.ca-team {
  margin: 0; flex: 1 1 auto; min-width: 0;
  font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ca-meta { margin: 3px 0 0; font-size: var(--fs-sm); color: var(--text-2); }
.ca-card-foot {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between;
  gap: var(--sp-sm); margin-top: var(--sp-sm);
}
.ca-session { font-size: var(--fs-sm); color: var(--text-3); min-width: 0; }

/* ---- released ---- */
.ca-place {
  flex: none; font-size: var(--fs-lg); font-weight: var(--w-bold);
  color: var(--purple-ink); font-variant-numeric: tabular-nums;
}
.ca-score {
  flex: none; font-size: var(--fs-xxl); font-weight: var(--w-bold);
  color: var(--text); font-variant-numeric: tabular-nums; letter-spacing: -0.3px;
}

/* ---- locked ----
   The row still shows the routine, the division and when it skated: the
   coach knows the result exists and is simply not theirs to see yet. Only
   the placement and the number are withheld. Quiet, not alarming — nothing
   has gone wrong, the producer just hasn't released it. */
.ca-lock-tag {
  flex: none; display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: var(--r-full);
  border: 1px solid var(--hairline); background: var(--bg);
  color: var(--text-3); font-size: var(--fs-xs); font-weight: var(--w-semibold);
  text-transform: uppercase; letter-spacing: 0.6px;
}
.ca-lock { width: 11px; height: 11px; flex: none; }
/* Its own full-width row, always. Beside the session line it collided with
   the time and broke "9:04 AM" across two lines on a phone. */
.ca-pending {
  flex: 1 1 100%; margin: 2px 0 0;
  font-size: var(--fs-sm); color: var(--text-muted);
}
/* Locked rows sit a step back from released ones without going grey — the
   hairline stays the single weight, only the fill softens. */
.ca-card[data-released="false"] { background: var(--surface-2); }

@media (max-width: 380px) {
  .ca-card-foot { gap: 4px; }
  .ca-session { flex: 1 1 100%; }
}


/* ---- coach: judge note chip + read-only playback ---- */
.ca-notes { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--sp-sm); }
/* Lavender, like every other "the panel confirmed this" surface in the app. */
.ca-note {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  padding: 5px 11px 5px 9px; border-radius: var(--r-full);
  border: 1px solid var(--purple-line); background: var(--purple-soft);
  color: var(--purple-ink); font-size: var(--fs-sm); font-weight: var(--w-semibold);
}
.ca-note-play { width: 12px; height: 12px; flex: none; }
.ca-note-dur { color: var(--text-2); font-weight: var(--w-medium); font-variant-numeric: tabular-nums; }

/* The waveform doubles as the progress bar: bars behind the playhead take
   the brand purple, the rest keep the judge side's idle tint. */
.wave i.is-played { background: var(--purple); }
.wave { cursor: pointer; }

/* Same box as the judge's transcript field, minus the field. */
.transcript.is-readonly {
  margin: 0; resize: none; white-space: pre-wrap;
  background: var(--surface-2);
}


/* ============================================================
   FAMILY / SPECTATOR APP — the attendee app's own shell
   This is the REAL app chrome, not a mode strip: a white header with
   the hamburger and a large LEFT-ALIGNED title, the day underneath,
   message and share at the right. There is deliberately no centred
   wordmark here — that belongs to the host home screen.
   Head and nav are fixed; the body between them is the one scroller.
   Nothing here has a :active rule — see the note at the top of the file.
   ============================================================ */
.fm-top {
  flex: none; z-index: 20;
  background: var(--surface); border-bottom: 1px solid var(--hairline);
  padding: calc(var(--sp-sm) + var(--sat)) var(--pad) var(--sp-md);
}
.fm-top-row { display: flex; align-items: center; gap: var(--sp-sm); }
/* Left-aligned and large. The judge/producer strips centre their titles
   because those are mode chrome; this is the app's own screen title. */
.fm-top-title {
  flex: 1 1 auto; min-width: 0; margin: 0;
  font-size: var(--fs-xxl); font-weight: var(--w-bold);
  color: var(--text); letter-spacing: -0.3px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fm-top-actions { flex: none; display: flex; align-items: center; gap: 6px; }
.fm-glyph { width: 21px; height: 21px; display: block; }
/* Share sits in the app's lavender disc; messages is a bare glyph, so the
   two read as different weights of action rather than a pair of buttons. */
.fm-circle-btn {
  flex: none; width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid var(--purple-line); background: var(--purple-soft);
  color: var(--purple-ink); cursor: pointer;
  display: grid; place-items: center; padding: 0;
}
.fm-circle-btn .fm-glyph { width: 17px; height: 17px; }
.fm-top-date { margin: 2px 0 0 42px; font-size: var(--fs-sm); color: var(--text-3); }

/* The one scroll region. */
.fm-scroll {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--sp-lg) var(--pad) var(--sp-xl);
}
.fm-scroll > * { width: 100%; max-width: 560px; margin-inline: auto; }
.fm-section { margin: var(--sp-lg) 0 var(--sp-sm); }
.fm-section-first { margin-top: 0; }

/* ---- NEXT UP ---- */
.fm-nu { padding: 0; overflow: hidden; }
/* The routine is its own button so the card can also carry the View
   Schedule link — see the note on familyNextCard(). It has no border or
   background of its own; the card around it is the surface. */
.fm-nu-open {
  display: flex; flex-direction: column; width: 100%; text-align: left;
  border: none; background: none; cursor: pointer;
  padding: var(--sp-md) var(--sp-md) 0;
}
.fm-nu-top { display: flex; align-items: flex-start; gap: var(--sp-sm); }
.fm-nu-lead { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.fm-nu-day { font-size: var(--fs-sm); color: var(--text-3); }
/* The countdown is the one number on this screen — a solid purple pill,
   the same fill the app gives its primary actions. */
.fm-pill {
  flex: none; padding: 5px 12px; border-radius: var(--r-full);
  background: var(--purple); color: var(--white);
  font-size: var(--fs-sm); font-weight: var(--w-bold);
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.fm-nu-team {
  display: block; margin: var(--sp-sm) 0 0;
  font-size: var(--fs-xxxl); font-weight: var(--w-bold);
  color: var(--text); letter-spacing: -0.4px; line-height: 1.15;
}
.fm-nu-program { display: block; margin: 3px 0 0; font-size: var(--fs-md); color: var(--text-2); }

.fm-nu-facts { display: flex; flex-wrap: wrap; gap: var(--sp-sm) var(--sp-lg); margin-top: var(--sp-md); }
.fm-fact {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--text);
}
.fm-ico { width: 15px; height: 15px; flex: none; color: var(--purple); }

/* ---- live status: where the routine is in the room ----
   Same chip grammar as .status-chip in the judge app — one hairline, the
   same three token trios — so a parent and a judge are reading the same
   visual language. Static states, no pulse and no flash: "on the mat now"
   is a fact the card is holding, not an animation. */
.fm-live {
  /* The card is a column flex, which would otherwise stretch a chip to
     the full width and turn it into a banner. It is a chip. */
  align-self: flex-start;
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: var(--sp-md); padding: 5px 11px; border-radius: var(--r-full);
  border: 1px solid var(--hairline); background: var(--surface-2);
}
.fm-live-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: currentColor; }
.fm-live-text {
  font-size: var(--fs-xs); font-weight: var(--w-bold);
  letter-spacing: 0.6px; text-transform: uppercase; white-space: nowrap;
}
.fm-live[data-live="ondeck"] {
  background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn);
}
.fm-live[data-live="performing"] {
  background: var(--purple-soft); border-color: var(--purple); color: var(--purple-ink);
}
.fm-live[data-live="done"] {
  background: var(--good-bg); border-color: var(--good-line); color: var(--good);
}

.fm-nu-foot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-sm);
  margin: var(--sp-md) var(--sp-md) 0; padding: var(--sp-sm) 0;
  border-top: 1px solid var(--hairline);
}
.fm-nu-session { font-size: var(--fs-sm); color: var(--text-3); min-width: 0; }
/* A text link, not a button: the commitment on this card is elsewhere. */
.fm-link {
  flex: none; display: inline-flex; align-items: center; gap: 2px; cursor: pointer;
  border: none; background: none; padding: 4px 0;
  font-size: var(--fs-sm); font-weight: var(--w-bold); color: var(--purple);
}
.fm-link .row-chev { width: 15px; height: 15px; }
.fm-nu.is-empty { padding: var(--sp-md) var(--sp-md) var(--sp-sm); }
.fm-nu.is-empty .fm-blank-title { margin-top: 6px; }

/* ---- grouped rows: one card, hairline-separated ---- */
.fm-rows { padding: 0; overflow: hidden; }
.fm-row {
  display: flex; align-items: center; gap: var(--sp-md);
  width: 100%; text-align: left; cursor: pointer;
  padding: var(--sp-md); border: none; background: none;
}
.fm-rows .fm-row + .fm-row { border-top: 1px solid var(--hairline); }
/* Wide enough for "10:42 AM" on one line at bold 14px — at 62px the
   meridiem wrapped under the digits and the column stopped scanning. */
.fm-row-time {
  flex: none; width: 74px; white-space: nowrap;
  font-size: var(--fs-md); font-weight: var(--w-bold);
  color: var(--purple-ink); font-variant-numeric: tabular-nums;
}
.fm-row-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.fm-row-team { display: flex; align-items: center; gap: 5px; min-width: 0; }
.fm-row-name {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text);
}
.fm-star { width: 12px; height: 12px; flex: none; color: var(--purple); }
.fm-row-where {
  display: flex; align-items: center; gap: 5px; min-width: 0;
  font-size: var(--fs-sm); color: var(--text-3);
}
.fm-row-where .fm-ico { width: 13px; height: 13px; color: var(--text-3); }
.fm-row .row-chev { flex: none; width: 16px; height: 16px; color: var(--text-3); }

/* ---- MY ITINERARIES ---- */
.fm-itin {
  display: flex; align-items: center; gap: var(--sp-md);
  width: 100%; text-align: left; cursor: pointer;
  padding: var(--sp-md); border: none; background: none;
}
.fm-itin-badge {
  flex: none; width: 38px; height: 38px; border-radius: 50%;
  background: var(--purple-soft); border: 1px solid var(--purple-line);
  display: grid; place-items: center; color: var(--purple);
}
.fm-itin-badge .fm-ico { width: 18px; height: 18px; }
.fm-itin-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.fm-itin-title {
  font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fm-itin-meta { font-size: var(--fs-sm); color: var(--text-3); }
.fm-itin-next { font-size: var(--fs-sm); font-weight: var(--w-semibold); color: var(--purple-ink); }
.fm-itin .row-chev { flex: none; width: 16px; height: 16px; color: var(--text-3); }

/* ---- empty + not-yet-built states: what is missing, and where to go ---- */
.fm-blank { padding: var(--sp-lg) var(--sp-md); }
.fm-blank-card { padding: var(--sp-lg) var(--sp-md); }
.fm-blank-title { margin: 0; font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text); }
.fm-blank-line { margin: 5px 0 0; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.45; }
.fm-blank-card .fm-link { margin-top: var(--sp-md); }

/* ============================================================
   THE PUSHED SCHEDULE SCREEN
   Centred event title, the day and hall dropdowns, then the day as one
   FLAT running order. Everything down to the search row is fixed; only
   the list scrolls, and the FILTERS pill floats over it.
   No :active rules here either — see the note at the top of the file.
   ============================================================ */
.fs-top {
  flex: none; z-index: 20;
  background: var(--surface); border-bottom: 1px solid var(--hairline);
  padding: calc(var(--sp-sm) + var(--sat)) var(--pad) var(--sp-md);
}
.fs-top-row { display: flex; align-items: center; gap: 2px; }
.fs-top-spacer { flex: 1 1 auto; }
.fs-glyph { width: 21px; height: 21px; display: block; }
.fs-glyph-sm { width: 17px; height: 17px; display: block; }

/* One star path, outline until it is on. Filling it IS the state — there
   is no separate chip or colour swap doing the work. */
.fs-star-glyph {
  width: 21px; height: 21px; display: block;
  fill: none; stroke: currentColor; stroke-width: 1.7;
}
#fmsFav.is-on { color: var(--purple); }
#fmsFav.is-on .fs-star-glyph { fill: currentColor; }

/* Centred, unlike Your Day's left-aligned title: this screen is ABOUT the
   event, so the event name is the subject rather than the section name. */
.fs-title {
  margin: 2px 0 0; text-align: center;
  font-size: var(--fs-xxl); font-weight: var(--w-bold);
  color: var(--text); letter-spacing: -0.3px; line-height: 1.2;
}
.fs-venue {
  margin: 4px 0 0;
  display: flex; align-items: center; justify-content: center; gap: 5px;
  font-size: var(--fs-sm); color: var(--text-3); text-align: center;
}
.fs-venue .fm-ico { width: 13px; height: 13px; flex: none; color: var(--text-3); }

.fs-pills {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-sm); margin-top: var(--sp-md);
}
.fs-pill { max-width: 48%; }

.fs-search { display: flex; align-items: center; gap: var(--sp-sm); margin-top: var(--sp-sm); }
/* The field carries the filter glyph inside it, so the padding has to
   leave room rather than letting the text run under the icon. */
.fs-search-box { position: relative; flex: 1 1 auto; min-width: 0; display: block; }
.fs-search-input { width: 100%; padding-right: 38px; }
.fs-search-glyph {
  position: absolute; right: 11px; top: 50%; transform: translateY(-50%);
  display: block; color: var(--text-3); pointer-events: none;
}

/* ---- the flat list ---- */
.fs-scroll {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--sp-md) var(--pad) 92px;
  display: flex; flex-direction: column; gap: var(--sp-sm);
}
.fs-scroll > * { width: 100%; max-width: 560px; margin-inline: auto; }

.fs-row {
  display: flex; align-items: stretch; gap: 0;
  width: 100%; flex: none; text-align: left; cursor: pointer;
  padding: 0; overflow: hidden;
  border: 1px solid var(--hairline); border-radius: var(--r-lg);
  background: var(--surface); box-shadow: var(--e1);
}
/* The stacked time sits in its own tinted cell, divided from the routine
   by the same hairline everything else uses. */
.fs-time {
  flex: none; width: 66px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: var(--sp-md) 6px;
  background: var(--bg); border-right: 1px solid var(--hairline);
}
.fs-time-clock {
  font-size: var(--fs-lg); font-weight: var(--w-bold);
  color: var(--purple-ink); font-variant-numeric: tabular-nums; line-height: 1.1;
}
.fs-time-mer {
  margin-top: 1px; font-size: var(--fs-xs); font-weight: var(--w-semibold);
  letter-spacing: 0.6px; color: var(--text-3);
}

.fs-main {
  flex: 1 1 auto; min-width: 0;
  display: flex; flex-direction: column; gap: 1px;
  padding: var(--sp-md) var(--sp-md) var(--sp-md) var(--sp-md);
}
.fs-team { display: flex; align-items: center; gap: 5px; min-width: 0; }
.fs-team-name {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text);
}
.fs-level { font-size: var(--fs-sm); color: var(--text-2); }
/* Uppercase, like every other supporting label in the app. */
.fs-program {
  font-size: var(--fs-xs); font-weight: var(--w-semibold);
  letter-spacing: 0.6px; text-transform: uppercase; color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.fs-right {
  flex: none; display: flex; align-items: center; gap: var(--sp-sm);
  padding: var(--sp-md) var(--sp-md) var(--sp-md) 0;
}
.fs-ico { width: 17px; height: 17px; display: block; }
/* Scheduled is the only status this round, so it reads as neutral rather
   than as a live or scored colour it has not earned. */
.fs-status { display: block; color: var(--text-3); }
.fs-bell { display: block; color: var(--purple); }
.fs-right .row-chev { width: 16px; height: 16px; color: var(--text-3); }

/* The pill is the judge list's own — it just needs showing on this screen
   and lifting clear of a bottom bar this screen does not have. */
body[data-screen="famsched"] .fs-filters { display: flex; bottom: calc(var(--sab) + 22px); }

@media (max-width: 360px) {
  .fs-time { width: 60px; }
  .fs-title { font-size: var(--fs-xl); }
  .fs-right { gap: 6px; }
}


/* Narrow phones: the title and the big team name give first. */
@media (max-width: 360px) {
  .fm-row-time { width: 68px; font-size: var(--fs-sm); }
  .fm-nu-team { font-size: var(--fs-xxl); }
  .fm-top-title { font-size: var(--fs-xl); }
}


/* ============================================================
   SCORING — the family's results board
   Its controls sit in a fixed bar between the header and the scroll
   region, so the view toggle and the session picker stay put while the
   board moves. The toggle is the judge cockpit's own segmented control
   (.caption-pager / .pager-btn) and the pills are the schedule screen's.
   No :active rules here either — see the note at the top of the file.
   ============================================================ */
.fm-subhead {
  flex: none; z-index: 15;
  background: var(--surface); border-bottom: 1px solid var(--hairline);
  padding: var(--sp-sm) var(--pad) var(--sp-md);
}
.fm-subhead > * { width: 100%; max-width: 560px; margin-inline: auto; }
.fm-subhead .caption-pager { margin-bottom: var(--sp-sm); }
.fm-subhead .fs-pills { margin-top: 0; }

.sc-note { margin: 0 0 var(--sp-sm); font-size: var(--fs-sm); color: var(--text-2); }

/* ---- one board row ---- */
.sc-row {
  display: flex; align-items: center; gap: var(--sp-md);
  width: 100%; text-align: left; cursor: pointer;
  padding: var(--sp-md); border: none; background: none;
}
.fm-rows .sc-row + .sc-row { border-top: 1px solid var(--hairline); }
/* Placement is the column the eye runs down, so it leads in brand purple
   and holds its width rather than sliding with the team name. */
.sc-place {
  flex: none; width: 42px;
  font-size: var(--fs-xl); font-weight: var(--w-bold);
  color: var(--purple); font-variant-numeric: tabular-nums;
}
.sc-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.sc-team { display: flex; align-items: center; gap: 5px; min-width: 0; }
.sc-team-name {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text);
}
.sc-level { font-size: var(--fs-sm); color: var(--text-2); }
.sc-program {
  font-size: var(--fs-xs); font-weight: var(--w-semibold);
  letter-spacing: 0.6px; text-transform: uppercase; color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sc-from {
  margin-top: 2px; font-size: var(--fs-sm); color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sc-score {
  flex: none; font-size: var(--fs-xl); font-weight: var(--w-bold);
  color: var(--purple-ink); font-variant-numeric: tabular-nums;
}

/* ---- pending: the coach app's tag and wording, unchanged ---- */
.sc-pending { padding: var(--sp-md); background: var(--surface-2); }
.sc-pending-title { margin: var(--sp-sm) 0 0; font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text); }
.sc-pending-line { margin: 5px 0 0; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.45; }

@media (max-width: 360px) {
  .sc-place { width: 36px; font-size: var(--fs-lg); }
  .sc-from {
  margin-top: 2px; font-size: var(--fs-sm); color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sc-score { font-size: var(--fs-lg); }
}


/* ============================================================
   FAMILY PERFORMANCE DETAIL — one structured, centred card
   Header, time, actions, prep times, facts and the gated Result are all
   BLOCKS of a single white card, divided by the one hairline. The Result
   block is where the real app puts an add-score affordance: a parent has
   no business adding a score, so the reveal takes that slot instead.
   No :active rules here either — see the note at the top of the file.
   ============================================================ */
.fd-scroll {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--sp-lg) var(--pad) var(--sp-xl);
}
.fd-scroll > * { width: 100%; max-width: 560px; margin-inline: auto; }

.fd-card { padding: 0; overflow: hidden; }
/* One divider rule for the whole card — every block gets the same
   hairline from its predecessor, so none can drift to a second weight. */
.fd-block { padding: var(--sp-md); }
.fd-block + .fd-block { border-top: 1px solid var(--hairline); }

/* ---- 1. header ---- */
.fd-head { text-align: center; padding: var(--sp-lg) var(--sp-md) var(--sp-md); }
.fd-team {
  display: flex; align-items: center; justify-content: center; gap: 7px;
  margin: 0; min-width: 0;
}
.fd-team-name {
  font-size: var(--fs-xxxl); font-weight: var(--w-bold);
  color: var(--text); letter-spacing: -0.4px; line-height: 1.15;
}
.fd-head .fm-star { width: 14px; height: 14px; }
.fd-div { margin: 4px 0 0; font-size: var(--fs-md); color: var(--text-2); }

/* ---- 3. time ---- */
.fd-when { text-align: center; }
.fd-clock { margin: 0; display: flex; align-items: baseline; justify-content: center; gap: 6px; flex-wrap: wrap; }
.fd-clock-value {
  font-size: var(--fs-xxl); font-weight: var(--w-bold);
  color: var(--text); font-variant-numeric: tabular-nums;
}
/* The countdown is the live part of this block, so it carries the brand
   colour and the time next to it does not compete for it. */
.fd-count { font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--purple); }
.fd-where {
  margin: 6px 0 0;
  display: flex; align-items: center; justify-content: center; gap: 5px;
  font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--text);
}
.fd-where .fm-ico { width: 14px; height: 14px; flex: none; color: var(--purple); }
.fd-venue { margin: 2px 0 0; font-size: var(--fs-sm); color: var(--text-3); }

/* ---- 5. action row ---- */
.fd-actions { display: flex; align-items: flex-start; }
.fd-act {
  flex: 1 1 0; min-width: 0; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  border: none; background: none; padding: 4px 2px;
  color: var(--text-2);
}
.fd-ico { width: 19px; height: 19px; display: block; }
.fd-act-icon { display: grid; place-items: center; width: 38px; height: 38px; }
/* The active one wears the app's lavender disc; the other two are bare
   glyphs, which is what makes the active one read as active. */
.fd-act.is-on { color: var(--purple); }
.fd-act.is-on .fd-act-icon {
  border-radius: 50%; background: var(--purple-soft);
  border: 1px solid var(--purple-line);
}
.fd-act-label { font-size: var(--fs-sm); font-weight: var(--w-semibold); }
.fd-act.is-on .fd-act-label { color: var(--purple-ink); }

/* ---- 7. prep times ---- */
.fd-prep { margin-top: var(--sp-sm); display: flex; flex-direction: column; }
.fd-prep-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-sm);
  padding: 7px 0;
}
.fd-prep-row + .fd-prep-row { border-top: 1px solid var(--hairline); }
.fd-prep-main {
  display: flex; align-items: center; gap: 8px; min-width: 0;
  font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--text);
}
.fd-prep-main .fd-ico { width: 16px; height: 16px; flex: none; color: var(--text-3); }
.fd-prep-at {
  flex: none; font-size: var(--fs-md); font-weight: var(--w-bold);
  color: var(--purple); font-variant-numeric: tabular-nums;
}

/* ---- 9. the flat facts ---- */
.fd-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-md); }
.fd-cell-wide { margin-top: var(--sp-md); }
.fd-value { margin: 3px 0 0; font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text); }

/* ---- 11. LOCKED: the coach app's tag and wording, unchanged ---- */
.fd-locked .ca-lock-tag { margin-top: var(--sp-sm); }
.fd-locked-title { margin: var(--sp-sm) 0 0; font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text); }
.fd-locked-line { margin: 5px 0 0; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.45; }

/* ---- 11. REVEALED ---- */
.fd-score {
  display: flex; align-items: center; gap: var(--sp-md);
  margin-top: var(--sp-sm); padding: var(--sp-md);
  border: 1px solid var(--purple-line); border-radius: var(--r-lg);
  background: var(--surface);
}
.fd-score-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.fd-score-label {
  font-size: var(--fs-xs); font-weight: var(--w-bold);
  letter-spacing: 0.7px; text-transform: uppercase; color: var(--text-3);
}
.fd-score-value {
  font-size: var(--fs-title); font-weight: var(--w-bold);
  color: var(--purple-ink); font-variant-numeric: tabular-nums; line-height: 1.1;
}
.fd-score-side {
  flex: none; display: flex; flex-direction: column; align-items: center;
  padding: var(--sp-sm) var(--sp-md); border-radius: var(--r-lg);
  border: 1px solid var(--purple-line); background: var(--purple-soft);
}
.fd-place { font-size: var(--fs-xxl); font-weight: var(--w-bold); color: var(--purple); line-height: 1.1; }
.fd-place-note { margin-top: 2px; font-size: var(--fs-xs); color: var(--purple-ink); text-align: center; }
.fd-foot { margin: var(--sp-sm) 0 0; font-size: var(--fs-sm); color: var(--text-3); line-height: 1.45; }

.fd-notes .ca-notes { margin-top: var(--sp-sm); }

@media (max-width: 360px) {
  .fd-team-name { font-size: var(--fs-xxl); }
  .fd-score-value { font-size: var(--fs-xxxl); }
  .fd-act-label { font-size: var(--fs-xs); }
}


/* ============================================================
   SETTINGS PANEL
   The app's full Settings screen, in the shared sheet. Grouped
   white blocks on an off-white body, the way the real screen
   reads, with the head pinned and only the body scrolling.
   Nothing here transitions or reacts to :active — see the
   no-tap-feedback note at the top of this file.
   ============================================================ */
/* Panel variant of .sheet: the sheet stops scrolling as one block and
   becomes a column with its own scroll region. */
.sheet.is-panel {
  padding: 0; overflow: hidden;
  display: flex; flex-direction: column;
  max-height: 92dvh;
}

/* ---- pinned head: circular X at the left, centred title ---- */
.set-head {
  flex: none; position: relative;
  display: flex; align-items: center;
  padding: var(--sp-md) var(--sp-lg);
  background: var(--surface); border-bottom: 1px solid var(--hairline);
  border-radius: 22px 22px 0 0;
}
.set-x {
  flex: none; z-index: 1; cursor: pointer;
  width: 32px; height: 32px; border-radius: 50%;
  border: 1px solid var(--hairline); background: var(--surface);
  color: var(--text); font-size: 20px; line-height: 1;
  display: grid; place-items: center; padding: 0;
}
/* Centred against the strip, not against the space the X leaves over. */
.set-title {
  position: absolute; left: 0; right: 0; margin: 0;
  text-align: center; pointer-events: none;
  font-size: var(--fs-xl); font-weight: var(--w-bold); color: var(--text);
  letter-spacing: -0.2px;
}

/* ---- the one scrolling region ---- */
.set-scroll {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  background: var(--bg);
  padding-bottom: calc(var(--sp-lg) + max(var(--sab), 14px));
}

/* Off-white shows between groups — that gap IS the section separator. */
.set-section {
  margin: var(--sp-lg) var(--sp-lg) var(--sp-xs);
  font-size: var(--fs-xs); font-weight: var(--w-semibold);
  text-transform: uppercase; letter-spacing: 1px; color: var(--text-2);
}
.set-group {
  background: var(--surface);
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}

/* ---- a row ---- */
.set-row {
  display: flex; align-items: center; gap: var(--sp-lg);
  padding: var(--sp-md) var(--sp-lg);
}
/* One hairline BETWEEN rows, never above the first or below the last. */
.set-row + .set-row,
.set-group .pref-row + .pref-row { border-top: 1px solid var(--hairline); }
.set-row.is-stacked { padding-bottom: var(--sp-sm); }
.set-row-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.set-row-label { font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text); }
.set-row-sub { font-size: var(--fs-sm); color: var(--text-2); line-height: 1.45; }

/* ---- toggle ---- */
.set-toggle {
  flex: none; cursor: pointer; width: 51px; height: 31px;
  border-radius: var(--r-full); padding: 2px;
  border: 1px solid var(--hairline); background: var(--bg-sunk);
  display: flex; align-items: center; justify-content: flex-start;
}
.set-toggle.is-on {
  background: var(--purple); border-color: var(--purple);
  justify-content: flex-end;
}
.set-knob {
  display: block; width: 25px; height: 25px; border-radius: 50%;
  background: var(--white); box-shadow: var(--e1);
}

/* ---- lead-time pills ---- */
.set-pills {
  display: flex; flex-wrap: wrap; gap: var(--sp-sm);
  padding: 0 var(--sp-lg) var(--sp-md);
}
.set-pill {
  flex: 0 0 auto; cursor: pointer;
  padding: 8px 14px; border-radius: var(--r-full);
  border: 1px solid var(--hairline); background: var(--bg-sunk); color: var(--text);
  font-size: var(--fs-sm); font-weight: var(--w-semibold);
}
.set-pill.is-on {
  background: var(--purple); border-color: var(--purple); color: var(--white);
}

/* ---- always-on tag ----
   The app's own success pairing: white on the raw green fails AA at this
   size, so it takes the darkened ink on the tint instead. */
.set-always {
  flex: none; white-space: nowrap;
  padding: 5px 12px; border-radius: var(--r-full);
  border: 1px solid var(--good-line); background: var(--good-bg); color: var(--good-ink);
  font-size: var(--fs-xs); font-weight: var(--w-semibold);
  text-transform: uppercase; letter-spacing: 0.6px;
}

/* Mode rows reuse .pref-row; inside a group they lose their own chrome so
   they sit flush with the toggle rows above them. */
.set-group .pref-row {
  border: none; border-radius: 0; background: var(--surface);
  padding: var(--sp-md) var(--sp-lg); width: 100%;
}


/* ============================================================
   COACH SCORESHEET  (score review + inquiry)
   ============================================================
   The coach's own routine in full. Same card grammar and the same one
   hairline as every other surface in the app. */
.cd-scroll {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--sp-lg) var(--pad) var(--sp-xl);
  display: flex; flex-direction: column; gap: var(--sp-md);
}
.cd-card { padding: var(--sp-lg); }
.cd-team { margin: 4px 0 0; font-size: var(--fs-xxl); font-weight: var(--w-bold); color: var(--text); }
.cd-meta { margin: 2px 0 0; font-size: var(--fs-md); color: var(--text-2); }
.cd-window {
  margin: var(--sp-md) 0 0; padding: var(--sp-sm) var(--sp-md);
  border: 1px solid var(--purple-line); border-radius: var(--r-md);
  background: var(--purple-soft);
  font-size: var(--fs-sm); color: var(--purple-ink); line-height: 1.5;
}

/* ---- caption breakdown ---- */
.cd-rows { margin-top: var(--sp-sm); }
.cd-row {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-sm);
  padding: var(--sp-sm) 0; border-bottom: 1px solid var(--hairline);
}
.cd-row:last-child { border-bottom: 0; }
.cd-row-label { font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--text); }
.cd-row-nums { display: flex; gap: var(--sp-md); }
.cd-num { display: flex; flex-direction: column; align-items: flex-end; }
.cd-num em { font-style: normal; font-size: var(--fs-xs); letter-spacing: 0.5px;
  text-transform: uppercase; color: var(--text-3); }
.cd-num b { font-size: var(--fs-md); font-variant-numeric: tabular-nums; color: var(--text-2); }
.cd-num.is-sum b { color: var(--text); font-weight: var(--w-bold); }

.cd-totals {
  margin-top: var(--sp-md); padding-top: var(--sp-md);
  border-top: 1px solid var(--hairline);
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-sm) var(--sp-md);
}
.cd-total { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-sm); }
.cd-total em { font-style: normal; font-size: var(--fs-xs); letter-spacing: 0.5px;
  text-transform: uppercase; color: var(--text-3); }
.cd-total b { font-size: var(--fs-lg); font-variant-numeric: tabular-nums; color: var(--text); }
.cd-total.is-final { grid-column: 1 / -1; padding-top: var(--sp-sm); border-top: 1px solid var(--hairline); }
.cd-total.is-final b { font-size: 26px; color: var(--purple-ink); font-weight: var(--w-bold); }

/* ---- deductions ---- */
.cd-ded {
  display: flex; align-items: baseline; gap: var(--sp-sm);
  padding: var(--sp-sm) 0; border-bottom: 1px solid var(--hairline);
}
.cd-ded:last-child { border-bottom: 0; }
.cd-ded-label { flex: 1 1 auto; font-size: var(--fs-md); color: var(--text); }
.cd-ded-at { font-size: var(--fs-xs); color: var(--text-3); }
.cd-ded-val { font-size: var(--fs-md); font-weight: var(--w-bold); color: var(--bad, #B3261E);
  font-variant-numeric: tabular-nums; }

/* ---- judge notes, read only ---- */
.cd-note {
  display: flex; align-items: center; gap: var(--sp-md); width: 100%; cursor: pointer;
  text-align: left; padding: var(--sp-sm) 0; border: 0; border-bottom: 1px solid var(--hairline);
  background: none; font-family: var(--font);
}
.cd-note:last-of-type { border-bottom: 0; }
.cd-note-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.cd-note-text { font-size: var(--fs-md); color: var(--text); }
.cd-note-meta { font-size: var(--fs-xs); color: var(--text-3); }
.cd-note-dur { font-size: var(--fs-sm); color: var(--text-3); font-variant-numeric: tabular-nums; }

/* ---- inquiries raised ---- */
.cd-inquiry-line { margin: var(--sp-sm) 0 var(--sp-md); font-size: var(--fs-sm);
  color: var(--text-2); line-height: 1.55; }
.cd-raised { margin-bottom: var(--sp-md); }
.cd-raised-row {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--sp-sm) var(--sp-md); margin-bottom: var(--sp-sm);
  border: 1px solid var(--good-line); border-radius: var(--r-md); background: var(--good-bg);
}
.cd-raised-label { font-size: var(--fs-sm); font-weight: var(--w-bold); color: var(--good); }
.cd-raised-note { font-size: var(--fs-sm); color: var(--text-2); }
.cd-raised-at { font-size: var(--fs-xs); color: var(--text-3); text-transform: capitalize; }

/* ---- the way in, on the coach's own card ---- */
.ca-own {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-sm);
  width: 100%; cursor: pointer; text-align: left;
  margin-top: var(--sp-md); padding: var(--sp-sm) var(--sp-md);
  border: 1px solid var(--purple-line); border-radius: var(--r-md);
  background: var(--purple-soft); font-family: var(--font);
}
.ca-own-label { font-size: var(--fs-xs); font-weight: var(--w-bold);
  letter-spacing: 0.6px; text-transform: uppercase; color: var(--purple); }
.ca-own-go { display: inline-flex; align-items: center; gap: 2px;
  font-size: var(--fs-sm); font-weight: var(--w-bold); color: var(--purple-ink); }
.ca-own-go .row-chev { width: 15px; height: 15px; }

/* ---- inquiry sheet ---- */
.iq-types { display: flex; flex-direction: column; gap: var(--sp-sm); margin-bottom: var(--sp-md); }
.iq-type {
  display: flex; flex-direction: column; gap: 2px; width: 100%; cursor: pointer; text-align: left;
  padding: var(--sp-md); border: 1px solid var(--hairline); border-radius: var(--r-md);
  background: var(--surface); font-family: var(--font);
}
.iq-type.is-on { border-color: var(--purple); background: var(--purple-soft); }
.iq-type-label { font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--text); }
.iq-type.is-on .iq-type-label { color: var(--purple-ink); }
.iq-type-blurb { font-size: var(--fs-sm); color: var(--text-3); }


/* ============================================================
   THE AWARDS SPINE
   Score detail, session flags, the head judge's master sign-off and
   the announcer's script. Every one of these screens is the verify
   review's skeleton reproportioned: white strip, .pc-context band,
   one scrolling region, and a dock where there is a commitment.
   One hairline weight throughout. No :active rules, per the policy at
   the top of this file.
   ============================================================ */

/* ---- board card additions ---- */
/* Signature and script sit on their own line above the action row, so a
   record of work already done never competes with the next press. */
.pc-card-sub {
  margin: 8px 0 0; display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-sm); flex-wrap: wrap;
}
.pc-signed {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-sm); font-weight: var(--w-semibold); color: var(--purple-ink);
}
.pc-signed .pc-tag-check { width: 11px; height: 11px; flex: none; }
/* A text link, not a second button: the card already carries the action. */
.pc-link {
  display: inline-flex; align-items: center; gap: 2px; cursor: pointer;
  border: none; background: none; padding: 0; font-family: var(--font);
  font-size: var(--fs-sm); font-weight: var(--w-bold); color: var(--purple);
}
.pc-link .row-chev { width: 14px; height: 14px; }
/* Count of what is worth a second look. Quiet by design — the flag list
   itself lives on the review and the master scoresheet. */
.pc-flag {
  margin-left: 8px; padding: 2px 8px; border-radius: var(--r-full);
  border: 1px solid var(--warn-line); background: var(--warn-bg); color: var(--warn);
  font-size: var(--fs-xs); font-weight: var(--w-bold);
}

/* ---- ranked row as a way in ---- */
/* .pcr-row supplies the card; this only turns it into a real button so it
   is keyboard reachable, the same trick .pc-card-open uses. */
.pcr-row-open {
  width: 100%; cursor: pointer; text-align: left; font: inherit; color: inherit;
  font-family: var(--font);
}
.pcr-go { flex: none; display: inline-flex; color: var(--text-3); }
.pcr-go .row-chev { width: 18px; height: 18px; }

/* ---- session flags ---- */
.fl-card {
  flex: none; background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--e1);
  padding: var(--sp-md) var(--sp-lg); margin-bottom: var(--sp-sm);
}
.fl-head { display: flex; align-items: center; gap: var(--sp-sm); margin-bottom: var(--sp-sm); }
.fl-head .section-label { flex: 1 1 auto; }
.fl-count {
  flex: none; min-width: 24px; padding: 2px 7px; text-align: center;
  border-radius: var(--r-full); border: 1px solid var(--hairline);
  background: var(--bg); color: var(--text-3);
  font-size: var(--fs-sm); font-weight: var(--w-semibold); font-variant-numeric: tabular-nums;
}
.fl-count.is-on { background: var(--warn-bg); border-color: var(--warn-line); color: var(--warn); }
.fl-row {
  display: flex; align-items: flex-start; gap: var(--sp-sm);
  padding: var(--sp-sm) 0; border-top: 1px solid var(--hairline);
}
.fl-row:first-of-type { border-top: none; padding-top: 0; }
.fl-glyph { width: 16px; height: 16px; flex: none; margin-top: 2px; color: var(--warn); }
.fl-row[data-flag="inquiry"] .fl-glyph { color: var(--purple); }
.fl-row.is-clean .pc-tag-check { width: 14px; height: 14px; flex: none; margin-top: 3px; color: var(--good); }
.fl-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.fl-label { font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--text); }
.fl-row.is-clean .fl-label { color: var(--good-ink); }
.fl-line { font-size: var(--fs-sm); color: var(--text-2); line-height: 1.45; }

/* ---- score detail ---- */
.pd-card {
  flex: none; background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--e1);
  padding: var(--sp-md) var(--sp-lg); margin-bottom: var(--sp-sm);
}
.pd-caps { display: flex; flex-direction: column; }
.pd-cap {
  display: flex; align-items: center; gap: var(--sp-md);
  padding: var(--sp-sm) 0; border-top: 1px solid var(--hairline);
}
.pd-cap:first-child { border-top: none; }
.pd-cap-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.pd-cap-label { font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--text); }
/* WHICH SEAT gave the number. The whole point of the drill-in. */
.pd-cap-judge { font-size: var(--fs-sm); color: var(--text-3); }
.pd-cap-nums, .pm-nums { flex: none; display: flex; align-items: center; gap: var(--sp-lg); }
.pd-num { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
.pd-num em {
  font-style: normal; font-size: var(--fs-xs); font-weight: var(--w-bold);
  letter-spacing: 0.6px; text-transform: uppercase; color: var(--text-3);
}
.pd-num b {
  font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text);
  font-variant-numeric: tabular-nums;
}
.pd-num.is-sum b { color: var(--purple-ink); font-weight: var(--w-bold); }
.pd-chip {
  flex: none; display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 9px; border-radius: var(--r-full);
  border: 1px solid var(--hairline); background: var(--bg); color: var(--text-3);
  font-size: var(--fs-xs); font-weight: var(--w-bold);
  letter-spacing: 0.4px; text-transform: uppercase; white-space: nowrap;
}
.pd-chip[data-state="confirmed"] {
  border-color: var(--purple-line); background: var(--purple-soft); color: var(--purple-ink);
}
.pd-chip .chip-glyph { width: 10px; height: 10px; }

.pd-ded {
  display: flex; align-items: flex-start; gap: var(--sp-md);
  padding: var(--sp-sm) 0; border-top: 1px solid var(--hairline);
}
.pd-ded:first-of-type { border-top: none; }
.pd-ded-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.pd-ded-label { font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--text); }
/* Deduction official, or the voice note it was applied from. */
.pd-ded-src { font-size: var(--fs-sm); color: var(--text-3); }
.pd-ded-note { font-size: var(--fs-sm); color: var(--text-2); font-style: italic; }
.pd-ded-val {
  flex: none; font-size: var(--fs-lg); font-weight: var(--w-bold); color: var(--danger);
  font-variant-numeric: tabular-nums;
}
.pd-empty { margin: var(--sp-sm) 0 0; font-size: var(--fs-sm); color: var(--text-3); }
.pd-note { margin: var(--sp-sm) 0 0; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.5; }

.pd-math { display: flex; flex-direction: column; margin-top: var(--sp-sm); }
.pd-math-row {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-md);
  padding: 7px 0; border-top: 1px solid var(--hairline);
}
.pd-math-row:first-child { border-top: none; }
.pd-math-row em {
  font-style: normal; font-size: var(--fs-sm); font-weight: var(--w-semibold); color: var(--text-2);
}
.pd-math-row b { font-size: var(--fs-lg); font-weight: var(--w-semibold);
  color: var(--text); font-variant-numeric: tabular-nums; }
.pd-math-row.is-final em { color: var(--purple-ink); font-weight: var(--w-bold); }
.pd-math-row.is-final b { font-size: var(--fs-xxl); font-weight: var(--w-bold); color: var(--purple-ink); }
.pd-math-line {
  margin: var(--sp-sm) 0 0; font-size: var(--fs-sm); color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.pd-note-row {
  display: flex; flex-direction: column; gap: 1px;
  padding: var(--sp-sm) 0; border-top: 1px solid var(--hairline);
}
.pd-note-row:first-of-type { border-top: none; }
.pd-note-text { font-size: var(--fs-md); color: var(--text); }
.pd-note-meta { font-size: var(--fs-sm); color: var(--text-3); }

/* ---- master scoresheet ---- */
/* Signed / unsigned reuses .pcr-stage's chip and only changes the trio. */
.pcr-stage[data-signed="true"] {
  border-color: var(--purple-line); background: var(--purple-soft); color: var(--purple-ink);
}
.pm-panel {
  flex: none; background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--e1);
  padding: var(--sp-md) var(--sp-lg); margin-bottom: var(--sp-sm);
}
.pm-seats {
  margin-top: var(--sp-sm);
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--sp-sm);
}
.pm-seat {
  display: flex; flex-direction: column; gap: 1px;
  padding: var(--sp-sm) var(--sp-md); border: 1px solid var(--hairline);
  border-radius: var(--r-md); background: var(--surface-2);
}
.pm-seat-role {
  font-size: var(--fs-xs); font-weight: var(--w-bold);
  letter-spacing: 0.6px; text-transform: uppercase; color: var(--text-3);
}
.pm-seat-judge { font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--text); }
.pm-seat-cert { font-size: var(--fs-sm); color: var(--text-3); }
.pm-nums { margin-right: var(--sp-sm); }

/* ---- awards script ---- */
.aw-scroll { gap: var(--sp-md); }
.aw-lede {
  flex: none; background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--e1); padding: var(--sp-md) var(--sp-lg);
}
.aw-lede-line { margin: 0; font-size: var(--fs-md); color: var(--text-2); line-height: 1.55; max-width: 78ch; }
.aw-lede-meta { margin: 6px 0 0; font-size: var(--fs-sm); color: var(--text-3); }
.aw-div {
  flex: none; background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--e1); padding: var(--sp-md) var(--sp-lg);
}
.aw-div-head {
  display: flex; align-items: baseline; gap: var(--sp-md);
  padding-bottom: var(--sp-sm); border-bottom: 1px solid var(--hairline);
}
.aw-div-title { margin: 0; flex: 1 1 auto; font-size: var(--fs-xl);
  font-weight: var(--w-semibold); color: var(--text); }
.aw-div-count { flex: none; font-size: var(--fs-sm); color: var(--text-3); }
.aw-calls { list-style: none; margin: 0; padding: 0; }
/* Read order IS the list order: last placement first, up to the win. */
.aw-call {
  display: flex; align-items: baseline; gap: var(--sp-md);
  padding: var(--sp-sm) 0; border-top: 1px solid var(--hairline);
}
.aw-call:first-child { border-top: none; }
.aw-call-place {
  flex: none; width: 44px; font-size: var(--fs-md); font-weight: var(--w-bold);
  color: var(--text-3); font-variant-numeric: tabular-nums;
}
.aw-call.is-first .aw-call-place { color: var(--purple-ink); }
.aw-call-say { flex: 1 1 auto; font-size: var(--fs-lg); color: var(--text); line-height: 1.5; }
.aw-call.is-first .aw-call-say { font-weight: var(--w-semibold); color: var(--purple-ink); }
.aw-champ { border-color: var(--purple-line); background: var(--purple-soft); }
.aw-champ .aw-div-head { border-bottom-color: var(--purple-line); }
.aw-champ .aw-call { border-top-color: var(--purple-line); }

@media (max-height: 700px) {
  .pd-card, .pm-panel, .fl-card { padding: var(--sp-sm) var(--sp-md); }
  .aw-div, .aw-lede { padding: var(--sp-sm) var(--sp-md); }
}
@media (max-width: 720px) {
  .pd-cap, .pd-ded { flex-wrap: wrap; }
  .pd-cap-nums, .pm-nums { gap: var(--sp-md); }
  .pcr-row-open { gap: var(--sp-md); }
}

/* ============================================================
   PRINT — the announcer's page, on paper
   The awards script is the one screen in this prototype that leaves the
   building on paper, so printing drops the app entirely and lays the
   script out as a document: no chrome, no shadows, no scroll region.
   Everything else is display:none already unless it is the open screen,
   so this only has to strip THIS screen back.
   ============================================================ */
@media print {
  html, body { background: #fff; height: auto; overflow: visible; }
  .drawer, .drawer-scrim, .sheet, .sheet-scrim, .popover, .pop-scrim, .toast { display: none !important; }

  body[data-screen="awards"] #screen-awards {
    display: block; height: auto; overflow: visible;
  }
  /* The strip and the print control are the app, not the script. */
  #screen-awards .pcr-top { display: none; }
  #screen-awards .pc-context {
    display: block; border: none; padding: 0 0 8pt;
    border-bottom: 1px solid #000;
  }
  #screen-awards .pc-context-block { border: none; padding: 0; display: inline-block; margin-right: 24pt; }
  #screen-awards .pcr-main { display: block; padding: 0; background: #fff; }
  #screen-awards .pcr-scroll { display: block; overflow: visible; padding: 0; }
  #screen-awards .aw-lede, #screen-awards .aw-div {
    box-shadow: none; border: none; border-bottom: 1px solid #000;
    border-radius: 0; padding: 8pt 0; background: #fff;
    break-inside: avoid; page-break-inside: avoid;
  }
  #screen-awards .aw-champ { background: #fff; }
  #screen-awards .aw-call-say { font-size: 12pt; }
  #screen-awards .aw-div-title { font-size: 14pt; }
  @page { margin: 14mm; }
}


/* ---- the review screen's two reads ----
   Ranked is the default. Running order is the same session in mat order.
   The switch is the app's existing segmented control, sized down for a
   header row rather than a full-width band. */
/* .pcr-head aligns on the baseline for its two text runs; a control has
   no useful baseline, so this one centres itself instead. */
.pcr-seg {
  flex: none; align-self: center; margin: 0 0 0 auto; width: auto; min-width: 260px;
}
.pcr-seg .pager-btn { flex: 1 1 auto; min-height: 32px; padding-inline: var(--sp-md); }

/* Running-order row. Same card as .pcr-row, with the clock where the
   placement sits: this list is ordered by the mat, not by score. */
.ro-time {
  flex: none; width: 74px; font-size: var(--fs-md); font-weight: var(--w-semibold);
  color: var(--text-2); font-variant-numeric: tabular-nums;
}
.ro-chip {
  flex: none; padding: 4px 11px; border-radius: var(--r-full);
  border: 1px solid var(--hairline); background: var(--bg); color: var(--text-3);
  font-size: var(--fs-xs); font-weight: var(--w-bold);
  letter-spacing: 0.6px; text-transform: uppercase; white-space: nowrap;
}
/* Same three token trios the arena chips already use, so "on the mat"
   means the same thing to a producer as it does on a family phone. */
.ro-chip[data-state="scored"] {
  border-color: var(--purple-line); background: var(--purple-soft); color: var(--purple-ink);
}
.ro-chip[data-state="performing"] {
  border-color: var(--purple); background: var(--purple-soft); color: var(--purple-ink);
}
.ro-chip[data-state="ondeck"] {
  border-color: var(--warn-line); background: var(--warn-bg); color: var(--warn);
}
/* A routine with no score yet gets a dash, not a zero. */
.pcr-score.is-waiting { color: var(--text-3); font-weight: var(--w-semibold); }

@media (max-width: 720px) {
  .pcr-seg { min-width: 0; width: 100%; margin-left: 0; }
  .ro-time { width: 66px; font-size: var(--fs-sm); }
}


/* ============================================================
   LIVE FLOOR — one column per hall
   ============================================================
   A producer runs the building, not a mat, so the horizontal axis is
   spent on ROOMS rather than on one room's three positions. Each hall
   is a narrow column: its name, an on-time chip, where it has got to,
   the three positions stacked, and its own control at the foot.

   Every hall stays on screen. The room worth looking at is the one
   drifting behind, and tabs would be hiding exactly that one, so more
   halls than fit scroll sideways instead.
   ============================================================ */
.pc-floor { flex: none; margin-left: var(--sp-md); }
/* When the arena chip is hidden the button still sits at the right end
   of the head rather than next to the note. */
.pc-live[hidden] + .pc-floor { margin-left: auto; }

.lf-rooms {
  flex: 1 1 auto; min-height: 0;
  display: flex; align-items: stretch; gap: var(--sp-md);
  overflow-x: auto; overflow-y: hidden;
  padding-bottom: var(--sp-sm);
}
.lf-room {
  flex: 0 0 296px; min-width: 0; min-height: 0;
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--e1);
  overflow: hidden;
}
/* The hall with something on the mat is the one being run. It takes the
   brand hairline; the others stay quiet rather than going grey. */
.lf-room[data-state="running"] { border-color: var(--purple-line); }

.lf-room-head {
  flex: none; padding: var(--sp-sm) var(--sp-md);
  border-bottom: 1px solid var(--hairline);
}
.lf-room-top { display: flex; align-items: baseline; gap: var(--sp-sm); }
.lf-room-name {
  margin: 0; flex: 1 1 auto; min-width: 0;
  font-size: var(--fs-xl); font-weight: var(--w-bold); color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* Where this hall has got to, in the smallest honest form. */
.lf-count {
  flex: none; padding: 2px 9px; border-radius: var(--r-full);
  border: 1px solid var(--hairline); background: var(--bg); color: var(--text-2);
  font-size: var(--fs-sm); font-weight: var(--w-semibold);
  font-variant-numeric: tabular-nums;
}
.lf-room[data-state="running"] .lf-count {
  border-color: var(--purple-line); background: var(--purple-soft); color: var(--purple-ink);
}
.lf-room-meta {
  margin: 3px 0 0; font-size: var(--fs-sm); color: var(--text-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lf-chips { display: flex; align-items: center; gap: 6px; margin-top: var(--sp-sm); }
.lf-chip {
  padding: 3px 9px; border-radius: var(--r-full);
  border: 1px solid var(--hairline); background: var(--bg); color: var(--text-3);
  font-size: var(--fs-xs); font-weight: var(--w-bold);
  letter-spacing: 0.5px; text-transform: uppercase; white-space: nowrap;
}
.lf-chip.is-ontime {
  border-color: var(--good-line); background: var(--good-bg); color: var(--good-ink);
}
.lf-chip[data-state="running"] {
  border-color: var(--purple-line); background: var(--purple-soft); color: var(--purple-ink);
}
.lf-chip[data-state="complete"] {
  border-color: var(--good-line); background: var(--good-bg); color: var(--good-ink);
}

/* ---- the three positions, stacked ---- */
/* All three positions have to be visible at once: the whole reason a
   column is narrow is so the stack fits without scrolling. The sizes
   below are set so three fit inside the shell's box on a 800px frame,
   which is the shortest place this renders. */
.lf-stack {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 6px;
  padding: var(--sp-sm); background: var(--bg);
}
.lf-slot {
  flex: none; padding: 6px var(--sp-md);
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-md);
}
/* The clock belongs to the routine on the floor. On deck and in the hole
   are positions, and their times are two rows down the running order. */
.lf-slot:not(.is-mat) .lf-slot-time { display: none; }
/* Only the mat carries the brand: on deck and in the hole are where a
   routine is standing, not where the room is looking. */
.lf-slot.is-mat { border-color: var(--purple-line); background: var(--purple-soft); }
.lf-slot.is-empty { background: var(--surface-2); }
.lf-slot-label { margin: 0; }
.lf-slot-team {
  margin: 4px 0 0; font-size: var(--fs-lg); font-weight: var(--w-semibold);
  color: var(--text); line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lf-slot.is-mat .lf-slot-label, .lf-slot.is-mat .lf-slot-team { color: var(--purple-ink); }
.lf-slot.is-mat .lf-slot-team { font-size: var(--fs-xl); font-weight: var(--w-bold); }
.lf-slot-meta {
  margin: 2px 0 0; font-size: var(--fs-sm); color: var(--text-2); line-height: 1.4;
}
.lf-slot-time {
  margin: 2px 0 0; font-size: var(--fs-sm); color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.lf-slot-none { margin: 4px 0 0; font-size: var(--fs-md); color: var(--text-3); }

/* ---- who is running the hall ----
   Where the Advance control used to be. The producer is not standing at
   this mat and cannot call it, so the foot answers the two questions they
   actually have from the back of the building: who is on it, and does it
   want looking at. */
.lf-room-foot {
  flex: none; padding: var(--sp-sm) var(--sp-md);
  border-top: 1px solid var(--hairline); background: var(--surface);
  cursor: pointer;
}
.lf-foot-label { margin: 0; }
.lf-foot-row {
  display: flex; align-items: baseline; gap: var(--sp-sm); margin-top: 3px;
}
.lf-coord {
  flex: 1 1 auto; min-width: 0;
  font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lf-foot-state {
  flex: none; font-size: var(--fs-sm); color: var(--text-3);
}
/* The one column worth walking over to. Amber, never red: red in this
   prototype means LIVE and nothing else. */
/* inline-block so it hugs its own text: stretched across the foot it read
   as a status bar rather than as one of the app's chips. */
.lf-attn {
  display: inline-block; max-width: 100%; margin-top: 6px; padding: 3px 9px;
  border: 1px solid var(--warn-line); border-radius: var(--r-full);
  background: var(--warn-bg); color: var(--warn);
  font-size: var(--fs-xs); font-weight: var(--w-bold);
  letter-spacing: 0.5px; text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.lf-done {
  margin: 0; min-height: 42px; display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-md); color: var(--text-3);
}


/* ============================================================
   COORDINATOR — ONE HALL, FULL WIDTH
   ============================================================
   The producer's floor spends its horizontal axis on ROOMS because a
   producer is comparing halls. A coordinator is standing in one, so this
   screen spends the whole width on the one hall's three positions.

   Same grammar as the column, one size up: this is read at arm's length
   off a tablet propped at the side of a mat, not leaned into on a laptop.
   ============================================================ */
.co-top {
  flex: none; display: flex; align-items: flex-start; gap: var(--sp-lg);
  padding: var(--sp-md) var(--sp-lg);
  background: var(--surface); border-bottom: 1px solid var(--hairline);
}
.co-top-hall { flex: 1 1 auto; min-width: 0; }
.co-top-who  { flex: none; text-align: right; }
.co-hall {
  margin: 3px 0 0; font-size: var(--fs-xxl); font-weight: var(--w-bold); color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.co-meta {
  margin: 3px 0 0; font-size: var(--fs-md); color: var(--text-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.co-who {
  margin: 3px 0 0; font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text);
}
.co-chips { display: flex; align-items: center; justify-content: flex-end; gap: 6px; margin-top: var(--sp-sm); }
.co-count {
  padding: 2px 9px; border-radius: var(--r-full);
  border: 1px solid var(--hairline); background: var(--bg); color: var(--text-2);
  font-size: var(--fs-sm); font-weight: var(--w-semibold);
  font-variant-numeric: tabular-nums;
}
.co-state {
  padding: 3px 9px; border-radius: var(--r-full);
  border: 1px solid var(--hairline); background: var(--bg); color: var(--text-3);
  font-size: var(--fs-xs); font-weight: var(--w-bold);
  letter-spacing: 0.5px; text-transform: uppercase; white-space: nowrap;
}
.co-state[data-state="running"] {
  border-color: var(--purple-line); background: var(--purple-soft); color: var(--purple-ink);
}
.co-state[data-state="complete"] {
  border-color: var(--good-line); background: var(--good-bg); color: var(--good-ink);
}

.co-main {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: var(--sp-md);
  padding: var(--sp-md) var(--sp-lg);
}

/* ---- the three positions, across the full width ---- */
.co-stack {
  flex: none; display: flex; align-items: stretch; gap: var(--sp-md);
}
.co-slot {
  flex: 1 1 0; min-width: 0;
  padding: var(--sp-md) var(--sp-lg);
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--e1);
}
.co-slot.is-wide { flex: 1 1 100%; }
/* The clock belongs to the routine on the floor, exactly as in the
   producer's column. */
.co-slot:not(.is-mat) .co-slot-time { display: none; }
/* Only the mat carries the brand. */
.co-slot.is-mat { border-color: var(--purple-line); background: var(--purple-soft); }
.co-slot.is-empty { background: var(--surface-2); box-shadow: none; }
.co-slot-label { margin: 0; }
.co-slot-team {
  margin: 6px 0 0; font-size: var(--fs-xxl); font-weight: var(--w-semibold);
  color: var(--text); line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.co-slot.is-mat .co-slot-label, .co-slot.is-mat .co-slot-team { color: var(--purple-ink); }
/* NOW is the one a person at the mat is reading from three steps away. */
.co-slot.is-mat .co-slot-team { font-size: var(--fs-title); font-weight: var(--w-bold); }
.co-slot-meta {
  margin: 4px 0 0; font-size: var(--fs-md); color: var(--text-2); line-height: 1.4;
}
.co-slot-time {
  margin: 4px 0 0; font-size: var(--fs-md); color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.co-slot-none { margin: 6px 0 0; font-size: var(--fs-lg); color: var(--text-3); }

/* ---- the running order, compact ---- */
.co-order-wrap {
  flex: none; padding: var(--sp-md);
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-lg); box-shadow: var(--e1);
}
.co-order-label { margin: 0 0 var(--sp-sm); }
.co-order { margin: 0; padding: 0; list-style: none; }
.co-row {
  display: flex; align-items: baseline; gap: var(--sp-md);
  padding: 7px 0; border-top: 1px solid var(--hairline);
}
.co-row:first-child { border-top: none; }
.co-row-time {
  flex: none; width: 74px; font-size: var(--fs-sm); color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
.co-row-team {
  flex: 1 1 auto; min-width: 0; font-size: var(--fs-md); color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.co-row-state {
  flex: none; font-size: var(--fs-sm); color: var(--text-3);
}
.co-row[data-state="performing"] .co-row-team { font-weight: var(--w-bold); color: var(--purple-ink); }
.co-row[data-state="performing"] .co-row-state { color: var(--purple-ink); font-weight: var(--w-semibold); }
.co-row[data-state="done"] .co-row-team { color: var(--text-3); }

/* ---- the controls ---- */
.co-foot {
  flex: none; padding: var(--sp-md) var(--sp-lg);
  border-top: 1px solid var(--hairline); background: var(--surface);
}
/* The correction row, above the primary control and never beside it.
   Secondary weight: the app's standard hairline on a white card, so it
   reads as available rather than as a second Advance. */
.co-foot-row {
  display: flex; align-items: center; gap: var(--sp-md);
  margin-bottom: var(--sp-md);
}
.co-back {
  flex: none; cursor: pointer; min-height: 44px; padding: 0 var(--sp-lg);
  border: 1px solid var(--hairline); border-radius: var(--r-md);
  background: var(--surface); color: var(--text); font-family: var(--font);
  font-size: var(--fs-lg); font-weight: var(--w-semibold);
}
/* Quiet, not hidden: a control that vanishes teaches nothing about when
   it is coming back. Persistent state, so no tap feedback is involved. */
.co-back:disabled { color: var(--text-3); cursor: default; }
.co-go {
  display: block; width: 100%; cursor: pointer; min-height: 64px;
  border: none; border-radius: var(--r-lg);
  background: var(--purple); color: var(--white); font-family: var(--font);
  font-size: var(--fs-xxl); font-weight: var(--w-semibold); box-shadow: var(--e1);
}
.co-go:disabled {
  background: var(--surface-2); color: var(--text-3); box-shadow: none; cursor: default;
}

/* In the hole joins the arena chips wherever they are read. Same trio
   grammar as on deck, one step quieter, because it is one step further
   away. */
.ro-chip[data-state="inhole"] {
  border-color: var(--hairline-2); background: var(--surface-2); color: var(--text-2);
}
.ro-chip[data-state="done"] { color: var(--text-muted); }
/* Where the floor has got to, in the strip. Same chip as the pipeline
   stage next to it, lit only while something is actually on the mat. */
.pcr-stage[data-live="true"] {
  border-color: var(--purple); background: var(--purple-soft); color: var(--purple-ink);
}

/* Short viewports, which is what the console shell leaves on an 800px
   laptop frame. A column gives up detail on the two staged positions
   before it gives up a position: all three are the point. */
@media (max-height: 840px) {
  .lf-slot:not(.is-mat) .lf-slot-meta { display: none; }
  .lf-slot { padding: 5px var(--sp-sm); }
  .lf-room-meta { display: none; }
  .lf-slot.is-mat .lf-slot-team { font-size: var(--fs-lg); }
  .lf-go { min-height: 36px; font-size: var(--fs-md); }
  .lf-stack { padding: 6px; gap: 5px; }
  /* Inside the console shell this band repeats what the shell already
     says two rows up, and the height it costs is a whole position. */
  body[data-desk="on"] #screen-live .pc-context { display: none; }
}
@media (max-width: 900px) {
  .lf-room { flex-basis: 260px; }
}

/* ============================================================
   DESKTOP CONSOLE SHELL
   ============================================================
   CHROME ONLY. The furniture the admin app puts around this console on
   a laptop. Every region is fixed-positioned off the five measurements
   below, and the producer screens are laid into the box left over. No
   screen is rebuilt and no release state is involved: the pipeline, the
   live floor, the master and the awards script render inside this
   exactly as they render without it.

   Red appears twice and only twice, on the LIVE pill and on End Live
   Mode, which is where the real app puts it. Everything else is on the
   same tokens as the rest of the prototype: one hairline weight, white
   cards, soft shadows, uppercase section labels, no :active anywhere.
   ============================================================ */
:root {
  --ds-nav: 50px;     /* top nav */
  --ds-rail: 56px;    /* icon rail */
  --ds-head: 60px;    /* event header strip */
  --ds-panel: 236px;  /* event lifecycle panel */
  --ds-live: 168px;   /* Live Mode header, stats and actions */
}

/* Below this the shell is off entirely and the phone app is byte for
   byte what it was. */
@media (min-width: 1000px) {

  body[data-desk="on"] .ds { display: block; }

  /* THE BOX. Every console screen is laid into what the chrome leaves. */
  body[data-desk="on"] #screen-producer,
  body[data-desk="on"] #screen-review,
  body[data-desk="on"] #screen-live,
  body[data-desk="on"] #screen-pdetail,
  body[data-desk="on"] #screen-master,
  body[data-desk="on"] #screen-awards {
    position: fixed;
    top: calc(var(--ds-nav) + var(--ds-head) + var(--ds-live));
    left: calc(var(--ds-rail) + var(--ds-panel));
    right: 0; bottom: 0; height: auto;
    border-top: 1px solid var(--hairline);
  }

  /* The board's own strip and event band are what the shell above them
     now says, so they step aside rather than repeat it. */
  body[data-desk="on"] .pc-top,
  body[data-desk="on"] #screen-producer .pc-context { display: none; }
  body[data-desk="on"] .pc-main { padding-top: var(--sp-md); }
}

.ds { display: none; }
.ds[hidden] { display: none !important; }

/* ---- top nav ---- */
.ds-nav {
  position: fixed; top: 0; left: 0; right: 0; height: var(--ds-nav); z-index: 2;
  display: flex; align-items: center; gap: var(--sp-md);
  padding: 0 var(--sp-lg);
  background: var(--surface); border-bottom: 1px solid var(--hairline);
}
.ds-logo { height: 22px; width: auto; display: block; }
.ds-nav-title {
  font-size: var(--fs-lg); font-weight: var(--w-semibold); color: var(--text);
}
.ds-nav-spacer { flex: 1 1 auto; }

.ds-icon {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; cursor: pointer; padding: 0;
  border: 1px solid transparent; border-radius: var(--r-md);
  background: none; color: var(--text-2);
}
.ds-icon svg { width: 18px; height: 18px; display: block; }
.ds-bell { position: relative; }
.ds-badge {
  position: absolute; top: 1px; right: 0;
  min-width: 15px; height: 15px; padding: 0 4px; border-radius: var(--r-full);
  background: var(--purple); color: var(--white);
  font-size: 9px; font-weight: var(--w-bold); line-height: 15px; text-align: center;
}
.ds-link {
  flex: none; cursor: pointer; padding: 6px var(--sp-sm);
  border: none; background: none; font-family: var(--font);
  font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--text-2);
}
.ds-user {
  flex: none; display: inline-flex; align-items: center; gap: var(--sp-sm);
  cursor: pointer; padding: 4px var(--sp-sm) 4px 4px;
  border: 1px solid var(--hairline); border-radius: var(--r-full);
  background: var(--surface); font-family: var(--font);
}
.ds-avatar {
  flex: none; width: 26px; height: 26px; border-radius: var(--r-full);
  background: var(--purple-soft); color: var(--purple-ink);
  font-size: var(--fs-xs); font-weight: var(--w-bold);
  display: inline-flex; align-items: center; justify-content: center;
}
.ds-user-name { font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--text); }
.ds-user-chev { width: 14px; height: 14px; color: var(--text-3); }

/* ---- icon rail ---- */
.ds-rail {
  position: fixed; top: var(--ds-nav); left: 0; bottom: 0; width: var(--ds-rail); z-index: 2;
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-md);
  padding: var(--sp-md) 0;
  background: var(--surface); border-right: 1px solid var(--hairline);
}
.ds-org {
  flex: none; width: 34px; height: 34px; border-radius: var(--r-md);
  background: var(--purple); color: var(--white);
  font-size: var(--fs-sm); font-weight: var(--w-bold); letter-spacing: 0.4px;
  display: inline-flex; align-items: center; justify-content: center;
}
.ds-rail-btn { color: var(--text-3); }

/* ---- event header strip ---- */
.ds-head {
  position: fixed; top: var(--ds-nav); left: var(--ds-rail); right: 0;
  height: var(--ds-head); z-index: 2;
  display: flex; align-items: center; gap: var(--sp-md);
  padding: 0 var(--sp-lg);
  background: var(--surface); border-bottom: 1px solid var(--hairline);
}
.ds-back { color: var(--text-2); }
.ds-back .chev-left { width: 18px; height: 18px; }
.ds-head-text { flex: 0 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.ds-head-line { display: flex; align-items: center; gap: var(--sp-sm); min-width: 0; }
.ds-head-title {
  font-size: var(--fs-xl); font-weight: var(--w-bold); color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ds-head-sub { font-size: var(--fs-sm); color: var(--text-3); }

/* One pill, three trios. Good is the published state, live is the only
   red on the shell besides End Live Mode. */
.ds-pill {
  flex: none; padding: 3px 10px; border-radius: var(--r-full);
  border: 1px solid var(--hairline); background: var(--bg); color: var(--text-3);
  font-size: var(--fs-xs); font-weight: var(--w-bold);
  letter-spacing: 0.8px; text-transform: uppercase; white-space: nowrap;
}
.ds-pill.is-good {
  border-color: var(--good-line); background: var(--good-bg); color: var(--good-ink);
}
.ds-pill.is-live {
  border-color: var(--danger-line); background: var(--danger-bg); color: var(--danger);
}

.ds-stages {
  flex: 1 1 auto; display: inline-flex; align-items: center; justify-content: center;
  gap: 6px; font-size: var(--fs-md); font-weight: var(--w-semibold); color: var(--text-2);
  white-space: nowrap;
}
.ds-stage-check { width: 14px; height: 14px; flex: none; color: var(--good); }
.ds-exit {
  flex: none; cursor: pointer; padding: 7px var(--sp-lg); border-radius: var(--r-full);
  border: 1px solid var(--purple-line); background: var(--surface);
  color: var(--purple); font-family: var(--font);
  font-size: var(--fs-sm); font-weight: var(--w-semibold); white-space: nowrap;
}

/* ---- event lifecycle panel ---- */
.ds-panel {
  position: fixed; top: calc(var(--ds-nav) + var(--ds-head)); left: var(--ds-rail);
  bottom: 0; width: var(--ds-panel); z-index: 2;
  display: flex; flex-direction: column;
  padding: var(--sp-md);
  background: var(--bg); border-right: 1px solid var(--hairline);
}
.ds-panel-head {
  flex: none; display: flex; align-items: center; gap: var(--sp-sm);
  padding: var(--sp-sm) var(--sp-md);
  background: var(--surface);
  border: 1px solid var(--hairline); border-bottom: 0;
  border-radius: var(--r-lg) var(--r-lg) 0 0;
}
.ds-panel-head .section-label { flex: 1 1 auto; }
.ds-panel-head .chev-down { width: 15px; height: 15px; color: var(--text-3); }
.ds-panel-body {
  flex: 1 1 auto; min-height: 0; overflow-y: auto;
  padding: 6px; background: var(--surface);
  border: 1px solid var(--hairline); border-radius: 0 0 var(--r-lg) var(--r-lg);
  box-shadow: var(--e1);
}
.ds-row {
  display: flex; align-items: center; gap: var(--sp-sm);
  width: 100%; cursor: pointer; text-align: left;
  padding: 9px var(--sp-md); border: 1px solid transparent; border-radius: var(--r-md);
  background: none; font-family: var(--font);
}
.ds-row-label {
  flex: 1 1 auto; min-width: 0;
  font-size: var(--fs-md); font-weight: var(--w-medium); color: var(--text-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ds-row-chev { width: 14px; height: 14px; flex: none; color: var(--purple); transform: rotate(90deg); }
/* The active stage. Lavender the app already means "this one" by. */
.ds-row.is-on { background: var(--purple-soft); border-color: var(--purple-line); }
.ds-row.is-on .ds-row-label { color: var(--purple-ink); font-weight: var(--w-bold); }

.ds-subs { display: flex; flex-direction: column; padding: 2px 0 2px var(--sp-lg); }
.ds-sub {
  cursor: pointer; text-align: left;
  padding: 7px var(--sp-md); margin-top: 2px;
  border: 1px solid transparent; border-radius: var(--r-md);
  background: none; font-family: var(--font);
  font-size: var(--fs-sm); font-weight: var(--w-medium); color: var(--text-3);
}
.ds-sub.is-on { background: var(--purple); color: var(--white); font-weight: var(--w-semibold); }

/* ---- Live Mode header, stats, actions ---- */
.ds-live {
  position: fixed; top: calc(var(--ds-nav) + var(--ds-head));
  left: calc(var(--ds-rail) + var(--ds-panel)); right: 0;
  height: var(--ds-live); z-index: 2;
  display: flex; flex-direction: column; gap: var(--sp-sm);
  padding: var(--sp-md) var(--sp-xl);
  background: var(--surface);
}
.ds-live-top { flex: none; display: flex; align-items: center; gap: var(--sp-md); }
.ds-live-name {
  font-size: var(--fs-xxl); font-weight: var(--w-bold); color: var(--text);
  letter-spacing: -0.3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ds-clock {
  font-size: var(--fs-md); color: var(--text-3); font-variant-numeric: tabular-nums;
}
.ds-refresh { width: 26px; height: 26px; color: var(--text-3); }
.ds-refresh svg { width: 15px; height: 15px; }
/* THE OTHER RED. Solid, because ending the mode is the loudest thing on
   this screen and the real app draws it that way. */
.ds-end {
  flex: none; cursor: pointer; min-height: 36px; padding: 0 var(--sp-lg);
  border: 1px solid var(--danger-fill); border-radius: var(--r-md);
  background: var(--danger-fill); color: var(--white); font-family: var(--font);
  font-size: var(--fs-md); font-weight: var(--w-semibold); white-space: nowrap;
}

.ds-stats {
  flex: none; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--sp-sm);
}
.ds-stat {
  padding: 7px var(--sp-md);
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r-md); box-shadow: var(--e1);
  min-width: 0;
}
.ds-stat-label { margin: 0; }
.ds-stat-value {
  margin: 2px 0 0; font-size: var(--fs-xl); font-weight: var(--w-bold);
  color: var(--text); font-variant-numeric: tabular-nums; line-height: 1.2;
}
.ds-stat-note {
  margin: 0; font-size: var(--fs-sm); color: var(--text-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.ds-actions { flex: none; display: flex; align-items: center; gap: var(--sp-sm); }
.ds-act {
  flex: none; cursor: pointer; padding: 7px var(--sp-md); border-radius: var(--r-md);
  border: 1px solid var(--hairline); background: var(--surface);
  color: var(--text-2); font-family: var(--font);
  font-size: var(--fs-sm); font-weight: var(--w-semibold); white-space: nowrap;
}

/* Narrow desktops: the panel and the rail give up width before the
   console does, and the stats drop to two across. */
@media (min-width: 1000px) and (max-width: 1240px) {
  :root { --ds-panel: 196px; --ds-live: 196px; }
  .ds-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ds-live { padding-inline: var(--sp-lg); }
}
@media (min-width: 1000px) and (max-height: 720px) {
  :root { --ds-live: 152px; }
  .ds-live { gap: 6px; padding-block: var(--sp-sm); }
  .ds-live-name { font-size: var(--fs-xl); }
}

/* The awards script prints as a document, so the shell comes off with
   the rest of the app and the screen goes back in the page flow. */
@media print {
  .ds { display: none !important; }
  body[data-desk="on"] #screen-awards {
    position: static; border-top: 0;
  }
}
