/*
 * Charts, with no charting library. A library would weigh more than the entire rest of the front
 * end and would invite chart types this data does not support: a smoothed line over a series whose
 * whole point is discontinuity, an area fill implying a quantity where there is a ratio.
 *
 * Everything with a continuous x-axis is server-rendered inline SVG. Everything that is a set of
 * magnitudes is CSS boxes with inline widths — the CSP permits inline style and blocks inline
 * script, which is exactly the right way round for this.
 */
.fig {
  margin: var(--s5) 0;
  padding: var(--s4);
}

.fig__head {
  display: flex;
  align-items: baseline;
  gap: var(--s3);
  margin-bottom: var(--s3);
}

.fig__ticker { font-size: 17px; font-weight: 600; color: var(--fg); }

.fig svg { width: 100%; height: auto; display: block; }

.fig__ground { fill: var(--panel-deep); }

/* The stall bands. Drawn first and full height: a long stall is a wide band you see before you read
   anything. Windows past the headline bar are stronger, so the six-hour threshold is visible
   without a legend. */
/*
 * ── THE STALLS MOVED OUT OF THE PLOT AND UNDER IT ───────────────────────────────────────────────
 *
 * These were full-height fills at 10% and 20% opacity. That reads as a mark while stalls are the
 * exception; measured on AAPLc they covered 77% of the frame, at which point the shading is not on
 * the chart, it IS the chart — a brown ground with a line lost in it.
 *
 * Solid, in a strip of its own, on a track that is visible when empty. Full strength because it no
 * longer sits behind anything: a stall is now the most saturated thing in the figure, which is what
 * the original full-height band was reaching for and could not have while it was translucent.
 */
.fig__ribbon-track { fill: var(--on-panel-4); fill-opacity: 0.25; }
.fig__stall { fill: var(--frozen); fill-opacity: 0.55; }
.fig__stall--long { fill-opacity: 1; }

.fig__zero { stroke: var(--fg-5); stroke-width: 1; }
.fig__guide { stroke: var(--fg-5); stroke-width: 1; stroke-dasharray: 3 4; opacity: 0.6; }

/* The alert threshold. Solid where the guides are dashed, in the breach hue, because it is the one
   horizontal here that means something outside this chart. */
.fig__alert { stroke: var(--breach); stroke-width: 1; opacity: 0.75; }

.fig__tick { fill: var(--fg-3); font: 500 10px var(--font-mono); letter-spacing: 0.08em; }

/* The line's colour reports feed state, so the state needs no legend. */
.fig__line { stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }
.fig__line--fresh { stroke: var(--live); }
.fig__line--stalled { stroke: var(--frozen); }

.fig__note {
  margin: var(--s3) 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--fg-2);
  max-width: var(--measure);
}

.fig__empty {
  padding: var(--s5) var(--s4);
  border: var(--hair) dashed var(--panel-rule);
  text-align: center;
}

.fig__foot {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s3);
  align-items: center;
  margin-top: var(--s4);
  padding-top: var(--s3);
  border-top: var(--hair) solid var(--panel-rule);
}

.fig__perma { color: var(--fg-3); }

/*
 * ── NARROW: A FLOOR AND A PAN, NOT A SHRINK ─────────────────────────────────────────────────────
 *
 * This block used to say "a chart gets SIMPLER at narrow widths, never smaller" and then do
 * nothing of the kind. The svg is a fixed viewBox at width:100%, so every tick label scaled down
 * with the frame: on a 390px phone the axis rendered at roughly four pixels.
 * `vector-effect="non-scaling-stroke"` protects STROKES. Nothing protects text, and raising
 * font-size does not help, because that size is in user units and scales too.
 *
 * So the plot keeps a legible floor and pans inside its own scroller. At 700px against a ~360px
 * content width the labels land near 9px instead of 4px. Same move as .well-block__body in
 * 10-base.css, which is the house pattern for content that cannot be made narrower without
 * becoming unreadable.
 */
.fig__plot { overflow-x: auto; }

@media (max-width: 720px) {
  .fig { padding: var(--s3); }
  .fig__line { stroke-width: 2.5; }
  .fig__tick { font-size: 13px; }
  .fig__plot svg { min-width: 700px; }
}

/*
 * ── THE FIGURE'S COUNTS ─────────────────────────────────────────────────────────────────────────
 *
 * Four figures on a hairline strip under the plot, in one block with it rather than in a header
 * above it. They are what the removed second series was for: the shape says WHEN the oracle was
 * silent, these say how much priced against it meanwhile.
 *
 * THE BOX IS CLOSED. It carried `border-top: 0` on the claim that it was welded to the bottom of
 * the plot — and it never was: `.fig` sets `margin: var(--s5) 0`, so the strip has always floated
 * 32px clear of the figure above it. The result was a rectangle with three sides, its left and
 * right rules running up to nothing. Either weld it or close it; closing it is the smaller change
 * and keeps the figure's own margin doing what every other block on the page relies on.
 *
 * IT WAS SIX, AND SIX READ AS A WALL. Two of them were the product's own claim stated as a
 * contrast — the average difference while the underlying market was open against the average while
 * it was closed — and a contrast set in the same type as four unrelated statistics is not read as
 * one. Those two are a sentence under the strip now, where the labels have room to say what "open"
 * and "closed" mean. They are still side by side and still never blended into one mean.
 *
 * Four divides evenly at every breakpoint, so no row is ever left with a single orphan cell.
 *
 * EVERY VALUE IS --fg. The two that used to carry --breach-ink and --frozen-ink were statistics,
 * not states: colour on a 30-day mean says a threshold was crossed when none was, and the red drew
 * the eye to the largest number rather than the relevant one.
 */
