/*
 * THE THEME PASS — J23, the first-delivery gate's last job.
 *
 * Implements Governance\Front Yard Theme.md (Approved by Tim, 1 August 2026):
 * the BAA111 dark cut, absorbed from the Studio's BAA111 Livery. THAT SHEET IS
 * THE SOURCE OF TRUTH — a gap found here goes back to it, never into a page.
 *
 * One theme, dark, by ruling: navy ground, one amber accent, system fonts,
 * status never colour alone, touch first. The Livery's four rules of use bind
 * every rule below:
 *   1. the status WORD renders in ink, never the status colour — colour goes
 *      to the dot or the soft fill;
 *   2. the warn amber IS the accent, shared deliberately;
 *   3. links are amber and always underlined on cards;
 *   4. --ink-soft sits on --surface and --card only, never on --card-2.
 */

:root {
  color-scheme: dark;

  /* Colour — the fifteen tokens, verbatim from the Theme sheet. */
  --surface: #00467F;
  --card: #14588F;
  --card-2: #2A68A0;
  --ink: #F2F4F8;
  --ink-soft: #B8C5D6;
  --line: #3F7AB0;
  --accent: #FFB84D;
  --accent-ink: #1A1A1A;
  --accent-hover: #FFC76B;
  --accent-soft: rgba(255, 184, 77, 0.18);
  --ok: #4FCBA4;
  --ok-soft: rgba(79, 203, 164, 0.18);
  --warn: #FFB84D;
  --bad: #F08585;
  --bad-soft: rgba(240, 133, 133, 0.18);

  /* Type — four sizes and no more; a fifth is a design question. */
  --font: system-ui, sans-serif;
  --text-title: 1.375rem;
  --text-body: 1rem;
  --text-label: 0.875rem;
  --text-big: 2rem;

  /* Space and shape. */
  --radius: 8px;
  --touch: 44px;
  --measure: 40rem;
}

* {
  box-sizing: border-box;
}

/*
 * THE SINGLE SOURCE OF TRUTH FOR VISIBILITY, and it has to be here rather than
 * only in the scripts.
 *
 * The browser's own `[hidden] { display: none }` comes from the user-agent
 * stylesheet, so ANY author rule that sets `display` silently beats it. Every
 * panel on this platform carries `class="stack"`, which sets `display: flex` —
 * so `hidden` had no effect on a single one of them, while the scripts went on
 * setting it and believing it worked. Visibility lived in two places that could
 * disagree, and they did.
 *
 * Two consecutive failures were the same defect seen through two cache states:
 * with an older stylesheet that had no `.stack` rule, the UA rule applied and
 * every panel stayed hidden — a heading and nothing under it. With the current
 * stylesheet, none of them hide — the form and the joined panel at once, asking
 * a student to join and telling them they are already in, as nobody.
 *
 * `!important` is deliberate and is the point: nothing in this file, now or
 * later, may overrule the attribute. The scripts own visibility; the stylesheet
 * defers to them, unconditionally.
 */
[hidden] {
  display: none !important;
}

body {
  margin: 0;
  padding: 1.5rem 1.25rem 3rem;
  background: var(--surface);
  color: var(--ink);
  font: var(--text-body) / 1.5 var(--font);
}

main {
  max-width: var(--measure);
  margin: 0 auto;
}

h1 {
  margin: 0 0 0.25rem;
  font-size: var(--text-title);
  font-weight: 600;
  letter-spacing: -0.01em;
}

.tagline {
  margin: 0 0 2rem;
  color: var(--ink-soft);
}

h2 {
  margin: 0 0 0.75rem;
  font-size: var(--text-label);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ink-soft);
}

/* Rule 3: links amber, always underlined on cards — and everywhere, for one
   look; buttons are buttons and are exempt by not being anchors. */
a {
  color: var(--accent);
  text-decoration: underline;
}

/* ---- the hub ---------------------------------------------------------------
 * J24: the hub is two buttons and nothing else — the activities list and its
 * styles went with the ruling. The facilitator chooses the activity after the
 * room, so the front door has nothing to list.
 */

.note {
  font-size: var(--text-label);
  color: var(--ink-soft);
}

