/* What Tailwind cannot reach.
 *
 * Everything with a class on it is styled in the markup. This file is only for
 * nodes built by JavaScript — rendered markdown and SVG charts — which have no
 * markup to carry utility classes, plus the one Alpine convention.
 *
 * It replaced 340 lines of bespoke CSS. If something here could be a utility
 * class in a template, it belongs there instead. */

/* Alpine strips x-cloak once it has initialised, which keeps state-dependent
   controls from flashing in their wrong state on first paint. */
[x-cloak] { display: none !important; }

/* ---- scrollbars ----
 *
 * The browser's default scrollbar is a wide grey gutter that reads as a
 * system control dropped into the page. These are the app's own: thin, and
 * invisible until the pointer is over the thing that scrolls. The hiding
 * matters more than the thinness — a transcript full of scrollable command
 * boxes grew a grey bar under every one of them, which is exactly the
 * prototype look this replaces.
 * scrollbar-width/color is the standard pair (Firefox, Chrome 121+); the
 * ::-webkit rules carry Safari and older Chromium, which ignore the former.
 * Both are set because whichever one the browser honours must say the same
 * thing. */
* {
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
}
*:hover {
  scrollbar-color: #cbd5e1 transparent;
}
*::-webkit-scrollbar { width: 8px; height: 8px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: transparent;
  border-radius: 8px;
  /* A transparent border clipped out of the thumb keeps it off the content
     edge, which is what makes 8px read as slim rather than cramped. */
  border: 2px solid transparent;
  background-clip: content-box;
}
*:hover::-webkit-scrollbar-thumb {
  background-color: #cbd5e1;
  background-clip: content-box;
}
*::-webkit-scrollbar-thumb:hover { background-color: #94a3b8; background-clip: content-box; }

/* ---- shimmer ----
 *
 * The wave of lighter letters that runs along a line while work is still in
 * flight. It is here rather than in the markup because it needs keyframes and
 * background-clip, neither of which is a utility class.
 *
 * The gradient is painted through the glyphs and scrolled sideways. Using
 * -webkit-text-fill-color rather than `color: transparent` to hide the flat
 * text is what lets the gradient be built from currentColor: the class
 * lightens whatever colour the element already had, so the same class works on
 * the slate-500 working label and the slate-400 progress line.
 *
 * background-size is a fixed width, not a percentage, so the wave is the same
 * size and speed on a three-word label as on a full progress line.
 *
 * That width is also what decides how many waves are on screen at once. It was
 * 14em, which is narrower than a full progress line — so a long line carried
 * two crests at the same time and read as two separate things happening. 34em
 * is wider than any line this is used on, so there is only ever one. The period
 * is the same number twice: the gradient repeats, and travelling exactly one
 * width per cycle is what makes the loop seamless. */
.shimmer {
  background-image: linear-gradient(100deg, currentColor 42%, #dde3ea 50%, currentColor 58%);
  background-size: 34em 100%;
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  /* One wave every five seconds rather than every two and a half. This sits
     beside a spinner that is already saying "working"; the shimmer's job is to
     make the line feel live, not to keep asking for attention. */
  animation: shimmer 5s linear infinite;
}

@keyframes shimmer {
  from { background-position: 0 0; }
  to   { background-position: 34em 0; }
}

/* Motion this constant is exactly what reduced-motion is for; the line still
   has to be readable, so drop back to plain text rather than freezing a
   half-faded gradient in place. */
@media (prefers-reduced-motion: reduce) {
  .shimmer {
    background-image: none;
    -webkit-text-fill-color: currentColor;
    animation: none;
  }
}

/* ---- rendered markdown ----
 *
 * Built by markdown.js with createElement, so these are the only hooks. Sized
 * relative to the container: the same renderer draws an answer at full size and
 * a reasoning summary at 0.875rem, and both must look deliberate. */

.md > :first-child { margin-top: 0; }
.md > :last-child { margin-bottom: 0; }

.md-p { margin: 0 0 0.7em; }

.md-h { margin: 1.1em 0 0.4em; font-weight: 600; line-height: 1.3; }
.md-h1 { font-size: 1.25em; }
.md-h2 { font-size: 1.15em; }
.md-h3 { font-size: 1.05em; }
.md-h4, .md-h5, .md-h6 { font-size: 1em; }

/* Tailwind's preflight resets ul and ol to list-style: none, and nothing here
   put the markers back — so every list rendered as flat indented lines. That is
   the wrong thing to lose: nested bullets are the commonest construct in these
   answers (see renderList in markdown.js), and without a marker a sub-list is
   distinguishable from its parent only by a 1.4em step, which reads as a wrapped
   line rather than as nesting. The padding-left below was always the room a
   marker needs; it had nothing to hold.

   The marker changes with depth so two levels can be told apart at a glance
   without counting indents. Type is matched rather than depth alone, so a
   numbered sub-list under a bulleted one still gets numbers. */
.md-list { margin: 0 0 0.7em; padding-left: 1.4em; }
.md-list .md-list { margin-bottom: 0; }
.md-list li { margin: 0.15em 0; }

ul.md-list { list-style: disc; }
ul.md-list ul.md-list { list-style: circle; }
ul.md-list ul.md-list ul.md-list { list-style: square; }

ol.md-list { list-style: decimal; }
ol.md-list ol.md-list { list-style: lower-alpha; }
ol.md-list ol.md-list ol.md-list { list-style: lower-roman; }

/* The marker is structure, not content, so it sits below the text it labels. A
   number is doing more work than a dot — "step 3" is something an answer refers
   back to — so it is only one step down rather than two. */
ul.md-list > li::marker { color: #94a3b8; }
ol.md-list > li::marker { color: #64748b; }

.md-link { color: #0284c7; text-decoration: underline; text-underline-offset: 2px; }
.md-link:hover { color: #0369a1; }

.md-quote {
  margin: 0 0 0.7em; padding-left: 0.9em;
  border-left: 2px solid #e2e8f0; color: #64748b;
}

.md-hr { margin: 1em 0; border: 0; border-top: 1px solid #e2e8f0; }

.md code {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.875em;
  background: #f1f5f9; color: #b45309;
  padding: 0.1em 0.35em; border-radius: 4px;
  overflow-wrap: anywhere;
}
.md-pre {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.8125em; line-height: 1.5;
  margin: 0 0 0.7em; padding: 0.7em 0.85em;
  background: #f8fafc; color: #334155;
  border: 1px solid #e2e8f0; border-radius: 8px;
  overflow-x: auto;
}

/* Wide content scrolls inside its own box; the page itself never does. */
.md-table-wrap { overflow-x: auto; margin: 0 0 0.7em; }
.md-table { border-collapse: collapse; font-size: 0.875em; }
.md-table th, .md-table td {
  border: 1px solid #e2e8f0; padding: 0.3em 0.6em;
  text-align: left; vertical-align: top;
  /* break-word rather than anywhere: the label column used to collapse to one
     character per line when an unbroken log line set the width. */
  overflow-wrap: break-word;
}
.md-table th { background: #f8fafc; font-weight: 600; white-space: nowrap; }
/* The first column is the label — an agency, an error, a route — and the one
   the eye scans. Give it a floor and let the wrapper scroll. */
.md-table th:first-child, .md-table td:first-child { min-width: 18ch; }

/* ---- charts ----
 *
 * SVG built by charts.js. Text in SVG takes no utility classes and does not
 * inherit Tailwind's reset, so the type is set here. */

.md-figure { margin: 0 0 0.7em; }
.md-figure-bar { display: flex; gap: 0.5rem; align-items: center; margin-bottom: 0.35rem; }

/* The chart toggle and its column picker. They carried a `ghost` class from the
   stylesheet this file replaced, and nothing has defined it since — so they
   rendered as browser-default controls in the middle of a styled page. */
.chart-toggle, .chart-pick {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 11px; line-height: 1.4;
  padding: 0.15em 0.5em;
  color: #64748b; background: #fff;
  border: 1px solid #cbd5e1; border-radius: 5px;
  cursor: pointer;
}
.chart-toggle:hover, .chart-pick:hover { color: #0f172a; border-color: #94a3b8; }

.chart { width: 100%; max-width: 680px; height: auto; display: block; }
.chart-bar { fill: #0284c7; }
/* A negative bar points the other way and must read as a different thing, not
   as a shorter version of the same one. */
.chart-bar.neg { fill: #94a3b8; }
.chart-zero { stroke: #cbd5e1; stroke-width: 1; }
.chart-label, .chart-value {
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 11.5px; dominant-baseline: middle;
}
.chart-label { text-anchor: end; fill: #64748b; }
.chart-value { text-anchor: end; fill: #334155; }

/* ---- printing ----
 *
 * The single-answer page exists partly to be printed (see answer.tmpl), and
 * these are the JS-built nodes that make no sense on paper: a control that
 * swaps a table for a chart is not a control any more once it is ink. */
@media print {
  .md-figure-bar { display: none; }
  .md-table-wrap { overflow-x: visible; }
}
