/* ─────────────────────────────────────────────────────────────────────────
   dashboard.css — the dashboard register.

   A dashboard on this site is a RULED SHEET. The reference object is not a
   SaaS console; it is a printed operations sheet — a technical drawing, an
   aircraft checklist, the face of a laboratory instrument. Everything below
   follows from that one decision:

     · REGIONS ARE SEPARATED BY RULES, NOT CONTAINERS. A 1px --graphite line
       runs the width of the region it divides and, where the sheet is
       cropped, runs off the edge. It is a line on paper, not a box border.
     · A HAIRLINE BELONGS TO THE LOWER REGION (border-top, never
       border-bottom), so a region is self-contained: drop it at a narrow
       width and no orphan line is left behind.
     · TWO LINE WEIGHTS EXIST AND NO THIRD IS EVER DRAWN. The rule of record
       (2px solid var(--ink)) appears exactly once per sheet, under the
       chrome bar — the same device .figure already uses in sections.css.
       Everything else is a hairline.
     · VERTICAL SEPARATION IS DONE BY GAP. There is exactly one legal
       vertical hairline on the whole sheet: between a status matrix's
       row-header column and its data cells.
     · WHITE IS THE MATERIAL. No less than 62% of any frame is bare --page
       with nothing drawn on it. Row gap is therefore ZERO — the rules do
       the separating, and two stacked regions share one line instead of
       floating apart.

   NO BACKGROUNDS ON TILES. NO BORDER-RADIUS ON TILES. NO BOX-SHADOW, EVER,
   INCLUDING ON HOVER. NO GRADIENT EXCEPT THE PACKET'S OWN, WHICH IS COPIED
   VERBATIM FROM .orbit-packet BECAUSE IT IS A LIGHT SOURCE, NOT A SURFACE.

   GREEN MEANS CURRENT IS FLOWING. --leaf appears on nine things and nowhere
   else: the live dot, the travelling packet, one bar in a series, a
   sparkline's final segment, the meter fill, the confirmation tick, a
   reached cell, the underline under the row the run is on, and a value in
   the 400ms after it changed. Hard ceiling 3.5% of frame area; the target
   is about 1%. Every other mark is --ink, --ink-60 or --graphite.

   Everything is scoped under .dash so none of it can reach the existing
   pages. Every value is a var() — there is not a raw hex in this file.

   BREAKPOINTS ARE CONTAINER QUERIES, not viewport media queries, so one
   dashboard is correct in a hero column, in a half-width section and on a
   phone without a second rule being written. Drop order, memorised:
   sparkline → status matrix → bar series → calendar → feed sublines → foot
   rail. The chrome bar, the feed titles, the packet track and the tick are
   never dropped: those four are the sheet's meaning.

   Load AFTER tokens.css and base.css, and after flow.css where the
   reduced-motion stepper is wanted (it borrows .hero-stepper's treatment).
   ───────────────────────────────────────────────────────────────────────── */

/* ── the frame and the sheet ───────────────────────────────────────────── */

/* THE FRAME IS THE CONTAINER, AND THE SHEET IS INSIDE IT. An element cannot
   answer a container query about itself, and every rule below needs to change
   the sheet's OWN column count, padding, chrome height and aspect ratio — so
   the sheet has to be a descendant of whatever is being measured. The frame
   is that measurement, and it does nothing else. */
.dash-frame {
  container-type: inline-size;
  min-width: 0;
}

.dash {
  --dash-cols: 12;
  --dash-gutter: var(--s4);      /* 24px — the only column gap             */
  --dash-pad: var(--s5);         /* 40px — the sheet margin                */
  --dash-unit: var(--s3);        /* 16px — the vertical rhythm unit        */
  --dash-chrome-h: 48px;
  --dash-rail-h: 28px;
  --dash-row-pad: var(--s4);

  position: relative;
  display: grid;
  /* chrome · body · ambient rail · foot. The last two tracks collapse to
     nothing on the formats that do not carry them, so one template serves
     all four rather than four templates serving one each. */
  grid-template-rows: var(--dash-chrome-h) minmax(0, 1fr) var(--dash-rail-h) auto;
  padding: 0 var(--dash-pad) var(--s4);
  background: var(--page);
  color: var(--ink);
  font-family: var(--font-body);
  border-top: var(--hairline);        /* the sheet's own top edge */
  min-width: 0;                       /* never wider than the frame allows */
  /* `clip`, not `hidden` and never `auto`: it trims the deliberate crop
     without creating a scroll container, exactly as .sec-cards already does. */
  overflow: clip;
}