footer {
  margin-top: 2.5rem;
}

/* ---- the status line -------------------------------------------------------
 * Livery rule 1: THE WORD IS INK, the colour is the dot's. The old sheet
 * coloured the text red on disconnected/lost; those rules are gone on purpose
 * and must not return.
 */

.live-status {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  min-height: 28px;
  font-size: var(--text-label);
  font-weight: 500;
  color: var(--ink);
}

.dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--line);
  flex: none;
}

.live-status[data-state="connected"] .dot {
  background: var(--ok);
}

.live-status[data-state="reconnecting"] .dot {
  background: var(--warn);
}

.live-status[data-state="checking"] .dot {
  background: var(--line);
}

.live-status[data-state="disconnected"] .dot,
.live-status[data-state="lost"] .dot {
  background: var(--bad);
}

/* ---- entry, cards, forms ---------------------------------------------------- */

.entry {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 1rem;
  margin: 0 0 2rem;
}

.primary-link {
  display: inline-block;
  min-height: var(--touch);
  padding: 0.7rem 1.25rem;
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
  text-decoration: none;
}

.primary-link:hover {
  background: var(--accent-hover);
}

.quiet-link {
  color: var(--accent);
  font-size: var(--text-label);
  text-decoration: underline;
}

/* An outline button on an anchor — the hub's second door (J24). */
.outline-link {
  display: inline-block;
  min-height: var(--touch);
  padding: 0.7rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  color: var(--ink);
  font-weight: 600;
  text-decoration: none;
}

.outline-link:hover {
  border-color: var(--accent);
}

/* ---- the page header and Home (J24) ----------------------------------------
 * The footer "The Front Yard" links died; Home sits top-right in the header
 * instead (the console's Home sits beside Change room, not here). Since
 * J24 fix 1 item 4, Home wears the quiet button treatment everywhere — the
 * old .home-link text style is gone with the ruling.
 */

/*
  J28 item 5.4: the coordinator's snip showed the Home button sitting hard
  against the card below it. `h1` carries a 0.25rem bottom margin, which is the
  right gap under a heading and not enough under a header that also holds a
  button — the button is taller than the heading's margin, so it touched.

  On the header rather than on the panels, so the gap is the same on the two
  pages that use it (join and cards) and nothing has to remember it.
*/
.page-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
}

/* ---- number inputs without the native spinner (J24) -------------------------
 * The widget renders as a dark block on navy; typed entry is the interaction.
 */

input[type="number"] {
  appearance: textfield;
  -moz-appearance: textfield;
}

input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* The card: panels sit on --card with a --line border. Layout stays .stack's. */
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1rem;
}

.stack {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin: 0 0 1.5rem;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}

.field-label {
  font-size: var(--text-label);
  font-weight: 500;
  color: var(--ink-soft);
}

input[type="text"],
input[type="password"],
input[type="number"] {
  min-height: var(--touch);
  padding: 0.6rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card-2);
  color: var(--ink);
  /* 1rem or larger, so iOS does not zoom the page on focus. */
  font: inherit;
  font-size: 1.05rem;
}

input::placeholder {
  color: var(--ink-soft);
}

input:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

button {
  font: inherit;
  cursor: pointer;
}

button.primary {
  min-height: var(--touch);
  padding: 0.7rem 1.1rem;
  border: none;
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}

button.primary:hover:not([disabled]) {
  background: var(--accent-hover);
}

button.primary[disabled] {
  opacity: 0.55;
  cursor: default;
}

/* Quiet is an outline button now (the render's Rejoin and Join a different
   room), not an underlined text link — it shares the touch floor. Anchors may
   wear it too (J24 fix 1: Print room cards and Home are controls, and a
   control looks like a button whatever element it is). */
button.quiet,
a.quiet {
  min-height: var(--touch);
  padding: 0.6rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: transparent;
  color: var(--ink);
  font-size: var(--text-body);
}

