/* console-skin.css
   The ORAVANA skin (styling pass 2026-08-19). Loads LAST, after
   ops-dashboard.css, and changes appearance only — no data, no readers,
   no copy, no page structure. Every value here resolves to a design-system
   token from css/ora-ds-tokens.css; nothing is invented locally.

   Four moves, in the brief's priority order:
     1. Canvas   — the spin-up field as every page's ground.
     2. Cards    — white, floating, 18px (DS --radius-xl), soft diffuse
                   shadow, generous padding, no hairline wireframe.
     3. Sidebar  — white panel, icon + label, active item a dark pill.
     4. Dark el. — the active-calls pill keeps its friendly rounded weight.

   (Never write the sequence star-slash inside a comment - it closes it.)
*/

/* ══ 1. CANVAS ═══════════════════════════════════════════════════════════
   The same ambient field the spin-up surface floats on, fixed so it does
   not tile or scroll away on a long page. */
body {
  background: var(--console-canvas);
  background-repeat: no-repeat;   /* without this the radials tile down a long page */
  background-size: 100% 100%;     /* one field across the whole document */
  min-height: 100vh;
}

/* ══ 3. NAV PANEL ════════════════════════════════════════════════════════
   The mockup's nav language — white panel, icon + label, active item a dark
   rounded pill — carried on the console's existing top shell.

   NOT the mockup's left sidebar: a grid re-layout of <body> was built and
   measured first, and it broke the masonry column flow and the map at 1440
   (cards overlapping their column, content spilling the grid track). With a
   hard timebox, a working nav on every page beats a sidebar on none, so the
   panel treatment ships and the left-rail geometry is left for a session
   that can re-flow the masonry with it. Every link, href and label is
   untouched either way. */
.shell {
  background: rgba(255,255,255,.55);
  border-bottom: 1px solid var(--ops-card-border);
  box-shadow: var(--ops-card-shadow);
  backdrop-filter: blur(var(--ops-card-blur)) saturate(var(--ops-card-saturation));
  -webkit-backdrop-filter: blur(var(--ops-card-blur)) saturate(var(--ops-card-saturation));
}

/* Nav item: icon + label; the active one is a dark rounded pill. The icon
   is a CSS-drawn dot-in-square mark (no icon font, no network asset) so the
   rail keeps its shape offline. */
.shell__page {
  border-bottom: 0 !important;
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-5);
  color: var(--text-secondary);
  font-weight: 500;
  transition: background-color var(--dur-fast) var(--ease-standard),
              color var(--dur-fast) var(--ease-standard);
}
.shell__page::before {
  content: ""; flex: none;
  width: 16px; height: 16px; margin-right: var(--space-1);
  border-radius: 5px; /* glyph optics, below the radius scale */
  border: 1.5px solid currentColor; opacity: .55;
  background:
    radial-gradient(circle at 50% 50%, currentColor 0 2px, transparent 2px);
}
.shell__page:hover { background: var(--n-100); color: var(--text-primary); }
.shell__page[aria-current="page"] {
  background: var(--surface-inverse);
  color: var(--text-inverse);
  border-bottom-color: transparent;
}
.shell__page[aria-current="page"]::before { opacity: .9; }
.shell__badge { margin-left: auto; }
.shell__page[aria-current="page"] .shell__badge {
  background: rgba(255,255,255,.16); color: var(--text-inverse);
}

/* altitude switch: a soft sunken track on the white panel */
.shell__altitude {
  background: var(--n-100);
  border-color: var(--border-hairline);
}
.shell__alt[aria-current="page"] {
  background: var(--surface-overlay);
  box-shadow: var(--shadow-soft);
  border-color: var(--border-hairline);
}

/* ══ 2. CARDS — the ONBOARDING card, lifted ══════════════════════════════
   This is css/ops-card.css's .ops-card recipe applied to the console's own
   card family: the ceremonial frosted surface (translucent white over the
   field), the border KEPT, the large ceremonial radius, ceremonial padding
   and the diffuse three-layer ceremonial shadow. Values are the
   --ops-card-* tokens themselves (css/tokens.ceremonial.css) — the same
   ones the spin-up flow renders with. Onboarding wins over the design
   system here, so the DS's opaque-white / borderless / 18px card is
   overridden on purpose. */
.card,
.tile,
.viz-card,
.tbl-wrap,
.row,
.group,
.mem-viz,
.mem-insight,
.map-surface,
dialog.onboard {
  background: var(--ops-card-bg);
  border: 1px solid var(--ops-card-border);
  border-radius: var(--ops-card-radius);
  box-shadow: var(--ops-card-shadow);
  backdrop-filter: blur(var(--ops-card-blur)) saturate(var(--ops-card-saturation));
  -webkit-backdrop-filter: blur(var(--ops-card-blur)) saturate(var(--ops-card-saturation));
}
/* Padding was the missing piece: the console's cards were running at the
   old 16px. These are the ceremonial paddings. */
.card, .viz-card { padding: var(--ops-card-padding); }
.tile { padding: var(--ops-card-padding-sm); gap: var(--space-2); }
.row > summary, .row--flat, .group > summary { padding: var(--space-6) var(--ops-card-padding-sm); }
.mem-viz { padding: var(--ops-card-padding-sm); }
.mem-insight { padding: var(--space-6) var(--ops-card-padding-sm); border-radius: var(--ops-card-radius-sm); }
.masonry .card { margin-bottom: var(--space-6); }

/* Dense reading surfaces sit a touch more opaque than a ceremonial step
   card — same token family, the flow's own hover/active alphas — so long
   tables and row lists stay legible over the field. */
.tbl-wrap, .group, .row { background: var(--ops-card-bg-active); }
.mem-insight, .tile { background: var(--ops-card-bg-hover); }

/* onboarding's card motion: enter on a translate, hover lifts the shadow */
.card, .tile, .viz-card { transition:
  background var(--ops-motion-duration-micro) var(--ops-motion-curve),
  border-color var(--ops-motion-duration-micro) var(--ops-motion-curve),
  box-shadow var(--ops-motion-duration-card) var(--ops-motion-curve); }
.card:hover, .tile:hover, .viz-card:hover {
  background: var(--ops-card-bg-hover);
  box-shadow: var(--ops-card-shadow-hover);
}