/* The four formats. aspect-ratio is declared here so the box exists before
   the module runs — zero CLS, whatever the sheet later fills itself with. */
.dash[data-format='wide']   { aspect-ratio: 16 / 10; min-height: 420px; }
.dash[data-format='square'] { aspect-ratio: 1 / 1;   min-height: 340px; --dash-cols: 8; }
.dash[data-format='tall']   { aspect-ratio: 3 / 4;   min-height: 420px; --dash-cols: 6;
                              --dash-chrome-h: 36px; --dash-rail-h: 0px;
                              --dash-pad: var(--s4); padding-left: calc(var(--s4) + 22px); }
.dash[data-format='strip']  { aspect-ratio: 3 / 1;   min-height: 180px;
                              --dash-chrome-h: 36px; }

/* THE DELIBERATE CROP. At most one tile per sheet, on wide and strip only,
   runs off the RIGHT edge so the system reads as continuing beyond the
   frame. Never the left, which reads as a rendering bug, and never type. */
.dash[data-format='wide']  .dash-tile.is-crop,
.dash[data-format='strip'] .dash-tile.is-crop { margin-right: calc(var(--dash-pad) * -1); }

/* ── chrome bar (§2.1) ─────────────────────────────────────────────────── */

.dash-chrome {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--s3);
  border-bottom: 2px solid var(--ink);   /* the rule of record, once */
  will-change: transform, opacity;
}

.dash-bay { font-size: 12px; letter-spacing: 0.18em; color: var(--leaf-ink); }

.dash-name {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 15px;
  letter-spacing: var(--display-tracking);
  line-height: 1;
  text-transform: uppercase;
  color: var(--ink);
  margin: 0;
  /* ONE LINE, ALWAYS. The chrome row is a fixed height; a name that wraps
     inside it lands its second line on the 2px rule of record, and a name
     that overflows its minmax(0,1fr) column runs under LIVE. Ellipsis is
     the honest failure at widths where AUTOMATION does not fit. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.dash-live {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 11px;
  letter-spacing: 0.16em;
  color: var(--leaf-ink);
  white-space: nowrap;   /* LIVE never breaks from its dot */
}

.dash-live i {
  position: relative;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--leaf);
  flex: none;
}

/* The pulse is a SCALING PSEUDO-RING, not an animated box-shadow: a shadow
   cannot be composited and repaints the chrome bar every frame. */
.dash-live i::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--leaf-30);
  animation: dash-pulse 2s linear infinite;
  /* `--dash-phase` is set per mount by kit.js: nine sheets on one page must
     not share a heartbeat. Negative, so the ring is mid-breath at first
     paint rather than nine rings waiting out nine different delays. */
  animation-delay: var(--dash-phase, 0s);
  will-change: transform, opacity;
}

@keyframes dash-pulse {
  from { transform: scale(1);   opacity: 0.9; }
  to   { transform: scale(2.6); opacity: 0;   }
}

.dash-clock { font-size: 12px; color: var(--ink-60); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ── the body grid and its tiles (§1.1, §1.4) ──────────────────────────── */

.dash-body {
  display: grid;
  grid-template-columns: repeat(var(--dash-cols), minmax(0, 1fr));
  column-gap: var(--dash-gutter);
  row-gap: 0;                    /* rules separate rows, not gaps */
  align-content: start;
  min-height: 0;
}

.dash-tile {
  grid-column: span var(--span, 4);
  border-top: var(--hairline);
  padding: var(--dash-row-pad) 0;
  min-width: 0;
}

.dash-tile-label {
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-60);
  margin: 0 0 var(--s3);
  will-change: opacity;
}

/* ── KPI tile (§2.2) ───────────────────────────────────────────────────── */

