/* One palette. Previously copied into five files, where it had already drifted:
   the listener pair used #0E1418 and the operator trio #0B1014. */
:root{
  --bg:#0B1014;
  --panel:#131C22;
  --raise:#1A252D;
  --sunk:#080C0F;
  --line:#243139;
  --ink:#DBE4E9;
  --dim:#71838F;
  --dead:#3A4852;

  --live:#FFA23A;
  --live-dim:#8A5A22;
  --go:#3FD08A;
  --alert:#FF5A47;
  --caller:#4EA8F5;

  --mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
  --cond:"IBM Plex Sans Condensed","IBM Plex Sans",system-ui,sans-serif;
  --sans:"IBM Plex Sans",system-ui,-apple-system,sans-serif;
}

*{box-sizing:border-box;margin:0;padding:0}

/* `hidden` is a UA-stylesheet rule, so ANY author class that sets display beats
   it — an element with .btn (inline-flex) or .row (grid) stays on screen with
   the attribute set and nothing reports a problem. prep.html already carried a
   local `.bench[hidden]` patch for this; one rule here retires the whole class
   of bug rather than each new instance of it. */
[hidden]{display:none !important}
.num{font-family:var(--mono);font-variant-numeric:tabular-nums}

/* 44x44 is WCAG 2.5.5 and the floor this project treats as non-negotiable.
   inline-flex rather than the default inline-block: a min-height on an inline
   box is ignored, so the padding has to be doing the work and any surface that
   trims the padding silently drops under the minimum. That is exactly how
   prep.html ended up with thirteen sub-44px controls. */
.btn{appearance:none;background:var(--raise);border:1px solid var(--line);
  border-radius:2px;color:var(--ink);font-family:var(--mono);font-size:12px;
  font-weight:500;letter-spacing:.14em;text-transform:uppercase;
  padding:13px 16px;cursor:pointer;white-space:nowrap;
  display:inline-flex;align-items:center;justify-content:center;
  min-height:44px;min-width:44px;
  transition:border-color .15s,background .15s,color .15s}