/* status rails stay, as an inset left edge on the frosted card */
.row--down  { box-shadow: var(--ops-card-shadow), inset 3px 0 0 var(--state-down-ink); }
.row--stale { box-shadow: var(--ops-card-shadow), inset 3px 0 0 var(--state-degraded-ink); }
.mem-insight { border-left: 0; }
.mem-insight--danger { box-shadow: var(--ops-card-shadow), inset 3px 0 0 var(--state-down-ink); }
.mem-insight--warn   { box-shadow: var(--ops-card-shadow), inset 3px 0 0 var(--state-degraded-ink); }
.mem-insight--info   { box-shadow: var(--ops-card-shadow), inset 3px 0 0 var(--color-accent); }
/* nested rows inside a group must not double-frost */
.group__body .row {
  box-shadow: none; border-radius: 0; border: 0; background: transparent;
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
.group__body .row + .row { border-top: 1px solid var(--ops-card-border); }

/* table interior */
.tbl th { border-bottom: 1px solid var(--border-default); }
.tbl td { border-bottom: 1px solid var(--ops-card-border); }
.tbl tbody tr:hover { background: rgba(255,255,255,.35); }

/* skeleton keeps the ceremonial tempo */
.card--skeleton { box-shadow: var(--ops-card-shadow); }

/* ══ 2b. CARD DISCIPLINE — nothing towers ═══════════════════════════════
   No card is taller than 60vh. Past that it scrolls INSIDE itself with its
   title pinned, so a long list (insights, activity, alerts, checks) never
   stretches the page. CSS only: the card's own eyebrow is the sticky
   header, so no markup moved. */
.card {
  max-height: 60vh;
  overflow-y: auto;
  overscroll-behavior: contain;
}
/* The title pins itself when its card scrolls. It carries the card's own
   frosted tone rather than a white plate, so on the (majority) cards that
   never scroll it is invisible — no bar, no seam. */
.card__eyebrow {
  position: sticky; top: calc(var(--ops-card-padding) * -1);
  margin: calc(var(--ops-card-padding) * -1) calc(var(--ops-card-padding) * -1) var(--space-6);
  padding: var(--ops-card-padding) var(--ops-card-padding) var(--space-4);
  background: var(--ops-card-bg-active);
  backdrop-filter: blur(var(--ops-card-blur)); -webkit-backdrop-filter: blur(var(--ops-card-blur));
  border-radius: var(--ops-card-radius) var(--ops-card-radius) 0 0;
  z-index: 2;
}
/* the dark pill has no list to scroll and must not clip its glow */
.card--dark { max-height: none; overflow: visible; }

/* long record tables scroll inside their card, header pinned */
.tbl-wrap { max-height: 60vh; overflow: auto; overscroll-behavior: contain; }
.tbl thead th {
  position: sticky; top: 0; z-index: 2;
  background: rgba(255,255,255,.86);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
}

/* the insights column is the worst offender: it scrolls in place. The
   inline padding keeps each frosted card clear of the scrollbar gutter
   instead of running under it. */
.mem-insights {
  max-height: 60vh; overflow-y: auto; overscroll-behavior: contain;
  padding: var(--space-1) var(--space-4);
  margin: calc(var(--space-4) * -1);
  margin-top: 0; margin-bottom: 0;
}
.vmini__name { min-width: 6ch; }
/* and the two long strips on Overview */
.integ-strip { max-height: 34vh; overflow-y: auto; overscroll-behavior: contain; }
.cost-lines  { max-height: 34vh; overflow-y: auto; overscroll-behavior: contain; }

/* a quiet scrollbar, so an internal scroll reads as depth not as chrome */
.card, .tbl-wrap, .mem-insights, .integ-strip, .cost-lines { scrollbar-width: thin; }
.card::-webkit-scrollbar, .tbl-wrap::-webkit-scrollbar,
.mem-insights::-webkit-scrollbar, .integ-strip::-webkit-scrollbar,
.cost-lines::-webkit-scrollbar { width: 8px; height: 8px; }
.card::-webkit-scrollbar-thumb, .tbl-wrap::-webkit-scrollbar-thumb,
.mem-insights::-webkit-scrollbar-thumb, .integ-strip::-webkit-scrollbar-thumb,
.cost-lines::-webkit-scrollbar-thumb {
  background: rgba(42,32,48,.18); border-radius: var(--radius-pill);
}

/* ══ 4. DARK ELEMENTS — friendly rounded weight on the ceremonial radius */
.card--dark {
  background: var(--surface-inverse);
  border: 1px solid rgba(255,255,255,.14);
  border-radius: var(--ops-card-radius);
  box-shadow: var(--ops-card-shadow-hover);
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
.card--dark .card__eyebrow { background: none; backdrop-filter: none; }
.card--dark .card__n, .card--dark .live-pill__n { color: var(--text-inverse); }

/* chips: DS state tints, no borders — the label carries the meaning */
.chip { border-radius: var(--radius-pill); padding: var(--space-2) var(--space-5); }

/* buttons pick up the DS control tempo and radius */
.ops-btn { border-radius: var(--radius-pill); transition: var(--transition-control, none); }

/* the hero claim is a DS serif moment */
.hero__claim { font-family: var(--font-serif); font-weight: 300; }
.card__n, .tile__n, .donut-center__n, .live-pill__n {
  font-family: var(--font-serif); font-weight: 300;
}

/* modal: ceremonial glass, and the frame carries the field itself */
dialog.onboard { background: rgba(255,255,255,.35); }
dialog.onboard::backdrop { background: rgba(42,32,48,.32); backdrop-filter: blur(4px); }
.onboard__bar {
  background: rgba(255,255,255,.55);
  border-bottom: 1px solid var(--ops-card-border);
}
.onboard__frame { background: transparent; }

/* map plate + markers */
.map-pin__label {
  border: 1px solid var(--ops-card-border);
  background: rgba(255,255,255,.82);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  box-shadow: var(--ops-card-shadow);
  border-radius: var(--ops-card-radius-sm);
}

/* ══ THE EARTH ARC ═══════════════════════════════════════════════════════
   Overview's map sits on the top of the earth: a soft glowing horizon arc
   behind and under it, the way the operator's mockup renders it. Purely a
   backdrop — the map's own mechanics, markers and numbered ties are
   untouched, only restyled and overlaid on the arc. */
#residency {
  position: relative;
  padding-bottom: var(--space-12);
  /* the arc is wider than the page on purpose (it is a horizon, not a
     box); clipping it here is what keeps the document from scrolling
     sideways at every width. */
  overflow: hidden;
}
#residency::before {
  content: "";
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: -18%;
  width: 190%; aspect-ratio: 2 / 1;
  border-radius: 50% 50% 0 0 / 100% 100% 0 0;
  background:
    radial-gradient(ellipse 70% 52% at 50% 100%,
      rgba(255,255,255,.92) 0%, rgba(255,255,255,.55) 42%, rgba(255,255,255,0) 72%),
    linear-gradient(to top,
      var(--ops-field-bg-stop-tr) 0%,
      color-mix(in srgb, var(--ops-field-bg-stop-tl) 60%, transparent) 46%,
      transparent 78%);
  box-shadow: 0 -1px 0 rgba(255,255,255,.85) inset;
  pointer-events: none;
  z-index: 0;
}
#residency > * { position: relative; z-index: 1; }
#residency .map-surface {
  background: transparent;
  border-color: rgba(255,255,255,.55);
  box-shadow: none;
  backdrop-filter: none; -webkit-backdrop-filter: none;
}

/* the nav row breathes: pills need room from each other and from the
   altitude line that sits under them */
