/* ICP.SUPPLY colour tokens. The only file that may declare a colour value —
   no hex, rgb(), hsl() or named colour lives anywhere else. */

/* Layer 1 is two anchors; everything derives from them with color-mix. The
   literals are fallbacks, never independent tuning points. */

/* Contrast over --ink-glow..--ink: primary 13.3:1, secondary 9.6:1. Body text
   needs 4.5:1. Anything below secondary is structural only. */

:root {
  /* Layer 1: anchors and fallbacks. Never referenced by a component. */
  --primary-green: #2cff05;
  --ink: #000703;
  --secondary-green: #25da05;
  --ink-glow: #041b03;

  /* Layer 2: semantic roles, the only layer a component may consume. PRIMARY
     is top-level rows and accents, SECONDARY nested rows and support. */

  /* SECONDARY is PRIMARY dimmed toward the background, so role hierarchy and
     luminance ramp move together. */

  --bg: var(--ink);
  --bg-gradient: radial-gradient(
    ellipse 90% 60% at 50% 0%,
    var(--ink-glow) 0%,
    var(--ink) 70%
  );

  /* --text-faint is barred from text: hairlines, borders, bar tracks and
     inactive carets only. */
  --text-primary: var(--primary-green); /* 13.3:1–14.9:1 */
  --text-secondary: var(--secondary-green); /* 9.6:1–10.7:1 */
  --text-muted: var(--secondary-green); /* 9.6:1–10.7:1 */
  --text-faint: #157c04;

  /* The one element per view that must be seen first. */
  --accent: var(--primary-green);

  /* Named for what a number is worth, not how loud its copy is: a total and a
     percentage in one row rank without a shared token. */
  --value-emphasis: var(--primary-green); /* totals, headline figures */
  --value-normal: var(--secondary-green);
  --value-derived: var(--secondary-green); /* percentages, secondary columns */

  /* The only thing separating one surface from another; there are no panel
     fills. Takes --text-faint so chrome cannot drift apart. */
  --rule: var(--text-faint);

  /* The one raised surface, where a hairline cannot do the job alone. 10% of
     primary into ink is the ceiling; always paired with --rule. */
  --surface-raised: #042003;

  /* SHARE BAR. Burn and mint take the two colour roles, backed by a NON-COLOUR
     CUE — see `.stats-bar-mint`. */
  --bar-burn: var(--primary-green);
  --bar-mint: var(--secondary-green);

  --focus-ring: var(--primary-green);

  /* Glow. Every stage derives from PRIMARY. */
  --glow-core: var(--primary-green);
  --glow-mid: var(--secondary-green);
  --glow-outer: #0f5e04;

  /* Matrix rain. Canvas cannot read a stylesheet, so the renderer resolves these
     through a CSS `color` property first. */
  --rain-ink: var(--primary-green);
  --rain-head: #c0ffb4;
  --rain-bloom-core: #188f04;
  --rain-bloom-halo: #0f5e04;
}

/* Gated as one group: custom properties accept any token stream, so an
   unsupported color-mix would override a valid fallback and fail at use. */
@supports (color: color-mix(in srgb, currentColor 50%, transparent)) {
  :root {
    --secondary-green: color-mix(
      in srgb,
      var(--primary-green) 85%,
      var(--ink)
    );
    --ink-glow: color-mix(in srgb, var(--primary-green) 8%, var(--ink));
    --text-faint: color-mix(in srgb, var(--primary-green) 47%, var(--ink));
    --surface-raised: color-mix(
      in srgb,
      var(--primary-green) 10%,
      var(--ink)
    );
    --glow-outer: color-mix(
      in srgb,
      var(--primary-green) 35%,
      var(--ink)
    );
    --rain-head: color-mix(in srgb, var(--primary-green) 30%, white);
    --rain-bloom-core: color-mix(
      in srgb,
      var(--primary-green) 55%,
      var(--ink)
    );
    --rain-bloom-halo: color-mix(
      in srgb,
      var(--primary-green) 35%,
      var(--ink)
    );
  }
}


/* ---- GLOBAL FRAME ---- */

/* `color` is not decorative: without it the root keeps the UA's black and
   anything outside `.icp-terminal` paints black on near-black. */
/* `overflow: hidden` only keeps a second, document-level scrollbar from
   appearing behind `.icp-terminal`, which is the real scroll container. */
html,
body,
.matrix-fx-enabled {
  height: 100%;
  margin: 0;
  overflow: hidden;
  color: var(--text-secondary);
}

body {
  background: var(--bg-gradient);
}

.visually-hidden {
  position: absolute;
  width: 0.0625em;
  height: 0.0625em;
  overflow: hidden;
  white-space: nowrap;
}


/* ---- TERMINAL ---- */

/* The terminal establishes the container-driven base size used by STATS and
   the surrounding chrome. DATA applies one declared multiplier of that base;
   every component length remains relative to one of those two scales. */

/* NO COLOURS HERE — only semantic tokens from the top of the file. A missing
   role is added there, never inlined at the call site. */

/* Hue cannot distinguish a category here, so anything that leaned on it carries
   a non-colour cue, commented where it is applied. */

/* Outside matrix-fx there is no opacity and no alpha: a value is subordinate
   by tier, never by being a faded copy. */
.icp-terminal {
  /* STATS and the calculator retain the compact base panel. DATA keeps one
     physical measure while its narrow context spends that width on larger type. */
  --panel-width: 46ch;
  --data-grid: 19ch 13ch 14ch;
  --metrics-panel-width: 44.4ch;
  --metrics-grid: 20.4ch 13.2ch 10.8ch;
  --stats-window-width: 5ch;
  --stats-price-width: 11ch;
  --stats-burn-width: 9ch;
  --stats-mint-width: 13ch;
  --stats-ratio-width: 8ch;
  --row-height: 1.42em;
  --font-size-large: 1.4118em;
  --font-size-small: 1em;
  position: relative;
  isolation: isolate;
  background-color: transparent;
  color: var(--text-secondary);
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas,
    "Liberation Mono", Menlo, Monaco, "Courier New", monospace;
  font-size: clamp(0.625em, 3.35cqi, 1.6em);
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100vh;
  height: 100dvh;
  /* `auto`, not `hidden`: the scale guarantees a horizontal fit at the
     maintained narrow viewport and
     above, so if that axis engages it is a bug and must be visible. */
  overflow-x: auto;
  /* The vertical axis is ordinary scrolling and always was allowed to be: the
     dashboard is as tall as its open state makes it, and the scale no longer
     shrinks to avoid this bar. */
  overflow-y: auto;
  /* Reserving the gutter unconditionally keeps an expand from reflowing the
     column when the vertical bar appears. */
  scrollbar-gutter: stable;
  /* The legend's index jumps inside this box. Smoothing the jump is what says
     the reader moved down the same list rather than into a new view, and it is
     the only scroll on the page a control starts. */
  scroll-behavior: smooth;
  /* The title starts close to the terminal edge; the larger trailing inset still
     keeps the footer clear of the scrollport edge. */
  padding-block: 0.4412em 0.9em;
  padding-inline: 0;
  box-sizing: border-box;
}

