/* ============================================================
   Staff console (/admin rig dashboard)

   Propshaft links stylesheets alphabetically, so this file loads
   BEFORE theme.css: anything that overrides a theme rule is written
   compound (.chip.chip-idle) so it wins on specificity, not order.
   ============================================================ */

/* ---------- console shell ---------- */

/* The console is read standing at the counter, on the shop's widescreen
   monitor. Tailwind's .container caps every page at 96rem, which left a
   ten-rig board in the top-left corner of that screen with half the display
   empty. Document-shaped admin pages (forms, member tables) still want that
   cap, so the wide shell is opt-in: a view declares `content_for
   :wide_console` and the whole shell widens with it, nav and footer included,
   so nothing floats out of line with the board. The wide cap exists only so a
   49" ultrawide does not stretch one row of cards across a metre of glass. */
.console-shell {
  width: 100%;
  max-width: 96rem;
  margin-inline: auto;
}
.console-wide .console-shell { max-width: 160rem; }

/* ---------- summary strip ---------- */

/* The counts are the first thing read on walking up to the screen, so they
   grow with the monitor. Every clamp on this board has the old fixed size as
   its lower bound: a phone renders exactly what it rendered before. */
.stat {
  display: inline-flex;
  align-items: baseline;
  gap: 0.3rem;
  font-size: clamp(0.78rem, 0.74rem + 0.12vw, 0.95rem);
  color: var(--ink-muted);
  white-space: nowrap;
}
.stat-n {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(1.05rem, 0.9rem + 0.42vw, 1.6rem);
  line-height: 1;
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--ink);
}
.stat-live .stat-n { color: var(--pb); }
/* Problems draw the eye; a zero is not a problem, so it stays quiet. */
.stat-bad, .stat-bad .stat-n { color: var(--danger); }
.stat-warn, .stat-warn .stat-n { color: var(--warm); }
.stat-zero, .stat-zero .stat-n { color: var(--ink-faint); }

/* ---------- the rig board ---------- */

/* Columns follow the width of the glass, not a hard-coded breakpoint ladder,
   so the same board is right on a phone, a 1080p counter screen and an
   ultrawide. auto-fit (not auto-fill) lets a small shop grow into the space
   instead of huddling in one corner; the card's own max-width is what stops a
   two-rig shop producing two absurdly wide cards.
   align-items: start so a card that opens a panel grows on its own instead of
   stretching every other card in its row.

   26rem is not a taste call: it is the narrowest a card can be and still fit
   End stint / +15 min / Swap / Setup on one line. A wrapped action row is
   forty pixels taller than an unwrapped one, and a row where only the
   occupied cards wrapped is exactly the raggedness this board had. Shrink
   this number and the free cards stop lining up with the driven ones. */
.rig-board {
  --rig-col: 26rem;
  display: grid;
  gap: 0.75rem;
  align-items: start;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--rig-col)), 1fr));
}
/* Density follows the fleet, because two rigs and twenty are different
   problems: a small shop gets big seats, a big one gets all of them on
   screen at once. The dense tier buys its narrower cards by tightening the
   buttons rather than by letting them wrap. */
.rig-board.board-roomy { --rig-col: 34rem; }
.rig-board.board-dense { --rig-col: 23rem; }
.board-dense .btn.btn-console { font-size: 0.8rem; padding-inline: 0.6rem; }

/* ---------- rig card ---------- */

/* A colored rail down the left edge: the whole grid can be read from
   across the counter without landing on any single card. */
.rig-card {
  border-left: 3px solid var(--rig-rail, var(--edge-strong));
  /* A free card was half the height of an occupied one, which is what made
     the grid look ragged. Both clear the same floor now, with the action row
     pinned to the bottom of it, so every row lines up. The floor grows with
     the screen because everything inside it does. */
  min-height: clamp(10.5rem, 9rem + 3vw, 13.5rem);
  /* Small fleet, huge monitor: a stretched track can be a metre wide, and a
     card that wide is unreadable. */
  max-width: 44rem;
}
.rig-driving        { --rig-rail: var(--pb); }
.rig-in-sim         { --rig-rail: var(--wet); }
.rig-idle           { --rig-rail: var(--warm); }
.rig-offline        { --rig-rail: var(--edge-strong); }
.rig-out-of-service { --rig-rail: var(--danger); }

