/* Data ingestion.
 *
 * Rides on performance.css for the palette, header, bands and tiles, and on
 * network.css for the eyebrow, hero stats, tables and caveats -- this is a page
 * on that site, not a second product. Everything here is what neither of those
 * has a concept of: the cadence cards, the two SVG figures and the poll steps.
 *
 * The SVGs are styled here rather than inline so they follow the palette into
 * dark mode. Anything that carries meaning -- a live lane, a stale rollup -- is
 * given a word as well as a colour, the same rule the rest of the site holds
 * to: the warning yellow sits below 3:1 on the light surface.
 */

.viz-root {
  --lane-live: var(--brand-orange);
  --lane-quiet: var(--text-muted);
}

.quiet { color: var(--text-muted); font-size: 13px; }

/* ---------- Cadence cards ---------- */

.clocks {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 12px;
}

.clock {
  background: var(--page);
  border: 1px solid var(--border);
  border-top: 3px solid var(--brand-orange);
  border-radius: var(--radius);
  padding: 16px 18px 18px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.band.alt .clock { background: var(--surface-1); }

.clock-rate {
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}

.clock-what {
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--text-secondary);
}

.clock-who {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 12px;
  color: var(--text-muted);
  overflow-wrap: anywhere;
}

/* ---------- Figures ---------- */

.diagram-wrap,
.chart-wrap,
.chain-wrap {
  margin-top: 18px;
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface-1);
  padding: 14px;
}

.band.alt .diagram-wrap,
.band.alt .chain-wrap { background: var(--page); }

#flow-diagram { width: 100%; min-width: 660px; height: auto; display: block; }
#hourly-chart { width: 100%; min-width: 560px; height: 250px; display: block; }
#chain-diagram { width: 100%; min-width: 560px; height: auto; display: block; }
/* Wider than the others: it carries five boxes and two lanes, and shrinking
   it to a phone's width put the labels at three pixels. It scrolls instead. */
#swap-diagram { width: 100%; min-width: 780px; height: auto; display: block; }

/* Shared SVG furniture. */

.grid-line { stroke: var(--grid); stroke-width: 1; }