.icp-terminal * {
  box-sizing: border-box;
}

/* An observer target, not visible content. Absolute positioning gives it no
   height in the terminal while its full width makes only vertical scrolling
   able to take it out of the scrollport. */
.icp-scroll-origin {
  position: absolute;
  inset: 0 0 auto;
  height: 0.0625em;
  pointer-events: none;
}

/* Stacking over the rain comes from `.matrix-fx-layer`'s negative `z-index`
   inside this element's `isolation: isolate`, not from the `1` here. */
.icp-content {
  position: relative;
  z-index: 1;
  inline-size: var(--panel-width);
  margin-inline: auto;
  /* The terminal is a 100dvh column flex container and this column is routinely
     taller than it. Shrinking would compress the page instead of scrolling it —
     the automatic minimum size already prevents that, but this is the property
     the behaviour actually depends on. */
  flex-shrink: 0;
}

.icp-header {
  text-align: center;
  /* The title and tagline occupy consecutive lines; one SMALL line separates
     that shared header slot from STATS. */
  margin-bottom: 1em;
}

.icp-title {
  display: inline-block;
  /* The only type-size exception: exactly 10% above LARGE. */
  font-size: calc(1.1 * var(--font-size-large));
  font-weight: 700;
  line-height: 0.9;
  letter-spacing: -0.03em;
  margin: 0;
  color: var(--accent);
}

/* `line-height: 1` is load-bearing: header gaps are authored between the INK
   of one line and the next; `normal` leading adds ~2u. */
.icp-subtitle {
  display: block;
  font-size: var(--font-size-small);
  font-weight: 400;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--text-secondary);
  margin: 0;
}

/* The skip prompt takes the accent so it reads as live against the subtitle's
   SECONDARY tier. */
/* PROMPT AND TAGLINE SHARE THE SLOT: `fx.js` holds `matrix-fx-decoding` for as
   long as there is an entrance to skip. */
.icp-skip-prompt {
  color: var(--accent);
}

/* With no script the class never arrives and the tagline is simply the
   subtitle. */
.matrix-fx-enabled .icp-skip-prompt {
  display: none;
}

.matrix-fx-enabled.matrix-fx-decoding .icp-skip-prompt {
  display: inline-block;
}

.matrix-fx-decoding .icp-tagline-control {
  display: none;
}

.icp-tagline {
  color: var(--accent);
}

.icp-tagline-control {
  padding: 0;
  border: 0;
  color: inherit;
  background: transparent;
  font: inherit;
  letter-spacing: inherit;
  text-shadow: inherit;
  cursor: pointer;
}

.icp-tagline-control:focus-visible {
  outline: 0.0625em solid var(--focus-ring);
  outline-offset: 0.0735em;
}

.icp-tagline-control:disabled {
  cursor: default;
}

/* Supporting copy: it is text, so it stops at --text-muted and never takes
   --text-faint. */
/* The snapshot stamp shares the `Legend_` row with the control, so the cell is
   the anchor and the text hangs off its right edge. */
/* ABSOLUTE, SO IT COSTS NO WIDTH. `table-layout: auto` measures every cell,
   and this line is wider than the two figure columns it spans — left in flow it
   would widen them, narrow the label column and reflow the whole table around a
   line that is only annotating it. Out of flow it measures zero, so DATA's
   columns are exactly what they were before the row existed. */
.cell-snapshot {
  position: relative;
  grid-column: 2 / 4;
}

.cell-snapshot > .fx-scramble {
  position: absolute;
  right: 0;
  bottom: 0;
  color: var(--text-muted);
  /* The stamp annotates DATA but is not a metric. Its narrow-context override
     below cancels the ledger multiplier so it always stays at the base size. */
  font-size: 1em;
  font-style: italic;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  line-height: 1;
  white-space: nowrap;
}

/* Nothing but the status lives here now, and it is empty in the ordinary case:
   no reserve, no positioning, no margin of its own. The gap above the footer is
   the footer's. */
.snapshot-status-slot {
  margin-top: 0.4044em;
}

/* STATS and lower DATA use one stable-height-aware unit. LEGEND consumes the
   same unit, so corresponding roles are the same size in either mode. The
   controls row is a sibling of `.legend-view`, hence its explicit place in this
   list. Re-declaring both sizes is necessary because inherited custom
   properties were resolved against the ancestor's base unit. */
.metrics-rows,
.legend-view,
.legend-controls,
.snapshot-status-slot,
.icp-canister-support,
.icp-footer {
  --font-size-large: 1.4118em;
  --font-size-small: 1em;
}

/* STATS is the deliberate exception to DATA's label | value | percent grid:
   its peer metrics compare across five fixed columns. Native table layout keeps
   those column centres stable while the one terminal font size scales them. */
.stats-table {
  inline-size: var(--panel-width);
  margin-inline: auto;
  border-collapse: collapse;
  border-spacing: 0;
  table-layout: fixed;
  color: var(--value-emphasis);
  font-variant-numeric: tabular-nums;
  text-shadow: none;
}

.stats-col-window {
  inline-size: var(--stats-window-width);
}

.stats-col-price {
  inline-size: var(--stats-price-width);
}

.stats-col-burn {
  inline-size: var(--stats-burn-width);
}

.stats-col-mint {
  inline-size: var(--stats-mint-width);
}

.stats-col-ratio {
  inline-size: var(--stats-ratio-width);
}

/* Every visible band consumes the shared row rhythm; the footer fits its bar
   and captions inside the same measure. */
.stats-table thead tr,
.stats-primary-row,
.stats-support-row,
.stats-share-row {
  block-size: var(--row-height);
}

.stats-table th,
.stats-table td {
  min-inline-size: 0;
  padding: 0;
  text-align: center;
  vertical-align: middle;
  white-space: nowrap;
  line-height: 1;
}

.stats-label {
  /* Scramble width reservation must match this tracking exactly. */
  --matrix-scramble-tracking: 0.11em;
  color: var(--text-muted);
  font-size: var(--font-size-small);
  font-weight: 700;
  letter-spacing: 0.11em;
}

.stats-primary-value,
.stats-period-value {
  color: var(--value-emphasis);
  /* STATS and DATA figures share one reading size; columns and weight carry the
     comparison hierarchy here. */
  font-size: var(--font-size-small);
  font-weight: 600;
  letter-spacing: -0.03em;
}

.stats-period-value {
  min-inline-size: 3ch;
  letter-spacing: -0.02em;
}

.stats-support-value,
.stats-window-support {
  color: var(--text-muted);
  font-size: var(--font-size-small);
  font-weight: 700;
  letter-spacing: -0.03em;
}

/* Direction/period and figure align locally inside their own table cell. They
   never participate in the five table columns. */
.stats-comparison-main,
.stats-comparison-support {
  display: inline-grid;
  grid-template-columns: max-content max-content;
  align-items: baseline;
  column-gap: 0.25ch;
}

.stats-comparison-main > :first-child,
.stats-comparison-support > :first-child {
  justify-self: end;
}