.rig-card.is-over {
  --rig-rail: var(--danger);
  border-color: rgba(248, 113, 113, 0.45);
}
.rig-card.is-warn {
  --rig-rail: var(--warm);
  border-color: rgba(229, 181, 103, 0.4);
}

/* The rig's own name, and the seat block holding the driver and the clock.
   The seat has a floor of its own so a "Free" card and a driver card present
   the same shape even before the card's min-height gets involved. */
.rig-name {
  font-size: clamp(1rem, 0.9rem + 0.32vw, 1.35rem);
  line-height: 1.15;
}
.rig-seat { min-height: clamp(3.2rem, 2.7rem + 1.1vw, 4.6rem); }
.rig-driver {
  font-size: clamp(0.875rem, 0.78rem + 0.3vw, 1.2rem);
  line-height: 1.2;
}

/* ---------- the countdown: the one number staff actually need ---------- */

/* Rendered as a <label> on an occupied shop rig: the caption names the limit,
   so the caption is what opens the form that changes it. The action row has
   no room for a fifth button (see .rig-board), and burying the only way to
   set a limit is what left staff with no way to give somebody another twenty
   minutes. display:block because a <label> is inline by default and this has
   always sat on its own line. */
.rig-clock-cap {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(0.62rem, 0.58rem + 0.13vw, 0.78rem);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  line-height: 1.2;
  color: var(--ink-faint);
}
.rig-clock-num {
  font-family: var(--font-display);
  font-weight: 700;
  /* The hero, and the one thing on this board legible from the far side of
     the counter. It is the number that grows the most with the screen. */
  font-size: clamp(1.4rem, 1.05rem + 0.85vw, 2.2rem);
  line-height: 1.15;
  letter-spacing: 0.01em;
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--ink);
  white-space: nowrap;
}
.rig-clock.is-warn .rig-clock-num,
.rig-clock.is-warn .rig-clock-cap { color: var(--warm); }
.rig-clock.is-over .rig-clock-num,
.rig-clock.is-over .rig-clock-cap { color: var(--danger); }

/* Elapsed, under the countdown. Quiet on purpose: it is context, and the
   number staff act on is the one above it. */
.rig-clock-sub {
  font-size: 0.62rem;
  line-height: 1.3;
  color: var(--ink-faint);
}

/* A driving-time countdown that is not counting, because the member is not on
   track. The number has to look deliberately stopped: a frozen clock that
   still looks live reads as a broken dashboard, and this one stopping is the
   whole feature (their minutes are not being spent).

   Written :not(...) so it never outranks a warning or an overrun: somebody
   can be out of the car AND out of time, and "out of time" is the colour
   staff need to see from across the counter. */
.rig-clock.is-held:not(.is-warn):not(.is-over) .rig-clock-num { color: var(--ink-muted); }
.rig-clock-hold { color: var(--warm); }

.rig-empty {
  font-family: var(--font-display);
  font-weight: 600;
  /* "Free" answers the same question the countdown does, from the same
     distance, so it is sized to sit beside it as an equal. */
  font-size: clamp(1.15rem, 0.95rem + 0.58vw, 1.8rem);
  line-height: 1.15;
  color: var(--ink-faint);
}

/* ---------- the controls staff press standing up ---------- */

/* Bigger than the .btn-sm used inside the disclosure panels: these are hit at
   arm's length, one-handed, while talking to somebody. Written compound so it
   beats theme.css's .btn-sm, which Propshaft loads after this file. */
.btn.btn-console {
  font-size: clamp(0.78rem, 0.72rem + 0.18vw, 0.92rem);
  padding: 0.5rem 0.85rem;
  min-height: 2.5rem;
}

/* ---------- status chips ---------- */

/* Two states theme.css has no chip for. Idle = the machine is up but
   iRacing is not running; offline = we have not heard from it at all. */
.chip.chip-idle {
  border-color: rgba(229, 181, 103, 0.35);
  background: var(--warm-soft);
  color: var(--warm);
}
.chip.chip-offline {
  border-color: var(--edge);
  background: rgba(255, 255, 255, 0.02);
  color: var(--ink-faint);
}

/* ---------- disclosures ---------- */

/* Progressive disclosure with no JavaScript, on purpose: the dashboard
   re-renders itself over a Turbo morph stream, and morphing resets the
   `open` attribute of a <details> (and any class a Stimulus controller
   toggled), collapsing a panel under the hand of whoever opened it.
   A checkbox marked data-turbo-permanent is skipped by the morph, so an
   open panel stays open while its contents still refresh. */