.figstats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--hair);
  background: var(--rule-soft);
  border: var(--hair) solid var(--rule-firm);
}
.figstats > div { background: var(--card); padding: 13px 15px; }
.figstats .label { display: block; margin-bottom: 6px; }
.figstats .datum { font: 500 19px/1.2 var(--font-mono); color: var(--fg); font-variant-numeric: tabular-nums; }

@media (max-width: 720px) { .figstats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/*
 * ── THE STACKED VENUE CHART ─────────────────────────────────────────────────────────────────────
 *
 * One hue stepped by lightness, not five hues. The four signal tokens each MEAN a feed state, so a
 * band borrowing one would read as a reading; and at five categorical hues an instrument turns into
 * a pie chart. Stepping --series-1..5 puts identity in POSITION rather than in colour, which is
 * what carries it through colour-blindness, greyscale print and a phone at low brightness. The
 * steps were contrast-checked against --panel-deep, which is this figure's ground in both themes.
 */
.fig__band--1 { fill: var(--series-1); }
.fig__band--2 { fill: var(--series-2); }
.fig__band--3 { fill: var(--series-3); }
.fig__band--4 { fill: var(--series-4); }
.fig__band--5 { fill: var(--series-5); }

/* The browser's own <title> hover needs no help, but a pointer cue makes it discoverable. */
.fig__band { cursor: help; }

.fig__range { color: var(--on-panel-3); font-size: 12px; margin-left: auto; }

/*
 * THE LEGEND IS NOT OPTIONAL. Identity is never colour alone, so it is always rendered for a
 * multi-series figure, and in stack order from the top band down so a reader walks it against the
 * chart rather than translating between two orders.
 *
 * It WRAPS rather than scrolling. The plot pans because its text cannot be made smaller without
 * becoming unreadable; the legend is real HTML text and reflows, so on a phone it becomes a short
 * list instead of a row that runs off the edge with the chart.
 */
.fig__legend {
  list-style: none;
  margin: var(--s3) 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) var(--s4);
}

/*
 * `min-width: 0` IS LOAD-BEARING, and its absence broke the whole page rather than this component.
 *
 * A flex item defaults to `min-width: auto`, so it refuses to shrink below its content. The
 * rolled-up band's note is a comma list of six ticker keys, which made this item about 480px wide
 * and unshrinkable. It pushed .fig wider than .container, which pushed the DOCUMENT wider than a
 * 390px viewport: every paragraph on the post clipped mid-sentence and the nav stopped wrapping.
 *
 * The plot next to it survives that because it pans inside its own scroller. This is real text and
 * has to reflow instead, so the item wraps internally and the note breaks where it must.
 */
.fig__legend-item {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  min-width: 0;
  gap: var(--s2);
  font-size: 12px;
  color: var(--on-panel-2);
}

.fig__swatch {
  width: 10px;
  height: 10px;
  flex: 0 0 auto;
  /* Square. The design has exactly one radius and it is zero, and spec/design_system_spec.rb says
     so; a rounded swatch beside square bars would also be lying about the mark it stands for. */
  /* Baseline-aligned with the label beside it rather than centred on the line box, so a wrapped
     legend keeps its swatches on the text's baseline grid. */
  transform: translateY(1px);
}

.fig__swatch--1 { background: var(--series-1); }
.fig__swatch--2 { background: var(--series-2); }
.fig__swatch--3 { background: var(--series-3); }
.fig__swatch--4 { background: var(--series-4); }
.fig__swatch--5 { background: var(--series-5); }

.fig__legend-label { font-family: var(--font-mono); letter-spacing: 0.02em; }

/* A rolled-up band names its members on its own line, under the legend. Inline it read as six
   tickers belonging to one square while four other squares sat beside it, so the square count and
   the ticker count disagreed. The swatch repeats here to say which band the list belongs to. */
.fig__members {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--s2);
  margin: var(--s2) 0 0;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--on-panel-3);
  overflow-wrap: anywhere;
}

@media (max-width: 720px) {
  /* The stack needs less width than the divergence plot: its x-axis is 26 bars rather than 900
     path commands, and its labels are dates rather than signed basis points. */
  .fig--growth .fig__plot svg { min-width: 560px; }
  .fig__range { margin-left: 0; width: 100%; }
  .fig__head { flex-wrap: wrap; }
  .fig__legend { gap: var(--s2) var(--s3); }
}