.stats-comparison-support strong {
  color: inherit;
  font-weight: inherit;
}

.stats-comparison-direction {
  color: var(--text-muted);
  font-size: inherit;
  font-weight: 700;
  line-height: 1;
}

/* NON-COLOUR CUE — NEGATIVE VS POSITIVE. The arrow glyph carries direction,
   so both states take the same SECONDARY tier. */
.stats-comparison-direction.negative {
  color: var(--text-muted);
}

.stats-period-arrow {
  position: relative;
  margin-inline: auto;
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  cursor: pointer;
  color: var(--text-muted);
}

/* CSS triangles scale with the inherited type instead of carrying a font's
   glyph metrics. */
.stats-period-arrow::before {
  content: "";
  display: block;
  inline-size: 0;
  block-size: 0;
  margin-inline: auto;
  border-inline: 0.34em solid transparent;
}

.stats-period-up::before {
  border-bottom: 0.38em solid currentColor;
}

.stats-period-down::before {
  border-top: 0.38em solid currentColor;
}

/* The overlay enlarges the control without changing its table row. */
.stats-period-arrow::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  inline-size: 1.5em;
  block-size: 1.5em;
}

.stats-period-arrow:hover,
.stats-period-arrow:focus-visible {
  color: var(--accent);
}

.stats-primary-row .stats-burn,
.stats-share-captions .stats-burn {
  color: var(--value-emphasis);
}

/* The burn figure and its share caption start from their reading edge; the mint
   side keeps the opposite edge, making the bar's two ends explicit. */
.stats-primary-row .stats-burn,
.stats-support-row .stats-burn,
.stats-share-captions .stats-burn {
  text-align: left;
}

/* Mint is one full tier below burn everywhere — column, bar segment, caption —
   so the split survives at caption size. */
/* The captions carry the non-colour cue for free: they read `burn share` and
   `mint share`. */
.stats-mint {
  color: var(--value-normal);
}

.stats-ratio {
  color: var(--value-emphasis);
}

/* The bar keeps the STATS BLOCK's full width; the compact DATA TABLE above it
   is centred independently. */
.stats-bar {
  display: flex;
  inline-size: var(--panel-width);
  block-size: 0.22em;
  margin: 0;
  overflow: hidden;
  border-radius: 0.0735em;
}

/* NON-COLOUR CUE — BURN VS MINT. Separated twice: by colour role and by
   TEXTURE — burn solid, mint a 135° hatch over --bg. */
/* Texture is the only cue that fits this narrow bar: a glyph has nowhere to sit, and an
   outline is almost all edge and reads as a dimmer fill. */
/* A hatch survives this height, a sliver-width segment, greyscale printing and
   monochromacy. */
.stats-bar-burn {
  background: var(--bar-burn);
}

.stats-bar-mint {
  background: repeating-linear-gradient(
    135deg,
    var(--bar-mint) 0 0.0735em,
    var(--bg) 0.0735em 0.1471em
  );
}

/* Two fixed halves anchor the captions to the panel edges without flex
   distribution. */
.stats-share-captions {
  --matrix-scramble-tracking: 0.04em;
  display: grid;
  grid-template-columns: 1fr 1fr;
  inline-size: var(--panel-width);
  margin-top: 0.0735em;
  /* SMALL, like the STATS labels: these captions name the two sides of the bar
     above them, so they read at the same rank as `BURNED`. */
  font-size: var(--font-size-small);
  font-weight: 500;
  letter-spacing: 0.04em;
  line-height: 1;
  text-shadow: none;
}

/* Mint holds the shared right edge; the tracking reservation above keeps its
   scrambled-text box wide enough for every tracked glyph. */
.stats-share-captions .stats-mint {
  color: var(--value-normal);
  text-align: right;
}

/* YTD TYPE STYLES ARE DELIBERATELY ABSENT: those figures are ordinary rows
   of the supply group, so their type IS the supply rows'. */
/* INFLATION and REWARDS carry no bar: node payments are already inside supply
   inflation, and granted maturity may never be spawned. */
/* Nesting is claimed only for the reward legs, which do sum. Every percentage
   here is against the 1 January supply. */

/* STATS has no width breakpoint: it inherits the terminal scale. */

/* Non-text graphics must not bypass the blank headline entrance frame — neither
   the bar nor the stepper's arrows decode. */
.stats-table:has(.stats-period-value .matrix-fx-scramble[data-phase="waiting"])
  .stats-bar,
.stats-table:has(.stats-period-value .matrix-fx-scramble[data-phase="waiting"])
  .stats-period-arrow {
  visibility: hidden;
}

/* Keyed on `matrix-fx-ready`, which only `fx.js` adds: the reveal holds the
   title at opacity 0 for 42%, blanking a script-less page. */
.matrix-fx-ready .icp-title {
  animation: icp-title-reveal var(--matrix-title-surge-duration) ease-out both;
}

/* IN FLOW, AND EMPTY MOST OF THE TIME. It used to be absolutely positioned on
   top of the metadata line, which was the reserve that kept the page from
   moving when a warning appeared or cleared. That line is a table cell now, so
   there is nothing to cover: an empty <output> has no line box and costs no
   height, and the one case that does show text is a partial snapshot, where a
   line above the footer is exactly what should appear. */
.icp-status {
  /* It is an <output>, which is inline by default. */
  display: block;
  text-align: center;
  /* Supporting copy, so it takes the supporting-copy size. */
  font-size: var(--font-size-small);
  line-height: 1;
  color: var(--text-secondary);
  margin: 0;
  overflow-wrap: anywhere;
}

/* The copy distinguishes file errors from loading; PRIMARY reinforces them. */
.icp-status.error {
  color: var(--accent);
  text-shadow: none;
}

/* ---- Metrics table ---- */
.metrics-table {
  inline-size: var(--panel-width);
  margin-inline: auto;
  border-collapse: separate;
  border-spacing: 0;
  table-layout: auto;
}

#icp-supply-table {
  inline-size: var(--metrics-panel-width);
  font-size: 1em;
}

.metrics-table tbody {
  display: block;
}

.metrics-rows tr:is(.row-level-0, .row-level-1, .row-level-2),
.calculator-summary-row,
.calculator-ladder tr {
  display: grid;
  block-size: var(--row-height);
  align-items: baseline;
}

.metrics-rows tr:is(.row-level-0, .row-level-1, .row-level-2) {
  grid-template-columns: var(--metrics-grid);
}

.calculator-summary-row,
.calculator-ladder tr {
  grid-template-columns: var(--data-grid);
}

.metrics-section-divider,
.calculator-ladder tr.calculator-break-even {
  display: grid;
  align-items: center;
}

.metrics-section-divider {
  grid-template-columns: var(--metrics-grid);
}

.calculator-ladder tr.calculator-break-even {
  grid-template-columns: var(--data-grid);
}

.metrics-section-divider {
  block-size: var(--row-height);
}

.calculator-ladder tr.calculator-break-even {
  block-size: calc(2 * var(--row-height));
}

.metrics-section-divider > :only-child,
.calculator-ladder tr.calculator-break-even > :only-child {
  grid-column: 1 / -1;
}