.dash-kpi-value {
  display: block;
  margin: 0;
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(34px, 5.4cqi, 74px);
  letter-spacing: var(--display-tracking);
  line-height: 0.92;
  color: var(--ink);
  /* PROPORTIONAL figures at display size, tabular figures in columns: 121 in
     tabular-nums at 74px looks broken, and the same number in a table column
     must align. Both rules are honoured, in their own places. */
  font-variant-numeric: proportional-nums;
  transition: color 200ms linear;
  will-change: transform, opacity;
}

/* Allow-list item 9: a value that JUST CHANGED, as text, for 400ms. */
.dash-kpi-value.is-changed { color: var(--leaf-ink); }

.dash-kpi-delta {
  margin: var(--s3) 0 0;
  font-size: 11px;
  letter-spacing: 0.16em;
  color: var(--ink-60);
}

/* ── sparkline (§2.3) ──────────────────────────────────────────────────── */

.dash-spark {
  display: block;
  width: 100%;
  height: 44px;
  margin-top: var(--s3);
  overflow: visible;
}

.dash-spark-line {
  fill: none;
  stroke: var(--graphite);
  stroke-width: 1.5;
  stroke-linejoin: round;
  stroke-linecap: round;
  /* pathLength="1" normalises the geometry, so the draw is a dash offset
     from 1 to 0 and nothing is measured at runtime. */
  stroke-dasharray: 1;
}

/* The FINAL SEGMENT ONLY. Never the whole line. */
.dash-spark-tail {
  fill: none;
  stroke: var(--leaf);
  stroke-width: 1.5;
  stroke-linecap: round;
}

/* The surface ring keeps the end dot legible where it crosses the line. */
.dash-spark-dot { fill: var(--leaf); stroke: var(--page); stroke-width: 2; }

/* ── bar series (§2.4) ─────────────────────────────────────────────────── */

.dash-bars {
  display: flex;
  align-items: flex-end;
  gap: var(--s2);
  height: 96px;
  border-bottom: var(--hairline);   /* the baseline, running off the crop */
  will-change: transform, opacity;
}

.dash-bars i {
  flex: 1 1 0;
  max-width: 18px;
  min-width: 6px;
  height: var(--h);
  border-radius: 3px 3px 0 0;       /* rounded data-end, square at the baseline */
  background: var(--graphite);
  transform: scaleY(0);
  transform-origin: bottom;
  will-change: transform;
}

/* EXACTLY ONE bar is green: the most recent. */
.dash-bars i.is-live { background: var(--leaf); }

.dash-bars-tip {
  margin: var(--s2) 0 0;
  font-size: 11px;
  letter-spacing: 0.16em;
  color: var(--ink-60);
}

/* ── activity feed (§2.5) ──────────────────────────────────────────────── */

.dash-feed { list-style: none; margin: 0; padding: 0; }

.dash-feed-row {
  position: relative;
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s3);
  /* Height is FIXED before mount — the subline's space is always reserved,
     exactly as .orbit-sub learned to do — so a reveal never reflows. */
  min-height: 52px;
  padding: var(--s3) 0;
  border-top: var(--hairline);
  will-change: transform, opacity;
}

/* Allow-list item 8: ONE row carries a 1px green underline — the row the
   run is currently on. Drawn with a transitioned scaleX on a pseudo-element,
   never a fading border-colour, which cannot be composited. */
.dash-feed-row::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background: var(--leaf);
  transform: scaleX(var(--on, 0));
  transform-origin: left;
  transition: transform 260ms var(--ease-out);
}

.dash-feed-icon {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--paper);
  color: var(--ink-60);
}

.dash-feed-icon svg { width: 14px; height: 14px; }

.dash-feed-text { display: block; min-width: 0; }