.axis-text {
  fill: var(--text-muted);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

.bar { fill: var(--brand-orange); }
.bar.night { fill: var(--text-muted); }

/* Flow diagram. */

.node {
  fill: var(--surface-1);
  stroke: var(--text-secondary);
  stroke-width: 1.5;
}

.band.alt .node { fill: var(--page); }

.node.live { stroke: var(--lane-live); stroke-width: 2; }
.node.reference { stroke-dasharray: 5 4; stroke: var(--lane-quiet); }

.node-title {
  fill: var(--text-primary);
  font-size: 13px;
  font-weight: 600;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

.node-sub { fill: var(--text-secondary); font-size: 11.5px; }
.node-figure { fill: var(--text-primary); font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; }

.lane { stroke: var(--text-secondary); stroke-width: 1.5; fill: none; }
.lane.live { stroke: var(--lane-live); stroke-width: 2; }
.lane.reference { stroke: var(--lane-quiet); stroke-dasharray: 5 4; }

.lane-label { fill: var(--text-secondary); font-size: 11px; }
.lane-label.live { fill: var(--lane-live); }

.legend { fill: var(--text-muted); font-size: 11.5px; }

/* Schema map.
 *
 * Same furniture as the flow diagram -- panels take the .node treatment, joins
 * take the .lane treatment -- so the two figures read as one page. What is new
 * here is the bar: thirty-nine tables spanning five orders of magnitude on
 * disk, which only fits on a log scale, so the bar is deliberately plain and
 * the scale is stated in the legend rather than implied by the drawing.
 */

#schema-diagram { width: 100%; min-width: 760px; height: auto; display: block; }

.fam {
  fill: var(--surface-1);
  stroke: var(--text-secondary);
  stroke-width: 1.5;
}

.band.alt .fam { fill: var(--page); }

.fam-live { stroke: var(--lane-live); stroke-width: 2; }
.fam-reference { stroke: var(--lane-quiet); stroke-dasharray: 5 4; }
.fam-quiet { stroke: var(--lane-quiet); }

.fam-title {
  fill: var(--text-primary);
  font-size: 13px;
  font-weight: 700;
}

.fam-figure {
  fill: var(--text-secondary);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
}

.fam-note { fill: var(--text-muted); font-size: 11px; }

.tbl-name {
  fill: var(--text-primary);
  font-size: 11.5px;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

/* A table this page names and the database does not have. Struck through and
 * labelled "absent" rather than dropped, because a diagram going out of date
 * silently is the failure worth designing against. */
.tbl-name.is-missing {
  fill: var(--text-muted);
  text-decoration: line-through;
}

.tbl-size {
  fill: var(--text-secondary);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

.tbl-bar { fill: var(--text-muted); opacity: 0.55; }
.tbl-live { fill: var(--lane-live); opacity: 0.8; }
.tbl-derived { fill: var(--text-secondary); opacity: 0.7; }

.join { stroke: var(--text-secondary); stroke-width: 1.5; fill: none; }
.join-fk { stroke: var(--lane-live); stroke-width: 2; }
.join-spatial { stroke: var(--text-muted); stroke-dasharray: 2 4; }

/* Haloed against the surface, so a key that has to sit near a panel edge or
 * cross a join is still readable rather than tangled into it. */
.join-key {
  fill: var(--text-secondary);
  font-size: 11px;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  paint-order: stroke;
  stroke: var(--surface-1);
  stroke-width: 3px;
  stroke-linejoin: round;
}

.band.alt .join-key { stroke: var(--page); }

.join-key.join-spatial { fill: var(--text-muted); font-family: inherit; }

/* Chain timeline. */

.chain-axis { stroke: var(--text-secondary); stroke-width: 1.4; }
.chain-tick { stroke: var(--text-secondary); stroke-width: 1.5; }
.chain-time { fill: var(--text-primary); font-size: 12.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.chain-table { fill: var(--text-secondary); font-size: 11.5px; font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; }
.chain-mark { fill: var(--brand-orange); }
.chain-note { fill: var(--brand-orange); font-size: 11.5px; }
.chain-bracket { stroke: var(--text-muted); stroke-width: 1.2; fill: none; }

/* ---------- Poll steps ---------- */

ol.steps {
  list-style: none;
  counter-reset: step;
  margin: 18px 0 0;
  padding: 0;
  display: grid;
  gap: 10px;
}

ol.steps > li {
  counter-increment: step;
  display: grid;
  grid-template-columns: 30px 1fr;
  gap: 12px;
  align-items: baseline;
  font-size: 14px;
  line-height: 1.6;
  color: var(--text-secondary);
}

ol.steps > li::before {
  content: counter(step, decimal-leading-zero);
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--brand-orange);
  font-variant-numeric: tabular-nums;
}

ol.steps strong { color: var(--text-primary); font-weight: 600; }

/* ---------- How the match resolves ---------- */

/* One bar and three keyed rows. Colour is never the only carrier -- each row
 * states its own share and its own cause in words, so the bar is a summary of
 * something already written down rather than a legend to decode. */

.split {
  margin: 18px 0 0;
  background: var(--page);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 18px 18px;
}

.band.alt .split { background: var(--surface-1); }

.split-bar {
  display: flex;
  height: 12px;
  border-radius: 6px;
  overflow: hidden;
  background: var(--grid);
}

/* Hairlines between segments rather than gaps: the three shares sum to the
 * whole, and a gap would draw a fourth thing that does not exist. */
.split-seg + .split-seg { box-shadow: inset 1px 0 0 var(--page); }

.split-resolved { background: var(--series-1); }
.split-drift { background: var(--brand-orange); }
.split-blind { background: var(--text-muted); }

.split-keys {
  margin: 14px 0 0;
  display: grid;
  gap: 11px;
}

.split-key {
  display: grid;
  grid-template-columns: 10px 1fr;
  gap: 11px;
  align-items: baseline;
}

.split-dot {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  align-self: center;
}

.split-head {
  font-size: 14px;
  color: var(--text-secondary);
  line-height: 1.5;
}

.split-head strong {
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.split-note {
  margin: 2px 0 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--text-muted);
}

/* ---------- The two landing tables ---------- */

.pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 14px;
}

.landing {
  background: var(--page);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 20px 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.landing-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
}

.landing-head h3 {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
}

.landing-figure {
  font-size: 27px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
  font-variant-numeric: tabular-nums;
}

.landing-figure-note { font-size: 12.5px; color: var(--text-muted); margin-top: -4px; }

.landing ul {
  margin: 0;
  padding-left: 18px;
  display: grid;
  gap: 7px;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--text-secondary);
}

/* ---------- Limits ---------- */

.limits {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 14px;
}

.limit {
  border-left: 3px solid var(--status-critical);
  background: var(--chip);
  border-radius: 0 8px 8px 0;
  padding: 14px 16px;
}

.limit h3 {
  margin: 0 0 6px;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--text-primary);
}

.limit p {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--text-secondary);
}