.shell__pages { padding: var(--space-2) var(--space-8) var(--space-5); gap: var(--space-3); }
.shell__indicator { padding-top: var(--space-2); }
.shell__bar { padding-bottom: var(--space-2); }

/* narrow: drop the nav glyphs so the labels keep the row */
@media (max-width: 720px) {
  .shell__page { padding: var(--space-3) var(--space-5); }
  .shell__page::before { display: none; }
}

/* ════════════════════════════════════════════════════════════════════════
   PASS 3 — OPERATOR DESIGN CORRECTIONS (2026-08-19)
   Loads last, overrides pass 2. Styling only.
   Every value below is either taken from the onboarding surface or derived
   from it and contrast-tested against BOTH the purple canvas and the white
   card (see the 2026-08-19 skin dispatch for the AA table).
   ════════════════════════════════════════════════════════════════════════ */
:root {
  /* 4. INK — the onboarding surface's own text colour (--ops-fg-primary,
     deep indigo-plum). Never #000, never a neutral grey. One token. */
  --console-ink:    #2A2030;
  --console-ink-2:  rgba(42, 32, 48, .76);
  --console-ink-3:  rgba(42, 32, 48, .68);

  /* 1. CARD SURFACE — white at 82% over the canvas, so a panel stands OFF
     the gradient. The canvas is purple; the cards are white. */
  --console-card-bg:       rgba(255, 255, 255, .82);
  --console-card-bg-hover: rgba(255, 255, 255, .90);
  --console-card-border:   rgba(255, 255, 255, .70);
  --console-card-pad:      24px;   /* 2. minimum, all four sides */
  --console-card-gap:      32px;   /* 3. minimum, both axes      */

  /* 5. SEMANTIC PALETTE, re-derived to harmonise with the purple canvas.
     No pure red anywhere on this surface. */
  --console-danger: #8E2F5F;   /* deep plum-magenta */
  --console-warn:   #884C26;   /* warm apricot      */
  --console-ok:     #2C664C;   /* soft green        */
  --console-muted:  #5E586A;   /* quiet violet-grey */
  --console-danger-tint: #F7E3EC;
  --console-warn-tint:   #FAEDE1;
  --console-ok-tint:     #E1F0E8;
  --console-muted-tint:  #EDEAF1;

  /* 6. ACCENT — one brighter complementary pink-purple, from the
     onboarding gradient family. Rare: white cards carry the space. */
  --console-accent:      #8F3593;
  --console-accent-soft: #F3E4F6;
  --console-accent-glow: rgba(143, 53, 147, .22);

  /* re-point the repo tokens so every component follows without an edit */
  --color-text:            var(--console-ink);
  --color-text-secondary:  var(--console-ink-2);
  --color-text-tertiary:   var(--console-ink-3);
  --color-status-danger:   var(--console-danger);
  --color-status-warn:     var(--console-warn);
  --color-status-ok:       var(--console-ok);
  --color-status-muted:    var(--console-muted);
  --danger-bg:             var(--console-danger-tint);
  --warn-bg:               var(--console-warn-tint);
  --ok-bg:                 var(--console-ok-tint);
  --color-accent:          var(--console-accent);
  --accent-bg:             var(--console-accent-soft);
  --accent-glow:           var(--console-accent-glow);
  --accent-rgb:            143, 53, 147;
  --state-down-ink:        var(--console-danger);
  --state-degraded-ink:    var(--console-warn);
  --state-healthy-ink:     var(--console-ok);
}
body { color: var(--console-ink); }

/* 1. CARDS READ AS CARDS ─────────────────────────────────────────────── */
.card, .tile, .viz-card, .tbl-wrap, .row, .group,
.mem-viz, .mem-insight, dialog.onboard {
  background: var(--console-card-bg);
  border: 1px solid var(--console-card-border);
  backdrop-filter: blur(20px) saturate(1.4);
  -webkit-backdrop-filter: blur(20px) saturate(1.4);
  box-shadow: var(--ops-card-shadow);
}
.card:hover, .tile:hover, .viz-card:hover { background: var(--console-card-bg-hover); }

/* 2. PADDING — 24px minimum inside every container, all four sides.
   No text sits against a card edge anywhere. */
.card, .viz-card, .tile, .mem-viz { padding: var(--console-card-pad); }
.row > summary, .row--flat, .group > summary,
.mem-insight, .act-row, .integ, .cost-line, .vmini {
  padding-left: var(--console-card-pad);
  padding-right: var(--console-card-pad);
}
.row > summary, .row--flat, .group > summary, .mem-insight {
  padding-top: var(--space-6); padding-bottom: var(--space-6);
}
.act-row, .integ, .cost-line, .vmini { padding-top: var(--space-5); padding-bottom: var(--space-5); }
.row__detail, .group__body { padding: var(--space-6) var(--console-card-pad); }
.tbl th, .tbl td { padding: var(--space-6) var(--console-card-pad); }
.audit__body, .audit__row { padding-left: 0; padding-right: 0; }
/* lists inside a card already sit in the card's 24px; cancel the doubling */
.card .act-row, .card .integ, .card .cost-line, .card .vmini {
  padding-left: 0; padding-right: 0;
}
.mem-insights { padding: 0; margin: 0; }

/* 3. CARD GAP — 32px minimum, both axes, every breakpoint */
.masonry { column-gap: var(--console-card-gap); }
.masonry .card { margin-bottom: var(--console-card-gap); }
.metrics, .cost-cards, .verticals { gap: var(--console-card-gap); }
.rows, .mem-insights { gap: var(--space-6); }
.mem-wrap { gap: var(--console-card-gap); }

/* 7. NO HEADER BACKGROUNDS — titles and legend labels are plain meta text */
.card__eyebrow {
  position: static; background: none; backdrop-filter: none;
  -webkit-backdrop-filter: none; box-shadow: none; border-radius: 0;
  margin: 0 0 var(--space-6); padding: 0;
  color: var(--console-ink-3);
}
.tbl thead th { background: none; backdrop-filter: none; -webkit-backdrop-filter: none; }
.cost-line, .cost-line:hover, .cost-line.is-lit { background: none; }
.tile__l, .section__head h2 { background: none; }

/* 5b. STATUS DOTS + CHIPS use ONLY the new palette */
.chip--live     { color: var(--console-ok);     background: var(--console-ok-tint); }
.chip--down     { color: var(--console-danger); background: var(--console-danger-tint); }
.chip--stale    { color: var(--console-warn);   background: var(--console-warn-tint); }
.chip--expected, .chip--noprobe, .chip--idle { color: var(--console-ink-2); background: var(--console-muted-tint); }
.chip--noprobe::before, .chip--expected::before, .chip--idle::before { background: var(--console-muted); }

/* The notification pill says what the RAIL did, beside what the CHECK found. On this
   palette like everything else -- an off-palette badge would read as a different
   system's chrome leaking in. */