.metrics-table > caption,
.metrics-table-head {
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
}

.metrics-table th,
.metrics-table td {
  min-inline-size: 0;
  padding: 0;
  white-space: nowrap;
  vertical-align: baseline;
}

/* The global scramble box reserves 1.2 leading for free-flowing text. Inside
   the table it would silently restore that loose leading and defeat the shared
   tight row rhythm even after the cell itself was set to one line. */
.stats-table .matrix-fx-scramble,
.metrics-table .matrix-fx-scramble {
  line-height: 1;
}

/* Each section boundary is its own decorative row, so equal rules can frame a
   centred label without changing the data columns. */
/* The rows always reserve their space; only the ink waits for the next
   section's entrance slot, so no divider appears on the blank boot frame. */
.metrics-table .metrics-section-divider td {
  padding: 0 0.1471em;
}

.metrics-section-rule {
  display: flex;
  align-items: center;
  gap: 0.4412em;
}

.metrics-section-rule::before,
.metrics-section-rule::after {
  content: "";
  flex: 1;
  border-top: 0.0625em solid var(--rule);
}

/* TRACKING PUTS A SPACE AFTER THE LAST GLYPH, and the box is sized around it —
   so the ink sits 0.18em left of centre in its own box while flex centres the
   box, and the rule on the right ends up that much nearer the text than the one
   on the left. Taking the trailing space back off the margin makes the box the
   width of the ink, which is the only way the two gaps come out equal at every
   size. `text-indent: 0.18em` was the old correction and moved the text by the
   whole trailing space instead of half of it, which put the ink flush against
   the right edge — the same fault, doubled. */
.metrics-section-label {
  /* `fx.js` reserves `Nch + N * this` because CSS cannot read letter-spacing
     back — this and the `letter-spacing` below are one value written twice.
     DATA's own divider labels are plain text and never needed it; LEGEND's are
     scrambled, and without it the reserved box is short by the whole of the
     tracking and the text runs out over the rule beside it. */
  --matrix-scramble-tracking: 0.18em;
  color: var(--accent);
  font-size: var(--font-size-small);
  font-weight: 600;
  letter-spacing: 0.18em;
  line-height: 1;
  margin-inline-end: -0.18em;
}

.metrics-table:has(
    .supply-section-start .matrix-fx-scramble[data-phase="waiting"]
  )
  .supply-section-divider
  .metrics-section-rule,
.metrics-table:has(.ytd-section-start .matrix-fx-scramble[data-phase="waiting"])
  .ytd-section-divider
  .metrics-section-rule {
  visibility: hidden;
}

.cell-label {
  text-align: left;
  font-weight: inherit;
}

.cell-value {
  text-align: right;
  color: var(--value-emphasis);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
}

.cell-pct {
  text-align: right;
  color: var(--value-derived);
  font-variant-numeric: tabular-nums;
}

.row-level-0 th,
.row-level-0 td,
.row-level-1 th,
.row-level-1 td,
.row-level-2 th,
.row-level-2 td {
  font-size: var(--font-size-small);
}

.row-level-0 th,
.row-level-0 td {
  font-weight: 600;
}
.row-level-0 .cell-label {
  color: var(--text-secondary);
}
.row-level-1 th,
.row-level-1 td {
  font-weight: 500;
}
.row-level-1 .cell-label {
  padding-inline-start: 1.35em;
}
.row-level-1 .cell-label,
.row-level-1 .cell-value,
.row-level-2 .cell-label,
.row-level-2 .cell-value {
  color: var(--text-muted);
}
.row-level-2 th,
.row-level-2 td {
  font-weight: 400;
}
.row-level-2 .cell-label {
  padding-inline-start: 2.5em;
}

/* Caret-less nested labels sit past the parent's text: its caret and gap move
   it 36.64u, so these add that plus half a char. */
.metrics-table .row-level-1 .cell-label:not(:has(> .icp-expand)) {
  padding-inline-start: 2.7em;
}

.metrics-table .row-level-2 .cell-label:not(:has(> .icp-expand)) {
  padding-inline-start: 3.5em;
}

/* DATA uses its 20% larger context where width is scarce. Above the maintained
   narrow range it returns to the terminal base so the finished desktop page
   fits its scrollport. The reciprocal tracks preserve the same physical width
   on both sides of the switch: 37 × 1.2 = 44.4. */
@container (max-width: 48em) {
  .icp-terminal {
    --metrics-panel-width: 37ch;
    --metrics-grid: 17ch 11ch 9ch;
  }

  #icp-supply-table {
    font-size: 1.2em;
  }

  .cell-snapshot > .fx-scramble {
    font-size: 0.8333em;
  }
}

/* Tight explicit leading and no added block padding make one scalable DATA row
   exactly its 38.4u LARGE line. The solver adds it. */
.metrics-table tr:is(.row-level-0, .row-level-1, .row-level-2) > :is(th, td) {
  line-height: 1;
}

/* One colour per complete row: every label, value and percentage of a top-level
   row takes PRIMARY. */
.metrics-table .cell-label {
  color: var(--text-primary);
}

.metrics-table .cell-value {
  color: var(--value-emphasis);
}

.metrics-table .cell-pct {
  color: var(--value-emphasis);
}

/* Every nested cell takes SECONDARY, so a row never mixes the two greens.
   Weight and indentation carry depth; no text dims into --text-faint. */
.metrics-table .row-level-1 .cell-value,
.metrics-table .row-level-2 .cell-value {
  color: var(--value-normal);
}

.metrics-table .row-level-1 .cell-label,
.metrics-table .row-level-1 .cell-pct,
.metrics-table .row-level-2 .cell-label,
.metrics-table .row-level-2 .cell-pct {
  color: var(--text-muted);
}

/* ---- Legend mode ---- */

/* ONE PITCH FOR THE WHOLE INDEX. Every gap in LEGEND is this length: entry to
   entry, intro to first entry, group to member. Nothing here varies its spacing
   to say something — a hairline does that below, and it is painted inside the
   gap rather than added to it — so the titles read as an evenly spaced index
   however long the description above one runs. */
.legend-view {
  --legend-gap: 0.5882em;
  /* RAIN REMAINS VISIBLE THROUGH THE VIEW. These background-coloured shadows
     form a local knockout around the glyphs, so a bright phosphor head cannot
     cut through the copy without turning the whole legend into a panel. */
  text-shadow:
    -0.0368em 0 0 var(--bg),
    0.0368em 0 0 var(--bg),
    0 -0.0368em 0 var(--bg),
    0 0.0368em 0 var(--bg),
    0 0 0.1103em var(--bg);
}

/* A `<dl>` in a grid, not a table: a single column of title/description pairs
   never needed table layout, and the table's habit of sharing spare height
   between rows is what made the gaps uneven. `gap` cannot do that. */
.legend-list {
  display: grid;
  gap: var(--legend-gap);
  margin: 0;
}

/* LEGEND titles form one index: hierarchy never shifts their reading edge, size
   or colour. Every title is PRIMARY and every description under it is SECONDARY,
   so the two roles read the same way at any depth — a section head and the
   plainest entry below it are the same green, and only the hairline and the
   tracking say which is which. */