.dash-feed-title {
  display: block;
  font-weight: 500;
  font-size: 14px;
  line-height: 1.25;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dash-feed-sub {
  display: block;
  font-size: 12px;
  line-height: 1.35;
  color: var(--ink-60);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.dash-feed-state {
  font-size: 11px;
  letter-spacing: 0.16em;
  color: var(--ink-60);
  transition: color 260ms linear;
}

.dash-feed-row.is-done .dash-feed-state { color: var(--leaf-ink); }
.dash-feed-row.is-done .dash-feed-icon { color: var(--ink); }

/* ── pipeline lane (§2.6) ──────────────────────────────────────────────── */

.dash-lane { position: relative; padding-top: var(--s2); }

.dash-lane-rail {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(var(--s2) + 4px);
  height: 0;
  border-top: var(--hairline);
}

.dash-lane-steps {
  position: relative;
  display: flex;
  gap: var(--s2);
  list-style: none;
  margin: 0;
  padding: 0;
}

.dash-lane-step { flex: 1 1 0; min-width: 0; text-align: left; }

.dash-lane-node {
  display: block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--page);
  border: 1.5px solid var(--graphite);
  /* Colour only, 260ms. The node never moves, never grows. */
  transition: background-color 260ms var(--ease-out), border-color 260ms var(--ease-out);
}

.dash-lane-step.is-on .dash-lane-node { background: var(--leaf); border-color: var(--leaf); }

.dash-lane-label {
  display: block;
  margin-top: var(--s2);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-60);
  /* Truncated, never rotated 45°, never wrapped. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── calendar / availability grid (§2.7) ───────────────────────────────── */

.dash-cal-head,
.dash-cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }

.dash-cal-head span {
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--ink-60);
  padding-bottom: var(--s2);
  text-align: center;
}

/* Cells carry border-top and border-left ONLY, so shared edges are a single
   hairline and the outer right and bottom edges stay open — the grid runs
   off the sheet rather than closing into a boxed table. The leading left
   edge is dropped too: the sheet has no vertical rule down its left side. */
.dash-cal-cell {
  position: relative;
  min-height: 22px;
  border-top: var(--hairline);
  border-left: var(--hairline);
}

.dash-cal-cell:nth-child(7n + 1) { border-left: 0; }

/* held — a hairline drawn corner to corner. A mark on paper, not a fill. */
.dash-cal-cell.is-held::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  border-top: var(--hairline);
  transform: rotate(-32deg);
}

/* booked — a small solid square, and never more than three at once. */
.dash-cal-cell.is-booked b {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 8px;
  height: 8px;
  margin: -4px 0 0 -4px;
  background: var(--leaf);
  will-change: transform, opacity;
}

/* ── status matrix (§2.8) ──────────────────────────────────────────────── */

.dash-matrix {
  width: 100%;
  border-collapse: collapse;
  text-align: left;
}

.dash-matrix thead th {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 400;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-60);
  padding: 0 var(--s2) var(--s2);
  text-align: center;
}

.dash-matrix tbody tr { border-top: var(--hairline); }

/* THE ONE LEGAL VERTICAL RULE on the whole sheet. */
.dash-matrix tbody th {
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink);
  padding: var(--s3) var(--s3) var(--s3) 0;
  border-right: var(--hairline);
  white-space: nowrap;
}

.dash-matrix td { padding: var(--s3) var(--s2); text-align: center; min-width: 20px; }

.dash-cell {
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  will-change: transform, opacity;
}

.dash-cell.is-na {
  width: auto;
  height: auto;
  border-radius: 0;
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--graphite);
}

.dash-cell.is-pending { border: 1px solid var(--ink-60); }
.dash-cell.is-on { background: var(--leaf); }

/* ── transcript (§2.10) ────────────────────────────────────────────────── */

.dash-script { list-style: none; margin: 0; padding: 0; }

.dash-script-line {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: var(--s3);
  align-items: baseline;
  padding: var(--s3) 0;
  border-top: var(--hairline);
  min-height: 44px;
  will-change: opacity;
}

.dash-script-time { font-size: 11px; color: var(--ink-60); font-variant-numeric: tabular-nums; }

/* The speaker mark is a rule at the left edge of the text column: ink for
   the system's own lines, graphite for the customer's. Not a coloured
   bubble, not an avatar, not a second accent. */
.dash-script-text {
  display: block;
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--ink);
  padding-left: var(--s3);
  border-left: 2px solid var(--graphite);
}

.dash-script-line[data-who='system'] .dash-script-text { border-left-color: var(--ink); }

/* ── the ambient rail: packet track (§2.11) + tick (§2.12) ─────────────── */

.dash-rail {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s3);
}

.dash-track {
  position: relative;
  height: 0;
  border-top: 1.5px dashed var(--leaf-30);
}