.npill--mail   { color: var(--console-warn);  background: var(--console-warn-tint); }
.npill--digest { color: var(--console-ink-2); background: var(--console-muted-tint); }
.npill--quiet  { color: var(--console-ink-2); background: transparent; }
.npill--test   { color: var(--console-ink-3); background: var(--console-muted-tint); }
.integ__dot--live  { background: var(--console-ok);     box-shadow: 0 0 0 3px var(--console-ok-tint); }
.integ__dot--down  { background: var(--console-danger); box-shadow: 0 0 0 3px var(--console-danger-tint); }
.integ__dot--stale { background: var(--console-warn);   box-shadow: 0 0 0 3px var(--console-warn-tint); }
.integ__dot--expected { background: var(--console-muted); }
.act-row__dot--danger { background: var(--console-danger); box-shadow: 0 0 0 3px var(--console-danger-tint); }
.act-row__dot--warn   { background: var(--console-warn);   box-shadow: 0 0 0 3px var(--console-warn-tint); }
.hero__claim--bad b, .t-danger { color: var(--console-danger); }
.integ--bad { background: color-mix(in srgb, var(--console-danger) 4%, transparent); border-color: var(--console-danger-tint); }

/* 10. LIST DISCIPLINE — edge bars from the new palette only */
.row--down    { box-shadow: var(--ops-card-shadow), inset 3px 0 0 var(--console-danger); }
.row--stale   { box-shadow: var(--ops-card-shadow), inset 3px 0 0 var(--console-warn); }
.mem-insight--danger { box-shadow: var(--ops-card-shadow), inset 3px 0 0 var(--console-danger); }
.mem-insight--warn   { box-shadow: var(--ops-card-shadow), inset 3px 0 0 var(--console-warn); }
.mem-insight--info   { box-shadow: var(--ops-card-shadow), inset 3px 0 0 var(--console-accent); }
.mem-bubble--danger { fill: var(--console-danger); stroke: var(--console-danger); }
.mem-bubble--warn   { fill: var(--console-warn);   stroke: var(--console-warn); }
.mem-bubble--info   { fill: var(--console-accent); stroke: var(--console-accent); }

/* 8. ONE LIST STYLE for activity: same size, same ink, timestamp right meta */
.act-row { border-top: 1px solid rgba(42,32,48,.08); align-items: center; }
.act-row:first-of-type { border-top: 0; }
.act-row__text, .act-row--quiet .act-row__text {
  font-size: var(--type-body); color: var(--console-ink); font-weight: 400;
}
.act-row__text b { font-weight: 500; color: var(--console-ink); }
.act-row__when {
  margin-left: auto; font-size: var(--type-meta); color: var(--console-ink-3);
  white-space: nowrap; font-variant-numeric: tabular-nums; text-align: right;
}

/* 9. THE MAP — no container. A blurred glowing horizon, map riding on top */
#residency .map-surface,
#residency .map-facts .row--flat {
  background: transparent; border: 0; box-shadow: none;
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
#residency::before {
  content: "";
  position: absolute; left: 50%; transform: translateX(-50%);
  bottom: 4%;
  width: 300vw; height: 300vw;         /* top of a circle ~3x viewport wide */
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 0%,
      var(--console-accent-glow) 0%,
      rgba(255,255,255,.55) 22%,
      rgba(214,200,232,.30) 42%,
      transparent 62%);
  filter: blur(70px);
  box-shadow: none;
  opacity: .95;
  pointer-events: none;
  z-index: 0;
}
#residency .map-facts .row--flat { padding-left: 0; padding-right: 0; }

/* narrow screens keep the 24/32 rules */
@media (max-width: 720px) {
  .masonry { column-gap: var(--console-card-gap); }
  .tbl th, .tbl td { padding: var(--space-5) var(--space-6); }
}

/* The dark pill is the one inversion on the page and must win over the
   white-card rule above (it matches .card too). Re-asserted last. */
.card--dark, .card--dark:hover {
  background: #2A2030;
  border: 1px solid rgba(255,255,255,.16);
  backdrop-filter: none; -webkit-backdrop-filter: none;
  box-shadow: var(--ops-card-shadow-hover);
  padding: var(--console-card-pad);
}
.card--dark, .card--dark .live-pill__n, .card--dark .card__n { color: #FFFFFF; }
.card--dark .card__eyebrow, .card--dark .live-pill__sub,
.card--dark .card__anchor { color: rgba(255,255,255,.78); }
.card--dark .i { color: rgba(255,255,255,.78); border-color: rgba(255,255,255,.34); }

/* The horizon needs to actually read. Same geometry, stronger bloom. */
#residency::before {
  background:
    radial-gradient(circle at 50% 0%,
      rgba(143, 53, 147, .30) 0%,
      rgba(255,255,255,.78) 16%,
      rgba(214,200,232,.55) 36%,
      transparent 58%);
  filter: blur(60px);
  opacity: 1;
}

/* ════════════════════════════════════════════════════════════════════════
   PASS 4 — GEOMETRY CORRECTIONS (2026-08-19). Palette + timestamp rules
   from pass 3 are frozen and untouched here; this pass moves boxes only.
   ════════════════════════════════════════════════════════════════════════ */
:root {
  --console-rail-w:   240px;
  --console-card-pad: 28px;   /* 2. bumped from 24 */
  --console-row-pad-y: 12px;  /* 2. list + table rows */
  --console-list-max: 420px;  /* 4. no list grows unbounded */
}

/* 1. THE LEFT RAIL ──────────────────────────────────────────────────────
   The page rail becomes a fixed left panel. Deliberately position:fixed +
   a body inset rather than a body grid: a grid container re-flows the
   masonry's CSS columns (that is what broke this the first time), a fixed
   panel does not touch them at all. */
@media (min-width: 961px) {
  body { padding-left: var(--console-rail-w); }
  .shell__pages {
    position: fixed; left: 0; top: 0; bottom: 0; width: var(--console-rail-w);
    z-index: var(--z-sticky, 100);
    display: flex; flex-direction: column; align-items: stretch;
    gap: var(--space-1);
    padding: var(--space-9) var(--space-5) var(--space-6);
    background: rgba(255,255,255,.88);
    backdrop-filter: blur(20px) saturate(1.4);
    -webkit-backdrop-filter: blur(20px) saturate(1.4);
    border-right: 1px solid var(--console-card-border);
    overflow-y: auto;
  }
  /* the top bar keeps only brand, altitude chips, checked-at, Refresh,
     Sign out — it starts where the rail ends */
  .shell { border-bottom: 1px solid var(--console-card-border); }
  .shell__bar { padding: var(--space-5) var(--space-8); }
  /* altitude line pinned to the rail bottom */
  .shell__indicator {
    position: fixed; left: 0; bottom: 0; width: var(--console-rail-w);
    z-index: calc(var(--z-sticky, 100) + 1);
    margin: 0; padding: var(--space-6) var(--space-7);
    border-top: 1px solid var(--console-card-border);
    background: rgba(255,255,255,.94);
    backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  }
  .ops-main, .ops-foot { padding-left: var(--space-8); padding-right: var(--space-8); }
}