/* performance.css sizes .dot as a flex item. In a table cell it is a plain
   inline span, where width and height do not apply and it collapses to
   nothing -- so it needs laying out here. */
/* ---------- The BODS-or-a-description comparison ---------- */

/* The shared table style sets white-space: nowrap, which is right for the
   inventory above (short cells, and a wrapped row count is unreadable) and
   badly wrong here: these cells are sentences, and nowrap turns the table
   into a two-metre horizontal scroll. */
#swap-table th,
#swap-table td {
  white-space: normal;
  vertical-align: top;
  line-height: 1.45;
}

#swap-table td { color: var(--text-secondary); }

/* The row label is a th, so it reads as the row's header to a screen reader
   as well as looking like one. thead's uppercase treatment is scoped to
   thead, so this only needs the weight putting back. */
#swap-table th.swap-label {
  width: 19%;
  min-width: 132px;
  color: var(--text-primary);
  font-weight: 600;
}

#swap-table thead th:nth-child(2),
#swap-table thead th:nth-child(3) { width: 40.5%; }

/* The column that describes what runs today, marked the same way the solid
   lane is marked in the diagram above it. */
#swap-table tbody td:first-of-type {
  box-shadow: inset 2px 0 0 var(--lane-live);
}

/* On a phone, three columns of prose in 390px is one word per line. The row
   becomes a card instead: the label as its heading, then the two answers
   stacked and each named by the column header it came from. */
@media (max-width: 720px) {
  #swap-table thead { display: none; }
  #swap-table,
  #swap-table tbody,
  #swap-table tr,
  #swap-table th,
  #swap-table td { display: block; width: auto; }

  #swap-table tbody tr {
    border-bottom: 1px solid var(--border);
    padding: 4px 0 10px;
  }
  #swap-table tbody tr:last-child { border-bottom: none; }

  #swap-table th.swap-label {
    width: auto;
    min-width: 0;
    border-bottom: none;
    padding-bottom: 2px;
    font-size: 14px;
  }

  #swap-table tbody td {
    border-bottom: none;
    padding: 4px 14px 4px 26px;
    font-size: 13px;
  }
  #swap-table tbody td:first-of-type { box-shadow: none; }

  /* Which column this answer is, since the header row is gone. */
  #swap-table tbody td::before {
    content: attr(data-col);
    display: block;
    margin-left: -12px;
    font-size: 11px;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--text-muted);
  }
  #swap-table tbody td:first-of-type::before { color: var(--lane-live); }
}

table.data .dot {
  display: inline-block;
  vertical-align: baseline;
  margin-right: 7px;
}

/* ---------- Inline code ---------- */

code {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.92em;
  background: var(--chip);
  padding: 0.08em 0.36em;
  border-radius: 3px;
}

/* ---------- Freshness ---------- */

.tick[data-stale="1"] { color: var(--status-critical); }

@media (max-width: 620px) {
  .clock-rate { font-size: 21px; }
}

/* Scope switch -----------------------------------------------------------
   Two buttons rather than a dropdown: there are two answers, and the one you
   are not looking at should be one click away and visibly available. */
.scope-switch {
  display: inline-flex;
  gap: 2px;
  margin: 14px 0 4px;
  padding: 3px;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.06);
}

.scope-btn {
  appearance: none;
  border: 0;
  cursor: pointer;
  padding: 7px 16px;
  border-radius: 999px;
  background: transparent;
  color: var(--ink-soft, #4b5563);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  transition: background 140ms ease, color 140ms ease;
}

.scope-btn:hover {
  color: var(--ink, #111827);
}

.scope-btn.is-on {
  background: var(--card, #ffffff);
  color: var(--ink, #111827);
  box-shadow: 0 1px 3px rgba(15, 23, 42, 0.16);
}

.scope-test {
  margin: 2px 0 0;
  font-size: 12.5px;
  color: var(--ink-soft, #4b5563);
}