/* THE TRAVEL, WITHOUT MEASURING ANYTHING. A percentage translate resolves
   against the element's own box, so this wrapper — stretched across the
   track — moves by exactly the track's width at translate 100%. No
   ResizeObserver, no getBoundingClientRect, and the vertical variant is the
   same code with a different axis.

   The wrapper's own box therefore hangs past the right edge for most of the
   lap. That is expected and is what .dash's `overflow: clip` is for; it
   creates no scroll container and no page overflow. Do not "fix" it by
   clipping .dash-track itself — that would cut the packet in half exactly
   as it completes its travel, which is where it parks under reduced motion. */
.dash-track-run { position: absolute; inset: 0; will-change: transform; }

.dash-packet {
  position: absolute;
  left: -7px;
  top: -7px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  /* Construction copied verbatim from .orbit-packet, and it stays verbatim:
     this is the one shape a returning visitor already recognises. The
     box-shadow is STATIC — a halo on a light source, never animated, so it
     breaks neither the compositor rule nor the no-shadows rule. */
  background: radial-gradient(circle at 36% 30%, var(--leaf-hot), var(--leaf) 55%, var(--leaf-ink));
  box-shadow: 0 0 0 3px var(--leaf-14);
}

.dash-tick { display: grid; place-items: center; width: 20px; height: 20px; }

.dash-tick svg { width: 20px; height: 20px; display: block; }

/* No circle behind it, no filled badge, no green pill. Stroke only. */
.dash-tick path {
  fill: none;
  stroke: var(--leaf);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
}

/* The vertical variant: the same rail rotated, running down the left margin,
   exactly as .orbit[data-mode='ladder'] does. Taken out of flow so the tall
   format's grid keeps its two rows. */
.dash-rail[data-axis='y'] {
  position: absolute;
  left: var(--s4);
  top: calc(var(--dash-chrome-h) + var(--s4));
  bottom: var(--s6);
  width: 0;
  display: block;
}

.dash-rail[data-axis='y'] .dash-track {
  position: absolute;
  inset: 0;
  height: auto;
  width: 0;
  border-top: 0;
  border-left: 1.5px dashed var(--leaf-30);
}

.dash-rail[data-axis='y'] .dash-tick { position: absolute; bottom: -28px; left: -10px; }

/* ── foot rail: the meter (§2.9) and one status readout ────────────────── */

.dash-foot {
  display: flex;
  align-items: center;
  gap: var(--s3);
  min-height: 44px;
  padding-top: var(--s3);
  border-top: var(--hairline);
}

.dash-foot-label,
.dash-foot-value { margin: 0; font-size: 11px; letter-spacing: 0.16em; color: var(--ink-60); }

/* Deliberately the same construction as .phone-progress and .spine-fill.
   One mechanism, three uses. Never a donut, never a needle. */
.dash-meter {
  flex: 1 1 auto;
  height: 3px;
  border-radius: 2px;
  background: var(--graphite);
  overflow: hidden;
}

.dash-meter span {
  display: block;
  height: 100%;
  background: var(--leaf);
  transform: scaleX(0);
  transform-origin: left;
  will-change: transform;
}

/* ── the reduced-motion stepper ────────────────────────────────────────── */

/* Borrows .hero-stepper's treatment; restated here so a page that loads
   dashboard.css without flow.css still gets a real, reachable control. */
.dash .dash-step {
  margin: var(--s3) 0 0;
  background: none;
  border: var(--hairline);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.10em;
  padding: 10px var(--s3);
  min-height: 44px;          /* the hit target floor, at every width */
  min-width: 44px;
  cursor: pointer;
  justify-self: start;
}

.dash .dash-step:hover { border-color: var(--leaf-ink); color: var(--leaf-ink); }

/* Ink, never browser blue. */
.dash .dash-step:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ── reduced motion ────────────────────────────────────────────────────── */

/* The settled state is painted by the module at t = 10.400s — everything
   arrived, the tick drawn, the packet parked at the end of its travel. All
   this block does is make sure nothing CSS owns keeps moving underneath it.
   The live-dot ring is REMOVED, not paused: a paused ring is a stalled
   halo sitting at whatever scale it happened to reach. */
@media (prefers-reduced-motion: reduce) {
  .dash *,
  .dash *::before,
  .dash *::after { animation: none !important; transition: none !important; }
  .dash-live i::after { display: none; }
}