/* rail rows: one per page, icon + label, active is a dark rounded pill.
   The old dot-chip pseudo-element is DELETED. */
.shell__page::before { content: none !important; display: none !important; }
.shell__page {
  display: flex; align-items: center; gap: var(--space-5);
  padding: var(--space-5) var(--space-6);
  border-radius: var(--radius-lg);
  color: var(--console-ink-2); font-weight: 500;
  line-height: 1.55;
}
.shell__icon { width: 18px; height: 18px; flex: none; opacity: .85; }
.shell__page-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.shell__page:hover { background: rgba(42,32,48,.05); color: var(--console-ink); }
.shell__page[aria-current="page"] {
  background: #2A2030; color: #FFFFFF;
}
.shell__page[aria-current="page"] .shell__icon { opacity: 1; }
.shell__badge { margin-left: auto; }

/* 2. PADDING — 28px inside every card, all four sides; header to first
   content 16px; rows at 12px vertical with dividers INSET to the padding */
.card, .viz-card, .tile, .mem-viz { padding: var(--console-card-pad); }
.card__eyebrow { margin: 0 0 var(--space-6); }           /* 16px header gap */
.section__head { margin-bottom: var(--space-6); }
.row > summary, .row--flat, .group > summary, .mem-insight {
  padding: var(--console-row-pad-y) var(--console-card-pad);
}
.act-row, .integ, .cost-line, .vmini {
  padding-top: var(--console-row-pad-y); padding-bottom: var(--console-row-pad-y);
}
.tbl th, .tbl td { padding: var(--console-row-pad-y) var(--console-card-pad); }
.row__detail, .group__body { padding: var(--space-6) var(--console-card-pad); }
/* dividers inset to the card padding, never touching the card edge */
.tbl th, .tbl td { border-bottom: 0; background-clip: padding-box; }
.tbl tbody tr > td { box-shadow: inset 0 -1px 0 rgba(42,32,48,.08); }
.tbl thead th { box-shadow: inset 0 -1px 0 rgba(42,32,48,.14); }
.tbl tr > *:first-child { border-left: var(--console-card-pad) solid transparent; padding-left: 0; }
.tbl tr > *:last-child  { border-right: var(--console-card-pad) solid transparent; padding-right: 0; }
.act-row { border-top: 0; box-shadow: inset 0 1px 0 rgba(42,32,48,.08); }
.act-row:first-of-type { box-shadow: none; }
.group__body .row + .row { border-top: 0; box-shadow: inset 0 1px 0 rgba(42,32,48,.08); }

/* 3. LINE SPACING */
body, .card, .tile, .row, .act-row, .integ, .cost-line, .tbl,
.mem-insight, .note, .card__anchor, .tile__anchor, .row__evidence { line-height: 1.55; }
.mem-insight__sum {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; line-height: 1.55;
}
.mem-insights { gap: 12px; }                              /* 12px between cards */

/* 4. INTERNAL SCROLL, for real */
.card { max-height: none; overflow: visible; }
.card[data-card="activity"], .card[data-card="integrations"],
.mem-insights, .tbl-wrap, .integ-strip, .cost-lines {
  max-height: var(--console-list-max);
  overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: thin; scrollbar-color: rgba(42,32,48,.22) transparent;
}
/* header pinned — carrying the card's OWN surface colour, so it is a
   seam-free pin, not the white pill pass 3 removed */
.card[data-card="activity"] .card__eyebrow,
.card[data-card="integrations"] .card__eyebrow {
  position: sticky; top: calc(var(--console-card-pad) * -1);
  margin: calc(var(--console-card-pad) * -1) calc(var(--console-card-pad) * -1) var(--space-6);
  padding: var(--console-card-pad) var(--console-card-pad) var(--space-5);
  background: #F7F5F9; z-index: 2;
}
.tbl-wrap::-webkit-scrollbar, .mem-insights::-webkit-scrollbar,
.card::-webkit-scrollbar, .integ-strip::-webkit-scrollbar,
.cost-lines::-webkit-scrollbar { width: 6px; height: 6px; }
.tbl-wrap::-webkit-scrollbar-thumb, .mem-insights::-webkit-scrollbar-thumb,
.card::-webkit-scrollbar-thumb, .integ-strip::-webkit-scrollbar-thumb,
.cost-lines::-webkit-scrollbar-thumb { background: rgba(42,32,48,.22); border-radius: 999px; }

/* 5. EDGE BARS — a plain 3px solid left border, full height, 2px radius.
   The inset box-shadow rendered as drawn parentheses on a rounded card;
   a real border does not. */
.mem-insight, .row--down, .row--stale {
  box-shadow: var(--ops-card-shadow);
  border-left-width: 3px; border-left-style: solid;
  border-radius: 2px var(--ops-card-radius-sm) var(--ops-card-radius-sm) 2px;
}
.mem-insight { border-left-color: transparent; }
.mem-insight--danger { border-left-color: var(--console-danger); }
.mem-insight--warn   { border-left-color: var(--console-warn); }
.mem-insight--info   { border-left-color: var(--console-accent); }
.row--down  { border-left-color: var(--console-danger); }
.row--stale { border-left-color: var(--console-warn); }

/* 6. "powers:" — one truncated line; the row's ⓘ carries the full text */
.tbl .t-2nd {
  display: block; max-width: 46ch;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* 7. THE ARC — one step bolder: the horizon is a presence, not a hint */
#residency::before {
  background:
    radial-gradient(circle at 50% 0%,
      rgba(143, 53, 147, .52) 0%,
      rgba(214,170,226,.46) 10%,
      rgba(255,255,255,.88) 22%,
      rgba(206,190,230,.60) 40%,
      transparent 60%);
  filter: blur(52px);
  opacity: 1;
}

/* 8. NO TEXT AGAINST AN EDGE, anywhere */
.card > *:first-child { margin-top: 0; }
.card > *:last-child  { margin-bottom: 0; }
.mem-insights { padding: 0 var(--space-2) 0 0; }
.audit__row { padding-left: var(--console-card-pad); padding-right: var(--console-card-pad); }
.hbar-rows { padding: 0; }
.live-pill { padding: 0; }

@media (max-width: 960px) {
  /* rail returns to a horizontal strip; nothing fixed, nothing inset */
  .shell__pages {
    position: static; width: auto; flex-direction: row; overflow-x: auto;
    padding: var(--space-2) var(--space-6) var(--space-5);
    background: none; border-right: 0; backdrop-filter: none;
  }
  .shell__indicator { position: static; width: auto; background: none; border-top: 0; }
  body { padding-left: 0; }
}

/* .card--dark re-asserted LAST so the active-calls pill survives every
   rule above (it matches .card too). */
