/* static/vr.css — the vocabulary every page shares.
 *
 * Linked BEFORE each page's own <style>, deliberately: a page-specific rule of
 * equal specificity then wins on source order, so this file sets the defaults
 * and a page can still say something different about its own layout without
 * fighting !important.
 *
 * Colours are read from each page's own :root custom properties, with the
 * literal values as fallbacks. That is not belt-and-braces for its own sake:
 * every page defines --red/--amber/--blue/--green in its own :root today, and
 * the fallback is what keeps this file honest if one ever links it before
 * declaring them.
 */

/* ---- the delay vocabulary ----------------------------------------------
 *
 * ONE set of bands for the whole app -- delayCls() in vr.js emits these, the
 * hex thresholds in /map's colourFor() are the same numbers, and hc.php's
 * server-side formatter matches. What they mean:
 *
 *   .delay-early  blue    running early. Noticeable, rarely actionable, and
 *                         on this railway a large negative figure is usually
 *                         a report matched to the wrong day's slot (see /odd).
 *   .delay-ok     green   RT, +1, +2. On time by any operational measure --
 *                         the industry PPM threshold is 5 or 10 minutes -- and
 *                         painting a +1 train the same red as one half an hour
 *                         down made a normal morning look like a bad one.
 *   .delay-mid    amber   +3 to +9. Slipping; worth a second look.
 *   .delay-late   red     +10 and worse.
 *
 * Colour only, no weight or size: these spans land inside table cells, inline
 * strip items and tooltips alike, and each of those already sets its own type.
 */
.delay-late  { color: var(--red,   #f85149); }
.delay-mid   { color: var(--amber, #ffb000); }
.delay-early { color: var(--blue,  #58a6ff); }
.delay-ok    { color: var(--green, #3fb950); }

/* ---- the board key -----------------------------------------------------
 *
 * The bands above are only self-explanatory once you know them, and a colour
 * key that is not written in the colours it describes is a second thing to
 * learn. This one is drawn with the real classes, so it is the legend and a
 * live sample of the rendering at the same time. */
.boardKey { font-size: 10px; color: var(--dim, #8b949e); padding: 6px 10px 0;
  letter-spacing: .2px; }

/* ---- "Normally: +3" ----------------------------------------------------
 *
 * cursor:help on a desktop, a real tap target on a phone -- the expanded text
 * is the title attribute's own content (mirrored into data-explain), so hover
 * and tap can never drift apart.
 *
 * display:block by default because the overwhelmingly common home for this is
 * under a booked time in a table cell. /concise's banner strip puts it back to
 * inline, which is the right way round: the inline case is the exception and
 * has to opt in, so a block element can never end up nested inside an inline
 * one by omission. */
.nrm { display: block; font-size: 10px; color: var(--dim, #8b949e); cursor: help; }
/* Marks a "normally" figure as THIS WEEKDAY's rather than the all-days one.
   Without it the two are indistinguishable on screen and they can differ by
   ten minutes on a Sunday engineering timetable. font-style:normal because
   some pages sit this inside italic secondary text. */
.nrm .dowTag { margin-left: 3px; font-size: 9px; text-transform: uppercase;
  letter-spacing: .3px; opacity: .8; font-style: normal; }
/* The expanded explanation. Wrapping is forced back on because board cells set
   white-space:nowrap for the table's sake, and a full sentence in one unbroken
   line would run off the side of a 200px banner. */
.nrm.open::after { content: attr(data-explain); display: block; margin-top: 2px;
  max-width: 34ch; white-space: normal; font-style: italic; line-height: 1.3; }

/* ---- tap-revealed explainers (see vrTapTips() in vr.js) -----------------
 *
 * Touch devices only. Deliberately high-contrast and wide: it is read at arm's
 * length on a platform, often in daylight, which is not the condition a desktop
 * tooltip is designed for. */
.tapTip { position: absolute; z-index: 9999; max-width: min(20rem, calc(100vw - 12px));
  background: var(--bg, #0d1117); color: var(--txt, #e6edf3);
  border: 1px solid var(--amber, #ffb000); border-radius: 6px;
  padding: 7px 10px; font-size: 13px; line-height: 1.4;
  box-shadow: 0 6px 20px rgba(0,0,0,.6); }
/* On touch, mark the things that have something to say. Without this the tap
   target is invisible -- on desktop the cursor change does that job. Links are
   excluded here for the same reason vrTapTips() excludes them: their tap
   already means something else. */
html.touch-tips .live[title], html.touch-tips .trivia[title],
html.touch-tips .plat[title], html.touch-tips .src[title] {
  text-decoration: underline dotted var(--dim, #8b949e); text-underline-offset: 2px; }

/* ---- Darwin platform diagram (renderDarwinPlatforms() in vr.js) ---------
 *
 * The no-describer fallback: platform rows with train chips, drawn wherever a
 * berth ladder was refused because no TD area covers the place. Two visual
 * registers and only two: a SOLID chip is a logged arrival ("at platform"), a
 * DASHED one is a forecast. The distinction is the whole honesty story of
 * this diagram, so nothing else here is allowed to look like it. */
.dpDiagram { text-align: left; font-size: 12px; }
.dpHead { color: var(--dim, #8b949e); padding: 2px 0 6px; }
.dpSrc { margin-left: 8px; font-size: 10px; cursor: help;
  text-decoration: underline dotted var(--dim, #8b949e); text-underline-offset: 2px; }
.dpRow { display: flex; align-items: flex-start; gap: 8px; padding: 3px 0;
  border-bottom: 1px solid rgba(139,148,158,.15); }
.dpPlat { flex: 0 0 4.5em; text-align: right; color: var(--dim, #8b949e);
  font-variant-numeric: tabular-nums; padding-top: 2px; white-space: nowrap; }
.dpPlatNone { font-size: 10px; cursor: help; }
.dpRail { flex: 1; display: flex; flex-wrap: wrap; gap: 4px; min-height: 1.4em; }
.dpChip { border: 1px solid var(--dim, #8b949e); border-radius: 9px;
  padding: 1px 7px; white-space: nowrap; cursor: default; }
.dpChip a { color: inherit; text-decoration: none; }
.dpAt   { border-color: var(--green, #3fb950); }
.dpDue  { border-style: dashed; color: var(--dim, #8b949e); }
.dpLate { border-color: var(--amber, #ffb000); }
/* The recent strip is the past, and reads as it: no border weight, struck. */
.dpRecent { padding-top: 5px; color: var(--dim, #8b949e); font-size: 11px;
  display: flex; flex-wrap: wrap; gap: 4px; }
.dpGone { border: none; padding: 1px 4px; text-decoration: line-through;
  text-decoration-color: rgba(139,148,158,.5); }
/* The refusal text when a platform view is drawn above it: still said, but as
   a footnote to a diagram rather than as the whole answer. */
.dpWhy { font-size: 10px; margin-top: 6px; opacity: .75; }