.dash[data-static] .dash-live i::after { display: none; }
.dash[data-static] *,
.dash[data-static] *::before,
.dash[data-static] *::after { animation: none; transition: none; }

/* ── responsive (§7) ───────────────────────────────────────────────────── */

/* Below 1200px the chrome clock loses its seconds: the sheet has less room
   to name itself and a ticking seconds field is the least of what it says. */
@container (max-width: 1199px) {
  .dash-clock-s { display: none; }
}

/* 1000–1199 — the transcript loses its timestamp column. */
@container (max-width: 1199px) {
  .dash-script-line { grid-template-columns: minmax(0, 1fr); }
  .dash-script-time { display: none; }
}

/* 780–999 — 8 columns. The SPARKLINE DROPS first: it is the primitive that
   shows shape rather than value, and shape is the least missed. The KPI band
   goes from three tiles to two, and the bar series keeps its last six. */
@container (max-width: 999px) {
  .dash { --dash-cols: 8; --dash-gutter: var(--s3); --dash-pad: var(--s4); }
  .dash-spark { display: none; }
  .dash-body > [data-part='kpi'] ~ [data-part='kpi'] ~ [data-part='kpi'] { display: none; }
  .dash-bars i:nth-last-child(n + 7) { display: none; }
}

/* 560–779 — 6 columns. THE STATUS MATRIX DROPS: it cannot lose columns
   without lying about which channels exist. The calendar drops to 7 × 2.
   Wide tiles stop being wide and take the full sheet. */
@container (max-width: 779px) {
  .dash { --dash-cols: 6; --dash-chrome-h: 40px; }
  .dash-body > [data-part='matrix'] { display: none; }
  .dash-cal-cell:nth-child(n + 15) { display: none; }
  .dash-body > [data-part='feed'],
  .dash-body > [data-part='transcript'],
  .dash-body > [data-part='lane'] { grid-column: 1 / -1; }
}

/* 400–559 — 4 columns. The BAR SERIES DROPS. One KPI, no status column on
   the feed rows, and every tile takes the full width: a tile narrower than
   four container-columns stacks instead of shrinking. */
@container (max-width: 559px) {
  .dash { --dash-cols: 4; --dash-chrome-h: 36px; --dash-pad: var(--s3); }
  /* The chrome bar's four regions keep clear water between them as the sheet
     narrows: the gap halves before any text is allowed near a neighbour. */
  .dash-chrome { gap: var(--s2); }
  .dash[data-format='wide'],
  .dash[data-format='square'] { aspect-ratio: 3 / 4; }
  .dash-body > [data-part='bars'] { display: none; }
  .dash-body > [data-part='kpi'] ~ [data-part='kpi'] { display: none; }
  .dash-tile { grid-column: 1 / -1; }
  .dash-feed-state { display: none; }
  .dash-feed-row { grid-template-columns: 24px minmax(0, 1fr); }
  .dash-name { font-size: 13px; }
  .dash-lane-label { font-size: 10px; letter-spacing: 0.14em; }
}

/* < 400 — what survives is the sheet's meaning and nothing else: chrome, one
   KPI, the feed titles, the packet track, the tick. FEED SUBLINES DROP
   rather than shrink below their 10.5px floor, and the foot rail goes. */
@container (max-width: 399px) {
  .dash { --dash-cols: 2; --dash-gutter: var(--s2); --dash-row-pad: var(--s3); }
  .dash-feed-sub,
  .dash-lane-label { display: none; }
  .dash-body > [data-part='cal'] { display: none; }
  .dash-foot { display: none; }
  .dash-feed-row { min-height: 44px; }
  .dash-tile-label { font-size: 10px; letter-spacing: 0.14em; }
  /* BAY NN · NAME · LIVE · clock, on one line, to the narrowest sheet the
     site serves. The mono flanks shrink a point and shed some tracking; the
     name column keeps its ellipsis; nothing wraps and nothing may touch the
     rule of record below. */
  .dash-bay { font-size: 10px; letter-spacing: 0.14em; }
  .dash-clock { font-size: 11px; }
  .dash-live { font-size: 10px; letter-spacing: 0.14em; }
}