.btn:hover:not(:disabled){border-color:var(--dim)}
.btn:focus-visible{outline:2px solid var(--live);outline-offset:2px}
.btn:disabled{opacity:.34;cursor:not-allowed}
.btn.go{border-color:#256B4A;color:var(--go)}
.btn.go:hover:not(:disabled){background:rgba(63,208,138,.1);border-color:var(--go)}
.btn.hot{border-color:var(--live-dim);color:var(--live)}
.btn.hot:hover:not(:disabled){background:rgba(255,162,58,.1);border-color:var(--live)}
.btn.danger{border-color:#7A2E26;color:var(--alert)}
.btn.danger:hover:not(:disabled){background:rgba(255,90,71,.1);border-color:var(--alert)}
/* .sm trims the padding for dense rows; the floor still applies. */
.btn.sm{padding:5px 8px;font-size:9px;letter-spacing:.1em}

/* A control that carries a value has to show both, and they are not the same
   kind of text.

   Built as one uppercase string ("BREAK: PERRICECONSULTINGSPON…") three things
   went wrong at once: the value inherited the label's caps and letter-spacing,
   which is 15% wider and strips the word shapes that make a name scannable; the
   caller truncated the string in JavaScript before CSS ever saw it, so a wide
   screen could not offer it more room; and because the characters were gone
   rather than clipped, no tooltip could recover them. The full name was
   unreachable from the interface.

   Split in two, the label stays a label and the value is just text — clipped by
   CSS at whatever width the screen actually has, with the full string still in
   the title attribute. */
.btn.pill{gap:9px;justify-content:flex-start;text-transform:none;letter-spacing:0}
.btn.pill .k{flex:none;font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--dim)}
.btn.pill .v{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:13ch}
.btn.pill .v.empty{color:var(--dim);font-style:italic}
@media (min-width:900px){ .btn.pill .v{max-width:22ch} }
@media (min-width:1400px){ .btn.pill .v{max-width:34ch} }
.btn[aria-pressed="true"]{background:rgba(255,162,58,.14);border-color:var(--live);color:var(--live)}

/* Base rule is the phone: 44px tall, and 16px text so mobile Safari does not
   zoom the whole page on focus. Operator density is restored from 700px up. */
.fld{appearance:none;background:var(--sunk);border:1px solid var(--line);
  border-radius:2px;color:var(--ink);font-size:16px;padding:10px 11px;
  width:100%;min-width:0;min-height:44px}
.fld:focus{outline:none;border-color:var(--live)}
.fld.mono{font-family:var(--mono);font-variant-numeric:tabular-nums}

@media (min-width:700px){
  .fld{font-size:13px}
}

/* Dialogs and notices, rendered by dialogs.js. The markup is built there and
   styled here for the same reason the palette lives here: rotation.html had the
   only toast in the project, so every other surface reached for the browser's
   alert box instead of a 12-line stylesheet.

   <dialog> renders in the top layer, so it needs no z-index — and cannot be
   trapped behind one. Both the element and ::backdrop must be painted: an
   unstyled backdrop is the UA's translucent white. */
.modal{border:1px solid var(--line);border-radius:2px;background:var(--panel);
  color:var(--ink);font-family:var(--sans);font-size:14px;padding:0;
  width:min(440px,calc(100vw - 32px));box-shadow:0 24px 60px rgba(0,0,0,.6)}
.modal::backdrop{background:rgba(4,7,9,.72)}
.modal form{display:flex;flex-direction:column;gap:14px;padding:20px}
.modal-title{font-family:var(--mono);font-size:11px;font-weight:400;
  letter-spacing:.22em;text-transform:uppercase;color:var(--dim)}
.modal-body{display:flex;flex-direction:column;gap:9px;line-height:1.5}
.modal-body p{overflow-wrap:anywhere}
.modal.bad .modal-title{color:var(--alert)}
.modal.warn .modal-title{color:var(--live)}
/* Phone first: full-width stacked buttons, because a 44px target pinned to the
   right edge of a narrow dialog is the hardest thing on screen to hit with a
   thumb. Side by side only when the dialog is wide enough for it. */
.modal-ops{display:flex;flex-direction:column-reverse;gap:8px}
.modal-ops .btn{width:100%}
@media (min-width:460px){
  .modal-ops{flex-direction:row;justify-content:flex-end}
  .modal-ops .btn{width:auto}
}

/* A modal that asks for answers. Wider than a confirmation because it holds
   fields, and scrollable because a phone in landscape has almost no height. */
.modal.form{width:min(520px,calc(100vw - 32px))}
.modal.form form{max-height:min(82dvh,720px);overflow-y:auto}
.modal-fields{display:flex;flex-direction:column;gap:15px}
.fieldrow{display:flex;flex-direction:column;gap:6px;min-width:0}
.fieldhint{font-size:12px;color:var(--dim);line-height:1.45}
.fieldproblem{font-family:var(--mono);font-size:12px;color:var(--alert);
  border-left:2px solid var(--alert);padding-left:10px}
.modal select.fld{cursor:pointer}
/* Each choice is a whole row and a whole tap target — a bare radio is 13px on a
   phone, which is a quarter of the 44px floor everything else here clears. */
.choices{display:flex;flex-direction:column;gap:7px}
.choice{display:flex;align-items:flex-start;gap:11px;cursor:pointer;
  border:1px solid var(--line);border-radius:2px;background:var(--sunk);
  padding:11px 13px;min-height:44px}
.choice:hover{border-color:var(--dim)}
.choice:has(input:checked){border-color:var(--live);background:rgba(255,162,58,.07)}
.choice:focus-within{outline:2px solid var(--live);outline-offset:2px}
.choice input{margin-top:2px;accent-color:var(--live);width:16px;height:16px;flex:none}
.choice-txt{display:flex;flex-direction:column;gap:3px;min-width:0}
.choice-txt b{font-family:var(--mono);font-size:12px;font-weight:500;
  letter-spacing:.1em;text-transform:uppercase;color:var(--ink)}
.choice-txt i{font-style:normal;font-size:12px;color:var(--dim);line-height:1.45}

/* Transient, non-blocking, and never the carrier of a decision. */
.toast{position:fixed;left:50%;transform:translateX(-50%);bottom:22px;
  max-width:calc(100vw - 32px);background:var(--raise);
  border:1px solid var(--line);border-radius:2px;padding:12px 18px;
  font-family:var(--mono);font-size:12px;color:var(--ink);
  box-shadow:0 10px 30px rgba(0,0,0,.5);z-index:60}
.toast.ok{border-color:#256B4A;color:var(--go)}
.toast.warn{border-color:var(--live-dim);color:var(--live)}
.toast.bad{border-color:var(--alert);color:var(--alert)}

/* Scrollbars are part of this UI, not the browser's chrome around it. Once the
   operator surfaces became app shells with panes scrolling inside them, the bars
   moved inside the design — and left alone they render in the host OS's light
   theme, putting bright grey strips down a near-black console.
   Both syntaxes are required and neither is redundant: `scrollbar-color` is the
   standard (Firefox, and Blink from 121) and inherits, so declaring it on html
   themes every pane; `::-webkit-scrollbar` is what older WebKit/Blink honours
   and is not inherited, hence the universal selector.
   The track is --sunk and the thumb --dead, which is the same pairing the rest
   of the station uses for a recessed surface and an inactive control. */
html{scrollbar-color:var(--dead) var(--sunk);scrollbar-width:thin}
*::-webkit-scrollbar{width:10px;height:10px}
*::-webkit-scrollbar-track{background:var(--sunk)}
/* The border is the gap: a thumb drawn edge-to-edge in a 10px gutter reads as a
   solid bar rather than a handle. */
*::-webkit-scrollbar-thumb{background:var(--dead);border-radius:6px;
  border:2px solid var(--sunk)}
*::-webkit-scrollbar-thumb:hover{background:var(--dim)}
*::-webkit-scrollbar-corner{background:var(--sunk)}

@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* Operator switcher. Rendered from surfaces.js, and deliberately absent from
   index.html and obs.html: one is what the public sees, the other is pixels
   going to a stream. */
/* One line, always. Wrapping put this on three rows at phone width and shoved
   the console's show clock out of the header — a switcher is navigation, not
   content, and it should never be the tallest thing on screen. It scrolls
   sideways instead, in its own container, so the page body still never does. */
.surfnav{display:flex;gap:6px;flex-wrap:nowrap;align-items:center;
  overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch;
  max-width:100%}
.surfnav::-webkit-scrollbar{display:none}
.surfnav .surf{flex:none}
.surfnav .surf{display:inline-flex;align-items:center;min-height:44px;
  padding:0 12px;border:1px solid var(--line);border-radius:2px;
  background:var(--raise);color:var(--dim);text-decoration:none;
  font-family:var(--mono);font-size:10px;letter-spacing:.16em;
  text-transform:uppercase;white-space:nowrap;
  transition:border-color .15s,color .15s}
.surfnav .surf:hover{border-color:var(--dim);color:var(--ink)}
.surfnav .surf:focus-visible{outline:2px solid var(--live);outline-offset:2px}
.surfnav .surf.on{border-color:var(--live);color:var(--live);
  background:rgba(255,162,58,.09)}
.surfnav .surf.listen{color:var(--go);border-color:#256B4A}