/* Visually hidden but still focusable and still clickable through its label:
   pointer-events:none here would stop the browser forwarding a real click
   from the label to the box. */
.disc-toggle {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
/* Each disclosure is paired by its data-disc value, because several toggles
   share one container and a bare `:checked ~ .disc-panel` would open all of
   them. CSS cannot say "same attribute value on both sides", so every value
   has to be listed here in all three blocks below. Adding a data-disc in a
   view without adding it here yields a button that silently does nothing;
   AdminDisclosureTest fails when the two lists drift apart. */
.disc-panel { display: none; }
.disc-toggle[data-disc="assign"]:checked ~ .disc-panel[data-disc="assign"],
.disc-toggle[data-disc="limit"]:checked ~ .disc-panel[data-disc="limit"],
.disc-toggle[data-disc="setup"]:checked ~ .disc-panel[data-disc="setup"],
.disc-toggle[data-disc="shop"]:checked ~ .disc-panel[data-disc="shop"],
.disc-toggle[data-disc="addrig"]:checked ~ .disc-panel[data-disc="addrig"],
.disc-toggle[data-disc="homerigs"]:checked ~ .disc-panel[data-disc="homerigs"] { display: block; }

/* Member typeahead. The list is absolutely positioned so it floats over the
   cards below instead of pushing the grid around while someone types, and the
   z-index has to clear neighbouring cards in the same row. */
.combo { position: relative; }
.combo-list {
  position: absolute;
  z-index: 30;
  top: calc(100% + 2px);
  left: 0;
  right: 0;
  max-height: 15rem;
  overflow-y: auto;
  margin: 0;
  padding: 0.25rem;
  list-style: none;
  background: var(--surface-2);
  border: 1px solid var(--edge-strong);
  border-radius: calc(var(--radius) - 3px);
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.55);
}
.combo-list[hidden] { display: none; }
.combo-option {
  display: flex;
  flex-direction: column;
  gap: 0.05rem;
  padding: 0.35rem 0.5rem;
  border-radius: calc(var(--radius) - 6px);
  cursor: pointer;
}
.combo-option.is-active { background: var(--accent-soft); }
.combo-name { font-size: 0.85rem; color: var(--ink); }
.combo-hint { font-size: 0.68rem; color: var(--ink-faint); }
.combo-empty { padding: 0.35rem 0.5rem; font-size: 0.72rem; color: var(--ink-faint); }

.disc-label { cursor: pointer; }
.disc-label::after {
  content: "▾";
  font-size: 0.7em;
  opacity: 0.7;
}
.disc-toggle[data-disc="assign"]:checked ~ * .disc-label[data-disc="assign"]::after,
.disc-toggle[data-disc="limit"]:checked ~ * .disc-label[data-disc="limit"]::after,
.disc-toggle[data-disc="setup"]:checked ~ * .disc-label[data-disc="setup"]::after,
.disc-toggle[data-disc="shop"]:checked ~ * .disc-label[data-disc="shop"]::after,
.disc-toggle[data-disc="addrig"]:checked ~ * .disc-label[data-disc="addrig"]::after,
.disc-toggle[data-disc="homerigs"]:checked ~ .disc-label[data-disc="homerigs"]::after,
.disc-toggle[data-disc="homerigs"]:checked ~ * .disc-label[data-disc="homerigs"]::after { content: "▴"; }

/* The visible label carries the focus ring for its screen-reader-only box. */
.disc-toggle[data-disc="assign"]:focus-visible ~ * .disc-label[data-disc="assign"],
.disc-toggle[data-disc="limit"]:focus-visible ~ * .disc-label[data-disc="limit"],
.disc-toggle[data-disc="setup"]:focus-visible ~ * .disc-label[data-disc="setup"],
.disc-toggle[data-disc="shop"]:focus-visible ~ * .disc-label[data-disc="shop"],
.disc-toggle[data-disc="addrig"]:focus-visible ~ * .disc-label[data-disc="addrig"],
.disc-toggle[data-disc="homerigs"]:focus-visible ~ .disc-label[data-disc="homerigs"],
.disc-toggle[data-disc="homerigs"]:focus-visible ~ * .disc-label[data-disc="homerigs"] {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