a.quiet {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

button.quiet:hover,
a.quiet:hover {
  border-color: var(--accent);
}

/* Touch first: on the student's panels, buttons run full width. The console's
   inline controls opt back out below. */
.card button.primary,
.card button.quiet {
  width: 100%;
}

.error {
  margin: 0;
  color: var(--bad);
  font-size: 0.9rem;
}

.joined-lead {
  margin: 0;
  font-size: 1.3rem;
}

/* ---- the console's room picker --------------------------------------------- */

.picker-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: 0.6rem;
  /* The cards page's picker is a <ul> wearing this class (J24) — the list
     chrome goes, the grid stays, and each item is its row. */
  margin: 0;
  padding: 0;
  list-style: none;
}

.picker-list li {
  display: contents;
}

.room-choice {
  /* An anchor on the cards page, a button on the console — one look. A
     control row is not a text link, so rule 3's underline does not apply. */
  text-decoration: none;
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  min-height: var(--touch);
  padding: 0.8rem 0.9rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card-2);
  color: var(--ink);
  text-align: left;
}

.room-choice:hover {
  border-color: var(--accent);
}

.room-choice-label {
  font-weight: 600;
}

/*
  `.room-choice-code` went with J29 item 6, in the same act as its last two
  writers rather than left behind as an orphan: the code sub-line is gone from
  both room pickers, because a row reading "Room A - Alpaca" already ends in the
  code's own word. The printed card's code line is unaffected and has its own
  rule in cards.html.
*/

/* ---- the roster ------------------------------------------------------------- */

.roster-head {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.5rem;
  align-items: flex-start;
  justify-content: space-between;
}

/* The console's header controls: cards, Change room, Home in one row (J24). */
.head-controls {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.roster-head h2 {
  margin: 0 0 0.15rem;
  font-size: 1.15rem;
  text-transform: none;
  letter-spacing: normal;
  color: var(--ink);
}

.roster-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.roster-entry {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: var(--touch);
  padding: 0.55rem 0.8rem;
  border-radius: var(--radius);
  background: var(--card-2);
}

.roster-entry .dot {
  background: var(--ok);
}

/*
 * A reconnecting player must be unmistakable from a metre away on a laptop, and
 * must not read as an error — they are mid-recovery, not broken. The warn amber
 * is the accent (rule 2), the fill is the soft accent, and the name stays full
 * strength in ink (rule 1): it is still the most important thing in the row.
 */
.roster-entry[data-connected="false"] {
  border-left: 3px solid var(--warn);
  background: var(--accent-soft);
}

.roster-entry[data-connected="false"] .dot {
  background: var(--warn);
}

.reconnecting-badge {
  margin-left: auto;
  padding: 0.15rem 0.5rem;
  border: 1px solid var(--warn);
  border-radius: 0.25rem;
  background: var(--accent-soft);
  color: var(--ink);
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  white-space: nowrap;
}

.count-reconnecting {
  color: var(--warn);
  font-weight: 700;
}

.roster-name {
  font-size: 1.05rem;
}

/* ---- Sound Check's screens (the shared vocabulary) -------------------------- */

.activity-surface {
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  margin-top: 0.5rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--line);
}

.activity-question {
  margin: 0;
  font-size: 1.15rem;
  font-weight: 600;
}

.option-list {
  display: grid;
  gap: 0.6rem;
}

.option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  /* A comfortable thumb target, not a form control. */
  min-height: 3.25rem;
  padding: 0.8rem 1rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--card-2);
  color: var(--ink);
  text-align: left;
}

.option-label {
  font-size: 1.15rem;
  font-weight: 600;
}

/* Rule 4: option rows are --card-2, so the count is ink, not soft. */
.option-count {
  font-size: var(--text-label);
  color: var(--ink);
}

/*
 * YOUR OWN ANSWER, and nobody else's — there is no styling here for another
 * player's choice because no other player's choice ever reaches this page.
 * The accent marks it (an active state), per the token sheet.
 */
.option[data-chosen="true"] {
  border: 2px solid var(--accent);
  background: var(--accent-soft);
}

.option[disabled] {
  cursor: default;
  opacity: 0.9;
}

.activity-note {
  margin: 0;
}

/* ---- the console's half ----------------------------------------------------- */

.activity-panel:empty {
  display: none;
}