.legend-title {
  margin: 0;
  color: var(--text-primary);
  font-size: var(--font-size-large);
  font-weight: 600;
  line-height: 1.2;
}

.legend-desc,
.legend-intro {
  margin: 0;
  text-align: left;
  font-size: var(--font-size-small);
  font-weight: 500;
  color: var(--text-muted);
  overflow-wrap: anywhere;
  line-height: 1.28;
}

/* The pair is tighter than the gap between pairs, which is the whole reason a
   title belongs to the description under it and not the one above. */
.legend-desc {
  margin-top: 0.0882em;
}

/* THE ARITHMETIC, ON ITS OWN LINE. Every quantitative entry carries the
   calculation that produced it, because "how is this worked out" is the
   question a glossary of derived figures actually gets asked — and answering it
   in prose buried the one line a reader came for.

   It is marked by a rule on its reading edge, not by a colour: the palette is
   one hue, so a colour step is reinforcement here and never the cue. That rule
   is the same hairline the section and group breaks paint, turned ninety
   degrees, so the legend has exactly one way of saying "this is set apart".

   `MEASURED` and `ESTIMATED` are words at the head of the line rather than
   badges. A badge would need a shape, a fill and a second colour to earn its
   place, and the distinction is worth a word, not a component. */
.legend-formula {
  display: block;
  margin-top: 0.2206em;
  padding-inline-start: 0.2941em;
  border-inline-start: 0.0625em solid var(--rule);
  font-size: var(--font-size-small);
  line-height: 1.32;
  letter-spacing: 0.01em;
  /* PRIMARY, like a figure in the table. The description is the explanation and
     sits in the muted role; this line is the answer, so it takes the same step
     up that a value takes over its label in DATA. */
  color: var(--text-primary);
  overflow-wrap: anywhere;
}

/* WHAT THE OLD 14 UNITS OF PADDING SAID, A RULE SAYS NOW. A group opens here
   and every title under it belongs to that group — which is also how three
   `Unlocking` entries and two `Locked` ones stay apart. */
/* ABSOLUTE, SO IT COSTS NO HEIGHT. The rule paints across the middle of the
   gap that was already there: it marks the break without adding a unit of
   space to it, which is the whole point of an evenly spaced index. */
.legend-group {
  position: relative;
}

.legend-group::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: calc(-0.5 * var(--legend-gap));
  border-top: 0.0625em solid var(--rule);
}

/* A VIEW SECTION IS DATA'S DIVIDER, markup and all. `.metrics-section-rule` is
   reused whole — two `flex: 1` rules with a centred, tracked label between
   them — so STATS, YEAR TO DATE and SUPPLY are one component in both modes
   rather than two drawings of the same idea that have to be kept in step.

   The rules stop at the label and never cross it: they are flex siblings with
   relative gaps on either side, not a line the text is laid over, so no
   width can bring them together.

   IT REPLACES THE SECTION'S OWN HAIRLINE rather than joining it. A `::before`
   painted in the gap above plus a framed label on the line below would mark one
   break twice, so `.legend-section` no longer paints one — the delimiter IS the
   break now. `.legend-group` keeps its hairline: a group opening inside a
   section is the quieter of the two, and that is the whole distinction. */
.legend-section .legend-title {
  /* The label owns its weight and tracking; the `<dt>` around it only has to
     stop imposing the title line-height on a line that is now a rule. */
  line-height: 1;
}

/* THE ROLE IS THE LEGEND'S, NOT THE TABLE'S. DATA sets this label at SMALL
   because there it heads rows of figures. Here it heads the legend's own
   titles, and a section is the largest thing in that list rather than the
   smallest — so it takes `.legend-title`'s size and the
   two read as one line of type with rules run out to the margins.

   The rules meet it at its middle and stop there: they are `flex: 1` siblings
   centred by `align-items: center`, separated by the rule's own gap, so there
   is no width at which a line can cross the text. Widening the gap with the
   type keeps that clearance proportional instead of leaving a 12-unit hole
   beside letters three times its height. */
.legend-section .metrics-section-rule {
  gap: 0.7353em;
}

.legend-section .metrics-section-label {
  font-size: var(--font-size-large);
}

/* A FRAGMENT LINK SCROLLS `.icp-terminal`, which is the legend's scroll
   container, and it lands the entry hard against the top edge without this.
   One `--legend-gap` of clearance is also exactly the space a group's hairline
   is painted into, so a jumped-to break stays visible. */
.legend-entry {
  scroll-margin-top: var(--legend-gap);
}

/* ---- The legend's index ---- */

/* THE CONTENTS, AS ORDINARY LINKS. The legend is the longest view in the page
   and the one a reader arrives at looking for a single entry, so it opens with
   a jump table: three sections, and the top-level entry under each in the order
   the list runs. Fragment links and nothing else — no handler, no scroll
   measurement, and it works with script off like every other control here. */

/* IT MIRRORS THE LIST, IT DOES NOT RESTATE IT. Section heads take the same
   0.18em the section titles take, and the entries under them sit one size
   down — the same step DATA puts between a level-0 row and its legs — so the
   index reads as a smaller copy of the page under it rather than a second
   heading level competing with the first. The tracking is the whole cue: the
   framed delimiter DATA draws between its sections would be three more
   full-width rules in a block meant to be taken in at a glance. */
/* Every line in here is a title, so the whole block is PRIMARY and the links
   inherit it — the index takes the same two roles the list does, and nothing in
   it is description. */
.legend-index {
  color: var(--text-primary);
}