.card--dark, .card--dark:hover {
  background: #2A2030;
  border: 1px solid rgba(255,255,255,.16);
  backdrop-filter: none; -webkit-backdrop-filter: none;
  box-shadow: var(--ops-card-shadow-hover);
  padding: var(--console-card-pad);
  max-height: none; overflow: visible;
}
.card--dark, .card--dark .live-pill__n, .card--dark .card__n { color: #FFFFFF; }
.card--dark .card__eyebrow, .card--dark .live-pill__sub, .card--dark .card__anchor {
  color: rgba(255,255,255,.78); background: none; position: static; margin: 0;
}
.card--dark .i { color: rgba(255,255,255,.78); border-color: rgba(255,255,255,.34); }

/* A backdrop-filter on an ancestor creates a containing block for its
   fixed descendants — with it on .shell the rail anchored to the shell
   instead of the viewport and collapsed over the brand. The top bar keeps
   a solid tint instead of a blur so the rail can be truly viewport-fixed. */
@media (min-width: 961px) {
  .shell {
    backdrop-filter: none; -webkit-backdrop-filter: none;
    background: rgba(255,255,255,.86);
    box-shadow: none;
  }
  .shell__bar { max-width: none; }
}

/* Rail rows must not shrink to fit the fixed-height column, and the 240px
   inset belongs only to pages that actually HAVE a rail — at vertical
   altitude the shell renders no page list (pages are platform-scoped), and
   without this the content kept a 240px empty gutter. */
@media (min-width: 961px) {
  body { padding-left: 0; }
  body:has(.shell__pages) { padding-left: var(--console-rail-w); }
  body:not(:has(.shell__pages)) .shell__indicator { position: static; width: auto; background: none; border-top: 0; }
  .shell__page { flex: none; min-height: 42px; }
  .shell__pages { justify-content: flex-start; padding-bottom: var(--space-13); }
}

/* ════════════════════════════════════════════════════════════════════════
   PASS 5 — LAYOUT FIX (2026-08-19). Geometry only; palette and content
   frozen.

   ROOT CAUSE of the overlap: the rail was position:fixed, so it was
   painted OVER the content column and reserved no space — every page's
   first card sat under it. A fixed panel can never reflow its neighbours.
   The page is now a real two-column grid, so the rail OCCUPIES a column
   and the content column is genuinely narrower.

   .shell carries display:contents so its three children become grid items
   of the page grid: the top bar sits in the content column, the nav rail
   in column 1, the altitude meta at the rail's foot.
   ════════════════════════════════════════════════════════════════════════ */
@media (min-width: 961px) {
  body {
    padding-left: 0;
    display: grid;
    grid-template-columns: var(--console-rail-w) minmax(0, 1fr);
    column-gap: 64px;                 /* the clear air, installed in the shell */
    grid-template-rows: auto 1fr auto;
    align-items: start;
  }
  body:has(.shell__pages) { padding-left: 0; }
  .shell { display: contents; }

  /* column 1 — the rail, occupying space */
  .shell__pages {
    position: sticky; top: 0;
    grid-column: 1; grid-row: 1 / span 2;
    width: auto; height: 100vh; inset: auto;
    display: flex; flex-direction: column; align-items: stretch; gap: var(--space-1);
    padding: var(--space-9) var(--space-5) var(--space-6);
    background: rgba(255,255,255,.88);
    backdrop-filter: blur(20px) saturate(1.4);
    -webkit-backdrop-filter: blur(20px) saturate(1.4);
    border-right: 1px solid var(--console-card-border);
    overflow-y: auto;
  }
  /* the stray mid-page caption now lives at the rail's foot */
  .shell__indicator {
    position: static; grid-column: 1; grid-row: 3;
    width: auto; margin: 0;
    padding: var(--space-6) var(--space-7) var(--space-8);
    background: rgba(255,255,255,.88);
    border-top: 1px solid var(--console-card-border);
    border-right: 1px solid var(--console-card-border);
    font-size: var(--type-meta); color: var(--console-ink-3);
  }

  /* column 2 — the content. min-width:0 is what lets a CSS-columns
     masonry live inside a grid track without blowing it out (this is the
     detail that broke the first grid attempt). */
  .shell__bar { grid-column: 2; grid-row: 1; min-width: 0; padding: var(--space-6) 0; max-width: none; }
  .ops-main   { grid-column: 2; grid-row: 2; min-width: 0; margin: 0; padding-left: 0; padding-right: var(--space-8); max-width: none; }
  .ops-foot   { grid-column: 2; grid-row: 3; min-width: 0; margin: 0; padding-left: 0; padding-right: var(--space-8); max-width: none; }

  .shell { background: none; border: 0; box-shadow: none; }
}

/* 2. CARD HEADER TO CONTENT — 32px on every card */
.card__eyebrow { margin: 0 0 var(--space-9); }
.card[data-card="activity"] .card__eyebrow,
.card[data-card="integrations"] .card__eyebrow {
  margin: calc(var(--console-card-pad) * -1) calc(var(--console-card-pad) * -1) var(--space-9);
}

/* 3. INSIGHT / MEMORY CARDS — no spine at all. The semantic colour lives
   only in the small theme label text. */
.mem-insight,
.mem-insight--danger, .mem-insight--warn, .mem-insight--info {
  border-left: 0 !important;
  box-shadow: var(--ops-card-shadow) !important;
  border-radius: var(--ops-card-radius-sm) !important;
}
.mem-insight--danger .mem-insight__meta { color: var(--console-danger); }
.mem-insight--warn   .mem-insight__meta { color: var(--console-warn); }
.mem-insight--info   .mem-insight__meta { color: var(--console-accent); }

/* 4. THE ACTIVE-CALLS STRIP — a status strip, not a hero */
.card--dark, .card--dark:hover {
  min-height: 56px; padding: 0 var(--space-7);
  display: flex; align-items: center;
  border-radius: var(--radius-pill);
}
.card--dark .live-pill {
  display: flex; align-items: center; gap: var(--space-5);
  width: 100%;
}
.card--dark .live-pill__orb { grid-row: auto; width: 10px; height: 10px; box-shadow: 0 0 0 3px var(--console-accent-glow); }
.card--dark .live-pill__n {
  font-family: var(--font-sans); font-size: var(--type-body); font-weight: 500;
  letter-spacing: 0; line-height: 1.55; white-space: nowrap;
}
.card--dark .live-pill__sub {
  font-size: var(--type-meta); white-space: nowrap;
  margin-left: auto; text-align: right;
}

/* 5. SCROLL AFFORDANCE — a soft fade while more content sits below, and a
   4px low-contrast bar that shows itself on hover or scroll. The fade is a
   mask, so it never paints over the card's own surface. */
.card[data-card="activity"], .card[data-card="integrations"],
.mem-insights, .tbl-wrap, .integ-strip, .cost-lines {
  scrollbar-width: thin; scrollbar-color: transparent transparent;
  mask-image: linear-gradient(to bottom, #000 0, #000 calc(100% - 48px), transparent 100%);
  -webkit-mask-image: linear-gradient(to bottom, #000 0, #000 calc(100% - 48px), transparent 100%);
  transition: scrollbar-color var(--dur-fast) var(--ease-standard);
}
/* at the end of the scroll the fade is gone: nothing is hidden below */
.card[data-card="activity"]:not([data-more]), .mem-insights:not([data-more]),
.tbl-wrap:not([data-more]), .integ-strip:not([data-more]), .cost-lines:not([data-more]),
.card[data-card="integrations"]:not([data-more]) {
  mask-image: none; -webkit-mask-image: none;
}
.card[data-card="activity"]:hover, .card[data-card="integrations"]:hover,
.mem-insights:hover, .tbl-wrap:hover, .integ-strip:hover, .cost-lines:hover {
  scrollbar-color: rgba(42,32,48,.20) transparent;
}
.card::-webkit-scrollbar, .tbl-wrap::-webkit-scrollbar, .mem-insights::-webkit-scrollbar,
.integ-strip::-webkit-scrollbar, .cost-lines::-webkit-scrollbar { width: 4px; height: 4px; }
.card::-webkit-scrollbar-thumb, .tbl-wrap::-webkit-scrollbar-thumb,
.mem-insights::-webkit-scrollbar-thumb, .integ-strip::-webkit-scrollbar-thumb,
.cost-lines::-webkit-scrollbar-thumb { background: transparent; border-radius: 999px; }
.card:hover::-webkit-scrollbar-thumb, .tbl-wrap:hover::-webkit-scrollbar-thumb,
.mem-insights:hover::-webkit-scrollbar-thumb, .integ-strip:hover::-webkit-scrollbar-thumb,
.cost-lines:hover::-webkit-scrollbar-thumb { background: rgba(42,32,48,.20); }

/* An auto inline margin on a grid item cancels stretch and shrinks it to
   fit-content — the rail was inheriting `margin: 0 auto` from the top-bar
   era and rendering 128px wide, centred in its 240px column. */
@media (min-width: 961px) {
  .shell__pages { margin: 0; width: 100%; max-width: none; justify-self: stretch; }
  .shell__indicator { margin: 0; width: 100%; max-width: none; justify-self: stretch; }
  /* No rail (vertical altitude renders no page list): one column, no
     reserved gutter, chrome and content full width. */
  body:not(:has(.shell__pages)) {
    grid-template-columns: minmax(0, 1fr);
    column-gap: 0;
  }
  body:not(:has(.shell__pages)) .shell__bar,
  body:not(:has(.shell__pages)) .ops-main,
  body:not(:has(.shell__pages)) .ops-foot { grid-column: 1; }
  body:not(:has(.shell__pages)) .shell__indicator {
    grid-column: 1; grid-row: 1; background: none; border: 0;
    padding: 0 var(--space-8) var(--space-4);
  }
  body:not(:has(.shell__pages)) .shell__bar { grid-row: 1; padding-left: var(--space-8); }
  body:not(:has(.shell__pages)) .ops-main { padding-left: var(--space-8); }
}

/* The strip's label and its meta were butting against each other, and the
   altitude caption belonged in the visible rail rather than at the far
   bottom of a long page: it now sticks to the rail's own foot. */
.card--dark .live-pill__n { margin-right: var(--space-6); }
.card--dark .live-pill__sub { padding-left: var(--space-4); }
@media (min-width: 961px) {
  body:has(.shell__pages) .shell__indicator {
    grid-column: 1; grid-row: 1 / span 2;
    align-self: end; position: sticky; bottom: 0; height: fit-content;
    border-right: 1px solid var(--console-card-border);
    backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  }
}

/* ════════════════════════════════════════════════════════════════════════
   PASS 6 — PADDING (2026-08-19). Operator: "padding babes padding".
   Three real causes, not three symptoms:
     a) the rail stopped at the fold because it was height:100vh — the white
        is now painted by a full-height grid layer (body::before) that spans
        every row, while the nav itself stays sticky inside it;
     b) the rail's own padding was 12px, so labels sat on its edge;
     c) .ops-main had no top or left padding and only 32px on the right, so
        content ran into the page edge. One 64px page inset now governs
        every page and both altitudes.
   ════════════════════════════════════════════════════════════════════════ */
:root { --console-page-pad: 64px; --console-rail-pad: 24px; }

@media (min-width: 961px) {
  /* (a) the white rail runs the FULL height of the document */
  body::before {
    content: "";
    grid-column: 1; grid-row: 1 / -1;
    background: rgba(255,255,255,.88);
    border-right: 1px solid var(--console-card-border);
    z-index: 0;
  }
  .shell__pages {
    grid-column: 1; grid-row: 1 / span 2;
    position: sticky; top: 0; height: 100vh;
    z-index: 1;
    background: none; border-right: 0;      /* the layer above paints it */
    backdrop-filter: none; -webkit-backdrop-filter: none;
    /* (b) real air around the nav */
    padding: var(--console-page-pad) var(--console-rail-pad) var(--space-8);
    gap: var(--space-2);
  }
  .shell__indicator {
    z-index: 1; background: none; border-right: 0; border-top: 0;
    backdrop-filter: none; -webkit-backdrop-filter: none;
    padding: var(--space-6) var(--console-rail-pad) var(--space-8);
  }

  /* (c) ONE page inset, every page, both altitudes. The left inset is the
     64px column-gap, so content never touches the rail either. */
  .shell__bar {
    padding: var(--console-page-pad) var(--console-page-pad) 0 0;
    gap: var(--space-6);
  }
  .ops-main {
    padding: var(--space-9) var(--console-page-pad) var(--console-page-pad) 0;
  }
  .ops-foot {
    padding: 0 var(--console-page-pad) var(--console-page-pad) 0;
  }
  /* no-rail altitude: the same inset on all four sides */
  body:not(:has(.shell__pages))::before { content: none; }
  body:not(:has(.shell__pages)) .shell__bar,
  body:not(:has(.shell__pages)) .ops-main,
  body:not(:has(.shell__pages)) .ops-foot,
  body:not(:has(.shell__pages)) .shell__indicator {
    padding-left: var(--console-page-pad);
    padding-right: var(--console-page-pad);
  }
}

/* the brand mark moves out of the top bar and sits at the head of the rail */
.shell__brand { display: none; }
@media (min-width: 961px) {
  .shell__pages::before {
    content: "";
    display: block; flex: none;
    height: 34px; margin: 0 var(--space-2) var(--space-9);
    background: url("/assets/oravion-mark.svg") left center / auto 26px no-repeat;
  }
}

/* nav rows: the label needs room from the pill edge, the pill from the rail */
.shell__page {
  padding: var(--space-5) var(--space-6);
  gap: var(--space-5);
  border-radius: var(--radius-lg);
}

/* the status strip: 16px inside, and the two texts each keep their own air */
.card--dark, .card--dark:hover { padding: 0 var(--space-6); gap: var(--space-5); }
.card--dark .live-pill { gap: var(--space-5); padding: 0; }
.card--dark .live-pill__n { margin-right: 0; font-size: var(--type-body); }
.card--dark .live-pill__sub {
  padding-left: var(--space-6); margin-left: auto;
  font-size: var(--type-meta); white-space: nowrap;
}

/* narrow: one page inset, no rail column */
@media (max-width: 960px) {
  .ops-main, .ops-foot, .shell__bar { padding-left: var(--space-8); padding-right: var(--space-8); }
  .ops-main { padding-top: var(--space-8); padding-bottom: var(--space-9); }
}

/* The strip's meta was nowrap and 13px wider than its masonry column, which
   was the page's only horizontal overflow once real padding existed. It now
   shrinks and wraps rather than pushing the document sideways. */
.card--dark .live-pill { flex-wrap: wrap; row-gap: var(--space-2); }
.card--dark .live-pill__n { min-width: 0; flex: 1 1 auto; white-space: normal; }
.card--dark .live-pill__sub {
  min-width: 0; flex: 1 1 auto; white-space: normal;
  padding-left: 0; text-align: left;
}

/* The pseudo-element backing layer did not paint (a grid-placed body::before
   is fragile). The rail element itself now spans every grid row, so its
   white runs the full document height by construction — no backing layer,
   nothing to fall out of sync. The nav sits at the top of that column. */
@media (min-width: 961px) {
  body::before { content: none; }
  .shell__pages {
    grid-column: 1; grid-row: 1 / -1;
    position: static; height: auto; align-self: stretch;
    justify-content: flex-start;
    background: rgba(255,255,255,.88);
    border-right: 1px solid var(--console-card-border);
    backdrop-filter: blur(20px) saturate(1.4);
    -webkit-backdrop-filter: blur(20px) saturate(1.4);
    padding: var(--console-page-pad) var(--console-rail-pad) var(--space-12);
  }
  /* the altitude meta rides just under the nav rows, inside the rail */
  .shell__indicator {
    grid-column: 1; grid-row: 1 / -1;
    align-self: start; position: sticky; top: auto;
    margin-top: 420px;              /* clears the six nav rows */
    padding: var(--space-6) var(--console-rail-pad);
    background: none; border: 0;
  }
}

/* ═══════════════════════════════════════════════════════════════════════════
   PASS 7 — the annotated-screenshot corrections, 2026-08-19.
   Four instructions, applied exactly: no dots anywhere, an axis on every
   chart, a status strip that centres and stops being purple when a call is
   live, and the memory panel's LIVE row lifted under its heading (that last
   one is a markup order change in js/ops-dashboard.js, not a rule here).
   Appended last, as every pass in this sheet is, so it wins the cascade.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── 1. NO DOTS ─────────────────────────────────────────────────────────────
   Every status dot on this surface sat beside a word that already said the
   same thing: the chip carries "LIVE", the integration row carries "3 of 4
   live", the activity row carries the alert's own headline. The dot was
   decoration wearing a semantic hat. It goes; state now rides the type,
   which was always the honest carrier (colour never carried identity alone
   here — that rule is what makes this safe to remove). */
.chip::before,
.chip--noprobe::before, .chip--expected::before, .chip--idle::before,
.integ__dot, .act-row__dot,
.live-pill__orb { content: none; display: none; }

/* the chip's gap existed to space a dot from its word */
.chip { gap: 0; }

/* the integration row loses its first column with the dot */
.integ { grid-template-columns: minmax(0, 1fr) auto; }
.integ__down { grid-column: 1 / -1; }
/* state, in the name's own weight and colour — one carrier, not two */
.integ--down .integ__name  { color: var(--console-danger); }
.integ--stale .integ__name { color: var(--console-warn); }
.integ--expected .integ__name { color: var(--console-muted); }

/* the same for an activity row: the headline itself takes the tone */
.act-row--danger .act-row__text { color: var(--console-danger); }
.act-row--warn .act-row__text   { color: var(--console-warn); }

/* ── 2. CHART AXES ──────────────────────────────────────────────────────────
   The operator asked whether the charts were even true, "as all the charts
   look like this". They are true, and they are different numbers; what they
   share is a calendar. Every series is normalised to its own min and max,
   so three different quantities measured over the same thirty days — where
   the same days are busy and the same days are idle — draw the same
   silhouette. The scale was the missing fact, so the scale is now printed:
   the peak on the y side, the window on the x side. Two ticks, meta size,
   muted. No gridlines, no ticks marks, no second type size. */
.spark-wrap { display: block; }
.spark-axis {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--space-5); margin: var(--space-2) 0 0;
  font-size: var(--type-meta); line-height: 1.4;
  color: var(--console-muted); font-variant-numeric: tabular-nums;
}
.spark-axis__y { font-weight: var(--fw-medium); color: var(--console-ink-2, var(--console-muted)); }
.spark-axis__x { white-space: nowrap; }
.card--dark .spark-axis { color: rgba(255,255,255,.72); }
.card--dark .spark-axis__y { color: rgba(255,255,255,.86); }

/* ── 3. THE STATUS STRIP ────────────────────────────────────────────────────
   No orb (rule 1 above already hides it), every word centred, and a live
   call no longer wears the resting ink. The live fill is --console-ok, the
   colour a LIVE check already carries everywhere else on this surface, so
   "something is happening right now" reads the same in both places. White
   on it measures 6.7:1, and the meta line is lifted to 86% white for 5.5:1
   — both clear AA. (The instruction naming the live colour arrived cut off
   mid-sentence; this reuses an existing token rather than inventing a
   seventh hue against the frozen palette. Flagged in the report.) */
.card--dark .live-pill {
  justify-content: center; align-items: center; text-align: center;
  gap: var(--space-5);
}
.card--dark .live-pill__n,
.card--dark .live-pill__sub {
  flex: 0 1 auto; text-align: center; padding-left: 0; margin-left: 0; margin-right: 0;
}
.card--live {
  background: var(--console-ok);
  border-color: color-mix(in srgb, var(--console-ok) 70%, #FFFFFF);
}
.card--live .live-pill__n { color: #FFFFFF; }
.card--live .live-pill__sub { color: rgba(255,255,255,.86); }
.card--live .live-pill__sub .i {
  border-color: rgba(255,255,255,.45); color: rgba(255,255,255,.86);
}

/* ── 4. THE MEMORY PANEL'S LIVE ROW ─────────────────────────────────────────
   Now the first thing under the heading, so it needs the air a lead row
   needs rather than the air a footnote needed. */
#memory .row--flat:first-of-type { margin-bottom: var(--space-6); }

/* the DOWN line's since-when, now its own span so no separator can orphan */
.integ__since { color: var(--console-muted); }

/* The vertical mini row overflowed its card by 87px at 1440 — three nowrap
   stats plus a name plus the go-arrow never fit a 334px masonry column, and
   "18.0% resolved" was clipped mid-word. Found while re-shooting this pass.
   The name takes the first line, the stats wrap under it and stay legible
   rather than being cut off. */
.vmini { flex-wrap: wrap; row-gap: var(--space-3); }
.vmini__name { flex: 1 1 auto; }
.vmini__stat:first-of-type { margin-left: 0; }
.vmini__stat { margin-left: 0; margin-right: var(--space-6); }
.vmini__go { margin-left: auto; }