.activity-panel {
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  margin-top: 1rem;
  padding: 1rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.activity-heading {
  margin: 0;
  font-size: 1.05rem;
}

.activity-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

/* The console's controls are inline, laptop-sized — they opt out of the
   student panels' full-width rule. */
.activity-panel button.primary,
.activity-panel button.quiet,
.activity-controls button {
  width: auto;
}

.tally-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.tally-entry {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.5rem 0.8rem;
  border-radius: var(--radius);
  background: var(--card-2);
}

.tally-label {
  font-size: 1.05rem;
}

.tally-count {
  font-size: 1.25rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

/* ---- the picker, formation, and the waiting state ---------------------------
   Platform surfaces, not an activity's. They look the same whatever is
   running — which is the point of them. */

/*
  WAITING IS A STATE. A student who joins before the facilitator has chosen
  anything sees this rather than a blank space under their own name, because a
  blank space reads as a page that failed and a student who reloads a page they
  think is broken is the one the seat token exists to protect.
*/
.waiting {
  padding: 0.9rem 1rem;
  border: 1px dashed var(--line);
  border-radius: var(--radius);
}

.run-control {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-top: 1rem;
  padding: 1rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.choice-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}

.activity-choice,
.formation-choice {
  min-height: var(--touch);
  padding: 0.55rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--card-2);
  color: var(--ink);
  text-align: left;
}

.activity-choice:hover:not([disabled]),
.formation-choice:hover:not([disabled]) {
  border-color: var(--accent);
}

/*
  THE CURRENT CHOICE IS MARKED AND DISABLED, and both matter. Marked with the
  accent, so a facilitator glancing down knows what the room is doing without
  reading the line above; disabled, so re-pressing the thing that is already
  true cannot restart a running activity by accident.
*/
.activity-choice[data-current="true"],
.formation-choice[data-current="true"] {
  border-color: var(--accent);
  background: var(--accent-soft);
  font-weight: 600;
}

/*
  A choice that is not built yet reads as unavailable rather than broken. Seated
  formation is Step 4b and is deliberately visible: a facilitator who never saw
  it would not know the platform is meant to have it.
*/
.activity-choice[disabled],
.formation-choice[disabled] {
  opacity: 0.55;
}

/*
  THE READ ROWS — J28 item 3, Hidden Agenda's nine dimensions as dropdowns.

  One row per question, the question above its own control, and the control at
  full width so nine of them read as a column rather than as a wrapped mass of
  buttons. That mass is what the ruling replaced: at console widths the old
  three-button rows wrapped and lost their alignment, so the facilitator had to
  find the row before they could answer it.

  The select is styled rather than left native because a default control on a
  dark surface renders as a white slab; nothing here changes how it behaves.
*/
.ha-read-row {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  margin-bottom: 0.6rem;
}

.ha-read-select {
  min-height: var(--touch);
  padding: 0.5rem 0.6rem;
  background: var(--card-2);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font: inherit;
  width: 100%;
}

.ha-read-select:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/*
  THE CONFIRM — J27 items 5 and 8. It appears between the controls and the
  groups panel, above the thing it is about to destroy, and it is styled with
  the warning colour rather than the accent: the accent means "this is what the
  room is doing", and this is a question, not a state.

  Loud on purpose. The tap it intercepts costs thirty students a rescan, and the
  whole reason it exists is that four consecutive staged reproductions showed
  nothing on screen at all when the partition went.
*/
.control-confirm {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.9rem;
  padding: 0.8rem 1rem;
  background: var(--card);
  border: 1px solid var(--warn);
  border-radius: var(--radius);
}

.control-confirm .note {
  flex: 1 1 14rem;
  margin: 0;
  color: var(--ink);
}

.groups {
  margin-top: 0.9rem;
}

.groups-list {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.group-entry {
  display: grid;
  grid-template-columns: auto auto;
  gap: 0.1rem 0.6rem;
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius);
  background: var(--card-2);
}

.group-label {
  font-weight: 600;
}

/* Rule 4: a --card-2 row, so the size figure holds full ink — the old
   opacity dim was soft ink in costume. */
.group-size {
  justify-self: end;
  font-variant-numeric: tabular-nums;
}

/* The names span both columns beneath the heading row. */
.group-members {
  grid-column: 1 / -1;
}