.legend-index-list,
.legend-index-entries {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* The sections are the only thing in the index spaced apart, and they take half
   the list's own pitch: the index is one block in the `--legend-gap` rhythm
   outside it, so a full gap in here would read as three blocks. */
.legend-index-list {
  display: grid;
  gap: calc(0.5 * var(--legend-gap));
}

/* Wrapped, not a column: sixteen lines of contents would push the first real
   entry off the screen the index exists to save the reader from. */
.legend-index-entries {
  display: flex;
  flex-wrap: wrap;
  column-gap: 0.7353em;
  margin-top: 0.1471em;
}

.legend-index a {
  /* `inherit` in every state, or the UA's link blue and visited purple are two
     more hues on the page — the same rule the footer link follows. */
  color: inherit;
  display: inline-flex;
  align-items: center;
  /* WCAG 2.2 target size. These are list items rather than links inside a
     sentence, so the inline exception does not cover them, and the floor is the
     one the close control already uses. */
  min-height: 1.5em;
  text-underline-offset: 0.15em;
}

.legend-index a:visited,
.legend-index a:hover,
.legend-index a:active {
  color: inherit;
}

.legend-index-head {
  /* One value written twice, as everywhere a scrambled span is tracked: `fx.js`
     reserves `Nch + N * this`. */
  --matrix-scramble-tracking: 0.18em;
  font-size: var(--font-size-small);
  font-weight: 600;
  letter-spacing: 0.18em;
}

.legend-index-entries a {
  font-size: var(--font-size-small);
  font-weight: 500;
}

.legend-index a:focus-visible {
  outline: 0.125em solid var(--focus-ring);
  outline-offset: 0.1875em;
}

.icp-expand {
  position: relative;
  background: none;
  border: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
  padding: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
}

/* AN INLINE-FLEX BOX TAKES ITS BASELINE FROM ITS FIRST BASELINE-ALIGNED ITEM,
   and with everything centred that was the caret — a baseline 4.7u below the
   label's own text, which the line box then had to grow upwards to seat. Every
   caret row measured 55.6u against the old 50.88u data row, at every scale:
   the uneven rhythm in DATA, and 4.7u the old height solver never counted. */
/* Baseline-aligning the TEXT hands the line box the baseline it already assumed.
   Aligning the whole label instead also fixes the height, but drops the caret
   4.7u off the text centre — measured, not assumed. The caret keeps
   `align-items: center` above and does not move. */
.icp-expand > span:not(.icp-caret) {
  align-self: baseline;
}

/* A separate hit box supplies the WCAG 2.2 minimum without feeding a fixed
   height back through the scale solver. */
/* `label`, NOT `button`: they stopped being buttons when the interaction moved
   to checkboxes. Static legend samples are spans. */
/* `.icp-legend-open` is the same shape of control — a label in a row's own type
   — so it takes the same hit box rather than growing one of its own. */
label.icp-expand::after,
label.icp-legend-open::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  inline-size: 2em;
  block-size: 1.5em;
  transform: translate(-50%, -50%);
}

.icp-caret {
  display: inline-block;
  /* Half-size ink inside the original one-SMALL reservation: labels and hit
     regions do not move when the disclosure marker gets quieter. */
  inline-size: 2em;
  line-height: 1;
  text-align: center;
  transition: transform 0.15s ease;
  font-size: 0.5em;
}
.icp-caret.open {
  transform: rotate(90deg);
}

/* ---- Legend controls ---- */

/* THE OPEN CONTROL IS A DATA ROW and is styled like one: no border, no fill,
   nothing that reads as a button parked in the table. ACCENT is what separates
   it from the figures above — the one element in DATA that opens something —
   and the cursor after it says the rest. */
.icp-legend-open {
  position: relative;
  display: inline-flex;
  align-items: baseline;
  color: var(--accent);
  cursor: pointer;
}

/* A terminal caret, and the only blink on the page. `steps(1)`, because a
   cursor is on or off — a fade would read as a glow, which is the rain's
   register, not the interface's. */
.icp-cursor {
  animation: icp-cursor-blink 1.06s steps(1, end) infinite;
}

@keyframes icp-cursor-blink {
  0%,
  49% {
    opacity: 1;
  }
  50%,
  100% {
    opacity: 0;
  }
}

/* THE CURSOR IS PART OF THE ROW, not decoration sitting on top of it. It is
   static text, so nothing in the scramble pipeline would ever hold it back, and
   left alone it blinks over a blank page from the first frame — the one thing
   on screen while everything above it is still waiting to decode. It arrives
   when its own label finishes resolving, like a prompt that has just typed
   itself. Keyed on the class `fx.js` adds, so a script-less page never hides it. */
.icp-legend-open:has(.matrix-fx-scramble:not([data-phase="resolved"]))
  .icp-cursor {
  visibility: hidden;
}

/* THE CONTROLS RIDE THE LEGEND. Sticky against `.metrics-view`, which in LEGEND
   is exactly as tall as the list, so the row holds the bottom of the scrollport
   the whole way down and comes to rest under the last entry. */
/* `bottom: 0` IS ALREADY THE SHELL PADDING AWAY FROM THE EDGE: a sticky box is
   constrained by its scroll container's content box, and `.icp-terminal` pads
   itself by `--design-shell-padding`. Naming that length here again would float
   the row two paddings up, not one. */
.legend-controls {
  position: sticky;
  bottom: 0;
  display: flex;
  justify-content: center;
  gap: 0.4412em;
  inline-size: var(--panel-width);
  margin-top: 1.1765em;
}

/* No panel fill: each control is the page substrate with a --rule hairline,
   and its PRIMARY glyph is what marks it as navigation rather than copy. */
.icp-legend-close,
.icp-legend-top {
  display: grid;
  place-items: center;
  /* The former 44u control grew by 1.5x. One explicit square keeps the label
     and button identical instead of letting their glyph metrics size them. */
  inline-size: 2.45em;
  block-size: 2.45em;
  background: var(--bg);
  border: 0.0625em solid var(--rule);
  color: var(--text-primary);
  font-family: inherit;
  font-size: var(--font-size-small);
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.05em;
  margin: 0;
  padding: 0;
  cursor: pointer;
}

/* Hover is where a raised surface is unavoidable: no hue left to shift and the
   glyph is already top tier. It keeps its --rule border. */
.icp-legend-close:hover,
.icp-legend-top:hover {
  background: var(--surface-raised);
  border-color: var(--accent);
}

.icp-legend-top:focus-visible {
  outline: 0.125em solid var(--focus-ring);
  outline-offset: 0.125em;
}

/* Arrows and carets are <label>s and never take focus; the ring belongs to
   their input. These two rules keep its shape in one place. */
.stats-period-arrow:focus-visible,
.icp-expand:focus-visible,
.icp-built-with a:focus-visible {
  outline: 0.125em solid var(--focus-ring);
}

.stats-period-arrow:focus-visible,
.icp-expand:focus-visible {
  outline-offset: 0.125em;
}

.icp-built-with a:focus-visible {
  outline-offset: 0.1875em;
}
.icp-footer {
  margin: 0.5882em 0 0;
  text-align: center;
  font-size: var(--font-size-small);
  /* Chrome made of text, so it stops at the --text-muted floor. */
  color: var(--text-muted);
}

.icp-footer p {
  margin: 0;
}

.icp-canister-support {
  margin: 0.5882em 0 0;
  color: var(--text-muted);
  font-size: var(--font-size-small);
  text-align: center;
  overflow-wrap: anywhere;
}

.icp-canister-support + .icp-footer {
  margin-top: 0.2206em;
}

/* The footer's only line; snapshot freshness sits above it in its own slot. */
.icp-footer .icp-built-with {
  margin-top: 0;
}

/* `inherit` in every state, or the UA's link blue and visited purple are two
   more hues on the page. */
.icp-built-with a,
.icp-built-with a:visited,
.icp-built-with a:hover,
.icp-built-with a:active {
  color: inherit;
  text-underline-offset: 0.15em;
}

.icp-heart {
  color: var(--accent);
}

@keyframes icp-title-reveal {
  0%,
  42% {
    opacity: 0;
  }
  67%,
  100% {
    opacity: 1;
  }
}

@media print {
  .matrix-fx-ready .icp-title {
    opacity: 1;
    animation: none;
  }

  /* Print keeps the screen's substrate and inks and forces the browser to
     honour them: no value in the palette clears 4.5:1 on white. */
  /* The glow is stripped — a text-shadow bloom only muddies at print DPI. */
  .icp-terminal {
    background: var(--bg);
    color: var(--text-secondary);
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }

  .icp-title,
  .icp-subtitle,
  .icp-tagline,
  .icp-status,
  .stats-table,
  .metrics-table {
    text-shadow: none;
  }

  /* Paper is one window: the arrows cannot be pressed, so they are noise. */
  .stats-period-arrow {
    display: none;
  }

  /* Paper is DATA only: both mode controls are unpressable, and a blinking
     cursor is nothing at all. The row itself stays — it carries the snapshot
     stamp, which is the one thing on paper that says when this was true. */
  .icp-caret,
  .icp-legend-open,
  .legend-controls {
    display: none;
  }
}


/* ---- MATRIX FX ---- */

.matrix-fx-enabled {
  min-height: 100%;
  container-type: inline-size;

  /* The title reveal's timing lives in CSS, not the engine. Leaving it unset
     invalidates the `animation` shorthand that names it. */
  --matrix-title-surge-duration: 2000ms;
}

/* Negative, not `0`: rain must never paint over foreground. At `z-index: 0`
   only siblings opting into a higher layer stay clear. */
/* A negative layer paints below every in-flow and positioned box in the
   stacking context, so no element has to opt in. */
/* `isolation: isolate` keeps the layer inside the terminal; the canvas stays
   transparent so the radial substrate shows through. */
.matrix-fx-layer {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

.matrix-fx-canvas {
  display: block;
  inline-size: 100vw;
  height: 100%;
}

.matrix-fx-sr-only {
  padding: 0;
  margin: -0.0625em;
  clip: rect(0, 0, 0, 0);
  border: 0;
}

.matrix-fx-scramble {
  display: inline-block;
  white-space: pre;
  /* A font-independent line box, so fallback glyph metrics cannot move controls
     while a line resolves. */
  line-height: 1.2;
}

/* Multi-line body copy, marked `fx-wrap` in the markup: the `ch` width becomes
   a ceiling and the line height goes back to the block's. */
.matrix-fx-scramble-wrap {
  max-inline-size: none;
  white-space: normal;
  line-height: inherit;
}

@media (prefers-reduced-motion: reduce) {
  .matrix-fx-layer {
    display: none;
  }

  .matrix-fx-scramble,
  .icp-caret,
  .icp-cursor {
    animation: none;
    transition: none;
  }

  /* A jump from the legend's index becomes a jump again. */
  .icp-terminal {
    scroll-behavior: auto;
  }
}

@media print {
  .matrix-fx-layer {
    display: none;
  }

  .matrix-fx-sr-only.visually-hidden {
    position: static;
    width: auto;
    height: auto;
    padding: 0;
    margin: 0;
    overflow: visible;
    clip: auto;
    white-space: inherit;
  }

  .matrix-fx-scramble > [aria-hidden="true"] {
    display: none;
  }
}


/* ---- DECLARATIVE STATE ---- */

/* Controls are real form inputs ahead of `.icp-content`, so `:checked ~ …`
   reaches the whole page. No script participates. */

/* Focusable but invisible: `display: none` would drop them from the tab order
   and kill the radio group's native arrow keys. */
/* `fixed`, NOT `absolute` — this is what stops the page jumping. Activating a
   <label> focuses its control, and a focused control that lies outside the
   scrollport is scrolled into view. These inputs must precede `.icp-content`
   for `:checked ~` to reach it, so absolutely positioned they took their static
   position at the very top of `.icp-terminal`, and every expand below the fold
   threw the reader back to the top — the collapse threw them back again.
   Pinned to the viewport they are never out of view, so focus costs no
   scrolling and the row stays under the pointer. */
.icp-state {
  position: fixed;
  top: 0;
  left: 0;
  width: 0.0625em;
  height: 0.0625em;
  margin: -0.0625em;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* --- Window selection ----------------------------------------------------- */

/* All three windows are in the document; one is shown. */
.w {
  display: none;
}

#w24:checked ~ .icp-content .w.w24,
#w7:checked ~ .icp-content .w.w7,
#w30:checked ~ .icp-content .w.w30 {
  display: inline;
}

/* The split bar's halves are flex items, not text. */
#w24:checked ~ .icp-content .stats-bar > .w24,
#w7:checked ~ .icp-content .stats-bar > .w7,
#w30:checked ~ .icp-content .stats-bar > .w30 {
  display: block;
  flex-grow: var(--share, 1);
  flex-basis: 0;
}

/* One arrow pair per window, so up/down point at the neighbour and wrap at
   both ends — the ring the removed keyboard handler computed. */
.stats-period-arrow {
  display: none;
  cursor: pointer;
}

#w24:checked ~ .icp-content .stats-period-arrow.p24,
#w7:checked ~ .icp-content .stats-period-arrow.p7,
#w30:checked ~ .icp-content .stats-period-arrow.p30 {
  display: block;
}

/* Focusing a window radio must show on its spinner, since the input itself is
   invisible. */
.icp-state:focus-visible ~ .icp-content .stats-period-value {
  outline: 0.0625em solid var(--accent);
  outline-offset: 0.125em;
}

/* --- Row expansion -------------------------------------------------------- */

.metrics-rows tr[class*="child-"] {
  display: none;
}

#exStaked:checked ~ .icp-content tr.child-staked,
#exRewards:checked ~ .icp-content tr.child-rewards,
#exMinted:checked ~ .icp-content tr.child-minted,
#exBurned:checked ~ .icp-content tr.child-burned,
#exYtdRewards:checked ~ .icp-content tr.child-ytdRewards {
  display: grid;
}

/* A bucket row belongs to two disclosures and needs both open. Equal
   specificity to the rules above, so these win on source order. */
#exStakedUnlocking:not(:checked) ~ .icp-content tr.child-stakedUnlocking,
#exStakedLocked:not(:checked) ~ .icp-content tr.child-stakedLocked,
#exRewardsUnlocking:not(:checked) ~ .icp-content tr.child-rewardsUnlocking,
#exRewardsLocked:not(:checked) ~ .icp-content tr.child-rewardsLocked {
  display: none;
}

/* The caret points down while its section is open; only the transform is state. */
.icp-expand {
  cursor: pointer;
}

#exStaked:checked ~ .icp-content label[for="exStaked"] .icp-caret,
#exStakedUnlocking:checked ~ .icp-content label[for="exStakedUnlocking"] .icp-caret,
#exStakedLocked:checked ~ .icp-content label[for="exStakedLocked"] .icp-caret,
#exRewards:checked ~ .icp-content label[for="exRewards"] .icp-caret,
#exRewardsUnlocking:checked ~ .icp-content label[for="exRewardsUnlocking"] .icp-caret,
#exRewardsLocked:checked ~ .icp-content label[for="exRewardsLocked"] .icp-caret,
#exMinted:checked ~ .icp-content label[for="exMinted"] .icp-caret,
#exBurned:checked ~ .icp-content label[for="exBurned"] .icp-caret,
#exYtdRewards:checked ~ .icp-content label[for="exYtdRewards"] .icp-caret {
  transform: rotate(90deg);
}

/* --- LEGEND / DATA mode --------------------------------------------------- */

/* ONE CHECKBOX, TWO LABELS, one visible at a time: the `Legend_` row goes with
   the table it sits in, and the controls only exist while there is a legend to
   navigate or close. Neither is chrome that survives the other mode. */
.legend-controls {
  display: none;
}

#modeLegend:checked ~ .icp-content .legend-controls {
  display: flex;
}

.icp-legend-top[hidden] {
  display: none;
}

/* The ring belongs to the input — a <label> never takes focus — so it is drawn
   on whichever of the two labels is currently on screen. */
#modeLegend:focus-visible ~ .icp-content .icp-legend-open,
#modeLegend:focus-visible ~ .icp-content .icp-legend-close {
  outline: 0.125em solid var(--focus-ring);
  outline-offset: 0.125em;
}

/* DATA and LEGEND share one slot: the legend replaces the metric rows in place
   rather than opening a panel beside them. */
.legend-view {
  display: none;
}

#modeLegend:checked ~ .icp-content .metrics-view > .metrics-table {
  display: none;
}

/* Grid, not block: the intro and the list are separated by the same
   `--legend-gap` as any two entries. */
#modeLegend:checked ~ .icp-content .legend-view {
  display: grid;
  gap: var(--legend-gap);
}

/* --- Without JavaScript --------------------------------------------------- */

/* `fx.js` adds `matrix-fx-ready` once it has taken over. Until then, and for
   good if it never loads, the page is already complete. */
.matrix-fx-layer {
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
  .matrix-fx-layer {
    display: none;
  }
}

/* --- Width reservation --- */

/* Switching windows must not reflow: the fill step measures all three and
   declares the widest here, with no shadow markup or extra grid items. */
[data-reserve] {
  min-width: var(--reserve, auto);
  display: inline-block;
}

/* ---- CHART FIGHT --------------------------------------------------------- */

.chart-fight-placeholder {
  inline-size: var(--panel-width);
  color: var(--text-secondary);
}

.chart-fight-placeholder > .metrics-section-rule {
  block-size: calc(2 * var(--row-height));
}

.chart-fight-message {
  display: flex;
  align-items: center;
  justify-content: center;
  block-size: var(--row-height);
  margin: 0;
  color: var(--text-primary);
  font-size: var(--font-size-small);
  line-height: 1;
}

/* ---- BURN CALCULATOR ----------------------------------------------------- */

.burn-calculator-content,
.burn-calculator {
  inline-size: var(--panel-width);
}

.calculator-output-table,
.calculator-ladder {
  inline-size: var(--panel-width);
}

.burn-calculator {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-auto-rows: auto;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}

.calculator-control {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

.calculator-summary-row > :is(dt, dd),
.calculator-summary-row > :is(th, td) {
  min-inline-size: 0;
  margin: 0;
  padding: 0;
  line-height: 1;
}

.calculator-summary-row > :first-child {
  color: var(--text-secondary);
  text-align: left;
}

.calculator-summary-row > :nth-child(2),
.calculator-summary-row > :nth-child(3) {
  color: var(--value-emphasis);
  text-align: right;
  font-variant-numeric: tabular-nums;
}

.calculator-wide-value {
  grid-column: 2 / 4;
}

.calculator-output-rows .row-level-0 > :is(th, td) {
  color: var(--text-primary);
}

.calculator-output-rows .row-level-1 > :is(th, td) {
  color: var(--text-secondary);
}

.burn-calculator > section > .metrics-section-rule,
.calculator-assumptions > .metrics-section-rule {
  block-size: calc(2 * var(--row-height));
}

.calculator-slider {
  display: block;
  inline-size: auto;
  block-size: var(--row-height);
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

.calculator-ticks {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 0.25em;
}

.calculator-tick {
  min-inline-size: 0;
  min-block-size: 2em;
  color: var(--text-secondary);
  text-align: center;
}

.calculator-tick[aria-pressed="true"] {
  color: var(--accent);
  font-weight: 700;
}

.calculator-slider:focus-visible,
.calculator-tick:focus-visible,
.calculator-assumption-fields input:focus-visible {
  outline: 0.08em solid var(--focus-ring);
  outline-offset: 0.08em;
}

.calculator-ladder {
  display: block;
  border-collapse: collapse;
}

.calculator-ladder thead,
.calculator-ladder tbody {
  display: block;
}

.calculator-ladder th,
.calculator-ladder td {
  min-inline-size: 0;
  overflow: hidden;
  padding: 0;
  line-height: 1;
  text-overflow: clip;
  white-space: nowrap;
}

.calculator-ladder thead th {
  color: var(--text-secondary);
  font-weight: 500;
  text-align: right;
}

.calculator-ladder thead th:first-child {
  text-align: left;
}

.calculator-price-row td:nth-child(2) {
  font-weight: 700;
}

.calculator-price-row > :is(th, td) {
  color: var(--text-primary);
}

.calculator-balance-row > :is(th, td) {
  color: var(--text-secondary);
}

.calculator-balance-row .cell-label {
  padding-inline-start: 1.35em;
}

.calculator-break-even > th {
  grid-column: 1 / -1;
  padding: 0;
  border-block: 0.04em dashed var(--value-emphasis);
  color: var(--text-primary);
}

.calculator-break-content {
  display: grid;
  grid-template-columns: var(--data-grid);
  align-items: center;
  block-size: calc(2 * var(--row-height));
}

.calculator-break-label {
  color: var(--value-emphasis);
}

.calculator-break-even strong,
.calculator-break-copy {
  text-align: right;
}

.calculator-break-copy {
  color: var(--value-normal);
  font-weight: 400;
}

.calculator-assumptions {
  margin: 0;
}

.calculator-assumptions summary {
  color: var(--text-secondary);
  cursor: pointer;
}

#assumptionStatus {
  color: var(--text-muted);
  font-style: italic;
}

.calculator-assumption-fields {
  display: block;
}

.calculator-assumption-row {
  display: grid;
  grid-template-columns: var(--data-grid);
  block-size: var(--row-height);
  align-items: baseline;
  min-inline-size: 0;
  color: var(--text-primary);
}

.calculator-assumption-row > .cell-label {
  color: var(--text-primary);
}

.calculator-assumption-fields input {
  grid-column: 2 / 4;
  box-sizing: border-box;
  min-inline-size: 0;
  border: 0;
  border-block-end: 0.04em solid var(--rule);
  color: var(--value-emphasis);
  background: transparent;
  font: inherit;
  line-height: 1;
}

.calculator-assumption-fields input[aria-invalid="true"] {
  border-color: var(--accent);
}

.calculator-formula,
.calculator-note,
.calculator-snapshot {
  margin: 0;
}

.calculator-formula,
.calculator-note {
  line-height: 1.35;
}

.calculator-formula {
  color: var(--text-primary);
  border-inline-start: 0.04em solid var(--rule);
  padding-inline-start: 0.5em;
}

.calculator-snapshot {
  display: block;
  color: var(--text-muted);
  font-style: italic;
  text-align: right;
}
