/* =============================================================================
   ryderkatz.com — Portal styles
   -----------------------------------------------------------------------------
   Loaded only by portal.html / portal-*.html. Builds on global.css tokens.
   The portal accent is the P2 graphite accent (set by body[data-accent="admin"]
   in global.css, light+dark). Green survives only as the admin-edge signal and
   the semantic --tone-green — never as a default surface tint.
============================================================================= */

/* Declared on body, not :root: a custom property computes where it's declared,
   and --accent only exists at body[data-accent] level — on :root this would
   freeze to the html-level default accent. */
body { --portal: var(--accent); --portal-2: var(--accent-2); }

/* Seamless-grid materials: one structural line token (a touch stronger than the
   card hairline so shared 1px cell edges read) and one OPAQUE cell surface —
   dashboard panels are cells of a single full-bleed grid, not floating boxes. */
:root {
  --grid-line: color-mix(in srgb, var(--border-hi) 45%, var(--hairline));
  --cell-bg: color-mix(in srgb, var(--bg-elev) 55%, var(--bg));
  /* The intentional palette: pillar hues as theme-aware tones — dark -2
     steps for ink on the light surface, bright -1 steps on dark. Every
     widget + KPI stat carries one, so the board reads in color families
     instead of one green tone. */
  --tone-cyan:   var(--c-cyan-2);
  --tone-violet: var(--c-violet-2);
  --tone-coral:  var(--c-coral-2);
  --tone-mint:   var(--c-mint-2);
  --tone-amber:  var(--c-amber-2);
  --tone-green:  var(--c-admin);
}
:root[data-theme="dark"] {
  --tone-cyan:   var(--c-cyan-1);
  --tone-violet: var(--c-violet-1);
  --tone-coral:  var(--c-coral-1);
  --tone-mint:   var(--c-mint-1);
  --tone-amber:  var(--c-amber-1);
  --tone-green:  var(--c-admin-2);
}

.portal-head { padding-top: 0; }
.portal-head .section-num { color: var(--portal-2); }

/* === Locked state (anonymous) ============================================= */
.portal-lock {
  min-height: 60vh; display: grid; place-items: center; padding: 4rem var(--pad-x);
}
/* A page may host two guarded sections (e.g. Shop = Software + Build Runner);
   for a signed-out visitor each guard appends its own lock card. One is enough. */
.portal-lock ~ .portal-lock { display: none; }
.portal-lock-card {
  text-align: center; max-width: 26rem;
  display: flex; flex-direction: column; align-items: center; gap: 1rem;
  padding: 3rem 2rem; border-radius: var(--radius);
  background: var(--mat-1); border: 1px solid var(--hairline);
}
.portal-lock-glyph {
  width: 64px; height: 64px; display: grid; place-items: center;
  font-size: 30px; border-radius: 18px; color: var(--portal-2);
  background: color-mix(in srgb, var(--portal) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--portal) 28%, transparent);
}
.portal-lock-card h2 { margin: 0; font-size: 1.5rem; }
.portal-lock-card p { color: var(--fg-dim); margin: 0; }
.portal-lock-back { font-family: var(--mono); font-size: 12px; color: var(--fg-mute); margin-top: .5rem; }
.portal-lock-back:hover { color: var(--portal-2); }

/* =============================================================================
   Command-center dashboard
   -----------------------------------------------------------------------------
   A working surface, not a launchpad: one metric rhythm (the KPI rail), then a
   12-column bento of live panels that show their data inline. Dense by intent.
============================================================================= */

/* Source accents, mirroring the transcript viewer. */
:root {
  --src-claude: #e0a84a; --src-gemini: #6ea8ff;
  --src-chatgpt: #3ec5b5; --src-other: var(--c-violet-1);
}

/* === Top strip: KPIs + live pulse ========================================= */
/* No hero title — the green nav highlight is the location signal. The strip is
   the first band of the seamless surface: full-bleed, cells split by 1px lines,
   flush under the tab bar (the hub drops the section's top padding). */
#portal-hub.portal-fit { padding-top: 0; }
/* Lines are cell borders (not gap-over-backdrop) so a part-filled last row
   reads as plain surface, never a stray tinted hole. */
.dash-strip {
  display: flex; align-items: stretch; flex-wrap: wrap;
  margin-inline: calc(-1 * var(--pad-x));
  background: var(--cell-bg);
  border-top: 1px solid var(--grid-line);
  border-bottom: 1px solid var(--grid-line);
  overflow: hidden; /* clips the first row's top-edge shadows */
}
.dash-strip .kpi-rail { flex: 1 1 0; min-width: 0; }
.dash-pulse {
  display: flex; align-items: center; gap: .55rem; flex-shrink: 0;
  padding: 0 1.2rem; background: var(--cell-bg);
  box-shadow: 0 -1px 0 var(--grid-line), -1px 0 0 var(--grid-line);
  font-family: var(--mono); font-size: 12px; color: var(--fg-dim);
}
.dash-pulse b { color: var(--fg); font-weight: 700; }
.dash-pulse .pulse-sep { color: var(--fg-mute); }
.pulse-dot {
  width: 8px; height: 8px; border-radius: 999px; background: var(--portal-2);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--portal-2) 60%, transparent);
  animation: pulse-beat 2.4s var(--ease) infinite;
}
@keyframes pulse-beat {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--portal-2) 55%, transparent); }
  70%, 100% { box-shadow: 0 0 0 7px transparent; }
}

/* === KPI rail ============================================================== */
/* Auto-fit: the cells re-flow to any width instead of a hard 7-column split. */
.kpi-rail {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr)); gap: .75rem;
  margin-bottom: 1.25rem;
}
.dash-strip .kpi-rail { gap: 0; margin-bottom: 0; }
.kpi {
  padding: 1rem 1.1rem; border-radius: var(--radius-sm);
  background: var(--mat-1); border: 1px solid var(--hairline);
}
/* Inside the strip, KPIs are cells: opaque, squared, edges are the grid lines.
   Right edge = border; row separators = a top shadow (the first row's shadow
   is clipped by the strip's overflow) — a part-filled wrapped row stays clean. */
.dash-strip .kpi {
  background: var(--cell-bg); border: none; border-radius: 0;
  border-right: 1px solid var(--grid-line);
  box-shadow: 0 -1px 0 var(--grid-line);
}
/* Minimized stats: value + tiny label, no sub-line — the detail lives on the
   page each stat links to. */
body[data-portal] .dash-strip .kpi { padding: .5rem .95rem; cursor: pointer; }
body[data-portal] .dash-strip .kpi .kpi-v { font-size: 1.15rem; color: var(--k-tint, var(--portal-2)); }
body[data-portal] .dash-strip .kpi .kpi-k { margin-top: .12rem; font-size: 9.5px; }
body[data-portal] .dash-strip .kpi .kpi-sub { display: none; }
/* KPI value reads in color: a per-tile --k-tint when set (Inventory, dashboard
   strip), else the section --tone (money pages coral, assets/inventory mint…),
   else admin-green. The dashboard strip + av-kpi-total keep their own more
   specific rules below/elsewhere. */
.kpi-v { font-size: 1.9rem; font-weight: 900; letter-spacing: -.03em; line-height: 1;
  color: var(--k-tint, var(--tone, var(--portal-2))); }
.kpi-k { font-family: var(--mono); font-size: 10.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .09em; color: var(--fg); margin-top: .5rem; }
.kpi-sub { font-size: 11.5px; color: var(--fg-mute); margin-top: .15rem; }

/* === Bento grid ============================================================ */
/* A working left column (projects + a smaller transcripts feed) beside a
   stacked right rail (workspaces, history, inventory) — one clean vertical
   rhythm per column rather than a ragged 5/4/3 row stack. */
.dash-grid { display: grid; grid-template-columns: 1.65fr 1fr; gap: 1rem; align-items: start; }
.dash-main, .dash-rail { display: flex; flex-direction: column; gap: 1rem; min-width: 0; }
.panel {
  display: flex; flex-direction: column; gap: 1rem;
  padding: 1.25rem 1.35rem; border-radius: var(--radius-sm);
  background: var(--mat-1); border: 1px solid var(--hairline);
}
.panel-head { display: flex; align-items: center; gap: .85rem; }
.panel-glyph {
  width: 38px; height: 38px; flex-shrink: 0; display: grid; place-items: center; font-size: 18px;
  border-radius: 11px; color: var(--tint, var(--portal));
  background: color-mix(in srgb, var(--tint, var(--portal)) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--tint, var(--portal)) 26%, transparent);
}
.panel-h-txt { flex: 1; min-width: 0; }
.panel-h-txt h3 { margin: 0; font-size: 1.05rem; font-weight: 800; letter-spacing: -.02em; }
.panel-sub { font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); }
.panel-links { display: flex; gap: .65rem; flex-shrink: 0; }
.panel-link { font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); white-space: nowrap; }
.panel-link:hover { color: var(--portal-2); }

/* === Live feed rows ======================================================== */
.feed { display: flex; flex-direction: column; gap: .15rem; }
.feed-row {
  display: flex; align-items: center; gap: .7rem; min-width: 0;
  padding: .55rem .6rem; border-radius: 10px; color: inherit;
  transition: background var(--t-fast) var(--ease);
}
.feed-row:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.feed-dot { width: 8px; height: 8px; border-radius: 999px; flex-shrink: 0; background: var(--fg-mute); }
.feed-dot.src-claude { background: var(--src-claude); }
.feed-dot.src-gemini { background: var(--src-gemini); }
.feed-dot.src-chatgpt { background: var(--src-chatgpt); }
.feed-dot.src-other { background: var(--src-other); }
.feed-main { flex: 1; min-width: 0; }
.feed-ttl { font-weight: 600; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.feed-prev { font-size: 12px; color: var(--fg-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: .05rem; }
.feed-side {
  display: flex; align-items: center; gap: .5rem; flex-shrink: 0;
  font-family: var(--mono); font-size: 11px; color: var(--fg-mute);
}
.feed-time { white-space: nowrap; }
.feed-tag { color: var(--fg-dim); }
.feed-flag {
  color: var(--c-coral-2); font-weight: 700;
  padding: .05rem .35rem; border-radius: 999px;
  background: color-mix(in srgb, var(--c-coral-1) 16%, transparent);
}
.feed-lens {
  font-family: var(--mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em;
  padding: .08rem .45rem; border-radius: 999px;
  background: color-mix(in srgb, var(--portal) 13%, transparent); color: var(--portal-2);
}
.feed-lens.lens-personal { background: color-mix(in srgb, var(--c-coral-1) 15%, transparent); color: var(--c-coral-1); }
.feed-lens.lens-psychological { background: color-mix(in srgb, var(--c-violet-1) 15%, transparent); color: var(--c-violet-1); }
.feed-lens.lens-working { background: color-mix(in srgb, var(--c-mint-1) 15%, transparent); color: var(--c-mint-1); }
.feed-empty { font-family: var(--mono); font-size: 12.5px; color: var(--fg-mute); padding: .75rem .6rem; }

/* === Quick-launch workspaces =============================================== */
.ql { display: flex; flex-direction: column; gap: .15rem; }
.ql-row {
  display: flex; align-items: center; gap: .7rem; color: inherit;
  padding: .55rem .6rem; border-radius: 10px;
  transition: background var(--t-fast) var(--ease);
}
.ql-row:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.ql-row:hover .ql-go { transform: translateX(3px); color: var(--portal-2); }
.ql-glyph {
  width: 30px; height: 30px; flex-shrink: 0; display: grid; place-items: center; font-size: 15px;
  border-radius: 9px; color: var(--tint, var(--portal));
  background: color-mix(in srgb, var(--tint, var(--portal)) 13%, transparent);
}
.ql-name { flex: 1; font-weight: 600; font-size: 14px; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ql-meta { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); white-space: nowrap; }
.ql-go { font-family: var(--mono); color: var(--fg-mute); transition: transform var(--t-fast) var(--ease), color var(--t-fast) var(--ease); }

/* Projects CRUD nested inside its panel: drop the panel's default body gap. */
#panel-projects .crud-list { gap: .5rem; }
#panel-projects .crud-card { padding: .7rem .9rem; }

/* Clickable card (a project that launches a destination). */
.crud-card.is-link { cursor: pointer; transition: border-color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease); }
.crud-card.is-link:hover { border-color: color-mix(in srgb, var(--portal) 45%, transparent); transform: translateY(-2px); }
.crud-card.is-link .ttl .go { color: var(--fg-mute); transition: transform var(--t-fast) var(--ease), color var(--t-fast) var(--ease); }
.crud-card.is-link:hover .ttl .go { color: var(--portal-2); transform: translateX(3px); }

/* Transcripts reads as a secondary feed — cap its height so the projects
   panel stays the anchor of the left column. */
.panel-sm .feed { max-height: 16.5rem; overflow-y: auto; }
.panel-sm .feed::-webkit-scrollbar { width: 6px; }
.panel-sm .feed::-webkit-scrollbar-thumb { background: var(--border-hi); border-radius: 999px; }

@media (max-width: 1000px) {
  .dash-grid { grid-template-columns: 1fr; }
}
@media (max-width: 620px) {
  .dash-pulse { display: none; }
}

/* === Single-viewport board (app mode) ===================================== */
/* The dashboard is one seamless surface: the KPI strip, then a board of cells
   that flexes to the bottom of the viewport — edge to edge, cells split by 1px
   grid lines instead of floating boxes. Overflow scrolls inside each cell; if
   the viewport is too short for the cells' minimums, the page scrolls (never
   clips). */
body[data-portal] .kpi { padding: .7rem 1rem; }
body[data-portal] .kpi-v { font-size: 1.5rem; }
body[data-portal] .kpi-k { margin-top: .3rem; }
body[data-portal] .kpi-sub { margin-top: .1rem; }
/* Honest load-failure state in place of the KPI rail (never fake zeros). */
.dash-loaderr { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap; padding: .9rem 1.1rem; border-radius: var(--radius-sm); background: var(--mat-1);
  border: 1px solid color-mix(in srgb, var(--c-coral-1) 30%, var(--hairline)); font-size: 14px; color: var(--fg-dim); }

/* Board layout — a widget grid, Apple-home-screen style. 12 columns; every
   widget spans width units (.dw-w4/.dw-w6/.dw-w12) and row units (.dw-h1..3);
   auto-flow dense reflows around hidden widgets. Edge to edge, cells share
   1px grid lines. DOM order = interaction priority (map, console, calendar). */
.dash-board {
  flex: 1; min-height: 0;
  position: relative;  /* anchors the resize ghost/snap overlays */
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  /* FIXED row units — rows never stretch with the viewport, so resize math
     and drag geometry stay put under the pointer (the 1fr stretch made every
     commit shift every row = the "inaccurate" feel). */
  grid-auto-rows: 7.25rem;
  grid-auto-flow: dense;
  gap: 1px;
  margin-inline: calc(-1 * var(--pad-x));
  /* Transparent canvas: holes show the page's ambient background, not grey
     slabs. Cell lines are per-cell rings (below), not a backdrop color. */
  background: transparent;
}
/* Edit mode: the free canvas reads as snappable — a faint unit dot-grid and
   spare rows at the bottom to resize/drop into. */
#portal-hub.editing .dash-board {
  padding-bottom: 15rem;
  background-image: radial-gradient(circle,
    color-mix(in srgb, var(--portal) 35%, var(--fg-mute)) 1.2px, transparent 1.3px);
  background-size: calc((100% - 11px) / 12 + 1px) calc(7.25rem + 1px);
  background-position: -0.6px -0.6px;
}
/* The full snap scale — manual resize can land on any of these. */
.dw-w2  { grid-column: span 2; }
.dw-w3  { grid-column: span 3; }
.dw-w4  { grid-column: span 4; }
.dw-w5  { grid-column: span 5; }
.dw-w6  { grid-column: span 6; }
.dw-w7  { grid-column: span 7; }
.dw-w8  { grid-column: span 8; }
.dw-w9  { grid-column: span 9; }
.dw-w10 { grid-column: span 10; }
.dw-w11 { grid-column: span 11; }
.dw-w12 { grid-column: span 12; }
.dw-h1  { grid-row: span 1; }
.dw-h2  { grid-row: span 2; }
.dw-h3  { grid-row: span 3; }
.dw-h4  { grid-row: span 4; }
.dw-h5  { grid-row: span 5; }
/* .panel's display:flex would defeat the hidden attribute — be explicit. */
.dw[hidden] { display: none; }
.dash-board .panel {
  min-height: 0; overflow: hidden; gap: 0; padding: 0;
  background: var(--cell-bg); border: none; border-radius: 0;
  box-shadow: 0 0 0 1px var(--grid-line);  /* neighbors' rings merge in the 1px gap */
  container-type: inline-size;
}
/* Widget tones (each panel owns one; the palette, applied). */
#panel-places      { --w-tint: var(--tone-cyan); }
#panel-console     { --w-tint: var(--tone-green); }
#panel-cal         { --w-tint: var(--tone-amber); }
#panel-assets      { --w-tint: var(--tone-mint); }
#panel-subs        { --w-tint: var(--tone-coral); }
#panel-launch      { --w-tint: var(--tone-violet); }
#panel-transcripts { --w-tint: var(--tone-cyan); }
#panel-typing      { --w-tint: var(--tone-cyan); }
#panel-history     { --w-tint: var(--tone-amber); }
#panel-inventory   { --w-tint: var(--tone-mint); }
/* One slim defined band: small glyph, 13px title, inline sub, compact link.
   The tinted underline is the widget's color signature — definition without
   a heavy block. Bodies below run end-to-end (see the margin rules). */
.dash-board .panel-head {
  gap: .5rem; padding: .42rem .75rem;
  border-bottom: 1px solid color-mix(in srgb, var(--w-tint, var(--portal)) 32%, var(--hairline));
  background: color-mix(in srgb, var(--fg) 3%, transparent);
}
.dash-board .panel-glyph { width: 21px; height: 21px; font-size: 11px; border-radius: 6px; }
.dash-board .panel-h-txt { display: flex; align-items: baseline; gap: .55rem; min-width: 0; }
.dash-board .panel-h-txt h3 { font-size: .82rem; letter-spacing: -.01em; }
.dash-board .panel-sub { font-size: 9.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.dash-board .panel-link { font-size: 10px; }
/* Squeezed widgets shed detail instead of distorting: sub first, then link. */
@container (max-width: 24rem) { .dash-board .panel-sub { display: none; } }
@container (max-width: 13rem) { .dash-board .panel-link { display: none; } }
/* Body content: a slim default inset; full-bleed surfaces override to 0. */
.dash-board .panel > :not(.panel-head, .dw-rz, .dw-ghost, .dw-snap, .dw-size-badge) {
  margin: .55rem .75rem; min-height: 0;
}
.dash-board .panel > :last-child:not(.panel-head, .dw-rz) { margin-bottom: .65rem; }
/* End-to-end surfaces: the map and the console meet the widget's edges.
   isolation:isolate contains Leaflet's internal z-index (its panes run up to
   ~650) to this element's own stacking context, so they can never bleed
   through a later dash-modal (z-index 300) that happens to render on top of
   the map's on-screen position — found while testing the TypeShit modal. */
.dash-board #dash-places-map { margin: 0; border-radius: 0; isolation: isolate; }
.dash-board .ag-embed { margin: 0; }
.dash-board .dash-places-tag { margin-top: .4rem; margin-bottom: 0; }

/* Places widget filter rail — the full Places page's family/attribute/open-now
   filters, compacted into one wrapping chip rail above the map. Chips drive the
   widget's pins in place (ctl.filterIds). The map (flex:1) takes what's left. */
#panel-places #dash-places-filters { margin: .5rem .75rem .4rem; display: flex; flex-direction: column; gap: .3rem; }
.dpf-row { display: flex; flex-wrap: wrap; gap: .3rem; }
.dpf-chip, .dpf-sub {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .18rem .5rem; border-radius: 99px;
  border: 1px solid var(--hairline); background: var(--bg-soft);
  color: var(--fg-dim); font: 600 11px var(--mono); cursor: pointer;
  white-space: nowrap; transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.dpf-chip:hover, .dpf-sub:hover { color: var(--fg); border-color: var(--border); }
.dpf-chip.active { color: var(--fg); border-color: color-mix(in srgb, var(--fam, var(--portal-2)) 70%, transparent); background: color-mix(in srgb, var(--fam, var(--portal-2)) 15%, var(--bg-soft)); }
.dpf-sub.active { color: var(--fg); border-color: var(--portal-2); background: color-mix(in srgb, var(--portal-2) 15%, var(--bg-soft)); }
.dpf-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--fam, var(--fg-mute)); flex-shrink: 0; }
.dpf-ic { font-size: 10px; line-height: 1; }

/* --- Edit mode (the ✎ in the strip) --------------------------------------- */
.dash-edit-btn {
  flex-shrink: 0; width: 2.3rem; cursor: pointer;
  border: none; border-left: 1px solid var(--grid-line);
  background: var(--cell-bg); color: var(--fg-mute); font-size: 13px;
  box-shadow: 0 -1px 0 var(--grid-line);
  transition: color var(--t-fast) var(--ease);
}
.dash-edit-btn:hover, .dash-edit-btn.on { color: var(--portal-2); }
.dw-x {
  display: none; width: 22px; height: 22px; flex-shrink: 0;
  place-items: center; border-radius: 999px;
  border: 1px solid var(--hairline); background: var(--bg-soft);
  color: var(--fg-dim); font-size: 14px; line-height: 1; cursor: pointer;
}
.dw-x:hover { color: var(--c-coral-2); border-color: var(--c-coral-2); }
#portal-hub.editing .dw-x { display: grid; }
#portal-hub.editing .dw {
  outline: 1px dashed color-mix(in srgb, var(--portal) 45%, transparent);
  outline-offset: -4px;
}
/* Resize grips — the grid lines become draggable in edit mode: grab a
   widget's right or bottom edge (or the corner) and the size snaps across
   the 12-col × row-unit grid; a center badge reads out "w × h". */
.dash-board .dw { position: relative; }
.dw-rz { display: none; position: absolute; z-index: 6; touch-action: none; }
#portal-hub.editing .dw-rz { display: block; }
.dw-rz-e  { top: 12px; right: -5px; width: 11px; height: calc(100% - 24px); cursor: col-resize; }
.dw-rz-w  { top: 12px; left: -5px; width: 11px; height: calc(100% - 24px); cursor: col-resize; }
.dw-rz-s  { left: 12px; bottom: -5px; height: 11px; width: calc(100% - 24px); cursor: row-resize; }
.dw-rz-n  { left: 12px; top: -5px; height: 11px; width: calc(100% - 24px); cursor: row-resize; }
.dw-rz-se { right: -5px; bottom: -5px; width: 20px; height: 20px; cursor: nwse-resize; z-index: 7; }
.dw-rz::after {
  content: ""; position: absolute; border-radius: 999px; background: transparent;
  transition: background var(--t-fast) var(--ease);
}
.dw-rz-e::after  { left: 4px; top: 15%; bottom: 15%; width: 3px; }
.dw-rz-w::after  { right: 4px; top: 15%; bottom: 15%; width: 3px; }
.dw-rz-s::after  { top: 4px; left: 15%; right: 15%; height: 3px; }
.dw-rz-n::after  { bottom: 4px; left: 15%; right: 15%; height: 3px; }
.dw-rz-se::after { right: 4px; bottom: 4px; width: 10px; height: 10px; border-radius: 3px; }
.dw-rz:hover::after { background: var(--portal-2); }
.dw.resizing { outline: 1px solid var(--portal-2) !important; outline-offset: -2px; }
/* Smooth resize: the ghost glides raw with the pointer; the dashed landing
   box eases between snap steps (magnetic feel, no mid-drag board jumping). */
.dw-ghost {
  position: absolute; z-index: 40; pointer-events: none;
  border: 1.5px solid var(--portal-2); border-radius: 4px;
  background: color-mix(in srgb, var(--portal) 8%, transparent);
}
.dw-snap {
  position: absolute; z-index: 39; pointer-events: none;
  border: 1px dashed color-mix(in srgb, var(--portal) 65%, transparent);
  transition: width .13s var(--ease), height .13s var(--ease);
}
/* Reorder: grab a widget anywhere (controls excluded) and drag; neighbors
   FLIP out of the way. */
#portal-hub.editing .dash-board .dw { cursor: grab; }
/* The grabbed widget stays in-grid as a dim dashed placeholder that shuffles;
   a scaled avatar (below) is what actually follows the hand. */
.dw.dragging {
  opacity: .35; pointer-events: none; cursor: grabbing;
  outline: 1.5px dashed var(--portal-2) !important; outline-offset: -2px;
}
/* The splitter bar — the shared line between two abutting widgets, live. */
.dw-splitbar {
  position: absolute; z-index: 41; pointer-events: none;
  width: 3px; border-radius: 999px;
  background: var(--portal-2);
  box-shadow: 0 0 10px color-mix(in srgb, var(--portal-2) 55%, transparent);
}
.dw-splitbar-y { width: auto; height: 3px; }
.dw-avatar {
  position: fixed; z-index: 300; pointer-events: none;
  transform-origin: top left;
  border-radius: 10px; overflow: hidden;
  background: var(--cell-bg);
  box-shadow: 0 0 0 1.5px var(--portal-2), 0 24px 60px -18px rgba(0,0,0,.5);
  opacity: .95;
}
.dw-size-badge {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 8;
  font-family: var(--mono); font-size: 13px; font-weight: 700; color: var(--portal-2);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  border: 1px solid var(--portal-2); border-radius: 9px; padding: .3rem .7rem;
  pointer-events: none; white-space: nowrap;
}
#portal-hub.editing .dash-board { user-select: none; }
.dash-strip .kpi { position: relative; }
.dash-strip .kpi .dw-x { position: absolute; top: .3rem; right: .3rem; width: 18px; height: 18px; font-size: 12px; }
/* The tray — hidden widgets wait here in edit mode; nothing is deleted. */
.dash-tray {
  display: flex; align-items: center; gap: .45rem; flex-wrap: wrap;
  margin-inline: calc(-1 * var(--pad-x)); padding: .45rem var(--pad-x);
  background: color-mix(in srgb, var(--fg) 3%, var(--cell-bg));
  border-bottom: 1px solid var(--grid-line);
  font-family: var(--mono); font-size: 11px; color: var(--fg-mute);
}
.dash-tray[hidden] { display: none; }
.tray-k { font-weight: 700; text-transform: uppercase; letter-spacing: .1em; font-size: 9.5px; }
.tray-add {
  font-family: var(--mono); font-size: 11px; cursor: pointer;
  color: var(--portal-2); background: var(--bg-soft);
  border: 1px dashed color-mix(in srgb, var(--portal) 40%, var(--hairline));
  border-radius: 999px; padding: .2rem .6rem;
}
.tray-add:hover { border-style: solid; }
.tray-empty { font-style: italic; }
.tray-hint { margin-left: auto; }

/* Console cell — the embedded shell flexes to the cell's height. */
#panel-console .ag-shell { flex: 1; min-height: 10rem; }

/* Mini calendar cell — the whole month always fits (rows compress; no cut-off
   month, ever: the calendar's whole point here is to stay visible). */
#dash-cal { flex: 1; min-height: 0; display: flex; }
#dash-cal .cal-month { flex: 1; display: flex; flex-direction: column; min-height: 0; }
#dash-cal .cal-cells { flex: 1; min-height: 0; grid-auto-rows: 1fr; }
#dash-cal .cal-cell.mini { aspect-ratio: auto; min-height: 0; }
.dcal-btn {
  font-family: var(--mono); font-size: 12px; line-height: 1; cursor: pointer;
  color: var(--fg-dim); background: var(--bg-soft);
  border: 1px solid var(--hairline); border-radius: 7px; padding: .2rem .45rem;
}
.dcal-btn:hover { color: var(--fg); border-color: color-mix(in srgb, var(--portal) 40%, transparent); }
/* Controlled-header parity with the calendar page: the month title sits BETWEEN
   the prev/next arrows as one group; spend total + today button trail on the
   right. (#dash-cal specificity beats the generic .cal-month.compact rules.) */
#dash-cal .cal-m-h { display: flex; align-items: center; gap: .5rem; justify-content: flex-start; font-weight: 700; font-size: 13px; margin-bottom: .4rem; }
#dash-cal .dcal-nav { display: inline-flex; align-items: center; gap: .35rem; margin-left: 0; }
#dash-cal .dcal-nav b { font-family: var(--sans); font-weight: 800; font-size: 13px; color: var(--fg); }
#dash-cal .cal-m-out { margin-left: auto; font-family: var(--mono); font-size: 11px; color: var(--portal-2); }
#dash-cal .cal-cell.mini { color: inherit; }
#dash-cal .cal-cell.mini:hover { border-color: color-mix(in srgb, var(--portal) 45%, transparent); }

/* Assets — the net-worth donut (physical vs digital). Chart colors are the
   classes' own sitewide identities, on mode-specific steps validated against
   each surface (dataviz six-checks). */
:root {
  --viz-physical: var(--c-mint-2);
  --viz-digital: var(--c-violet-2);
}
:root[data-theme="dark"] {
  --viz-physical: #059669;
  --viz-digital: #8b5cf6;
}
#assets-viz { flex: 1; min-height: 0; display: flex; align-items: center; gap: 1.1rem; }
.av-donut-wrap { display: flex; align-items: center; gap: 1.2rem; width: 100%; min-height: 0; }
.av-donut { flex: 0 0 auto; width: clamp(96px, 40%, 150px); height: auto; }
.av-donut circle { transition: stroke-width var(--t-fast) var(--ease); }
.av-donut circle:hover { stroke-width: 6; }
.av-donut-v { font-size: 5.4px; font-weight: 800; fill: var(--fg); letter-spacing: -.02em; }
.av-donut-k { font-size: 2.6px; font-weight: 600; fill: var(--fg-mute); text-transform: uppercase; letter-spacing: .12em; }
.av-donut-legend { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: .6rem; }
.av-leg-row { display: flex; align-items: baseline; gap: .5rem; min-width: 0; }
.av-leg-dot { width: 9px; height: 9px; border-radius: 3px; flex: none; align-self: center; }
.av-leg-physical { background: var(--viz-physical); }
.av-leg-digital { background: var(--viz-digital); }
.av-leg-name { font-weight: 600; font-size: 13px; }
.av-leg-v { margin-left: auto; font-family: var(--mono); font-weight: 700; font-size: 13px; color: var(--fg); text-align: right; }
.av-leg-v i { display: block; font-style: normal; font-weight: 500; font-size: 10px; color: var(--fg-mute); }

/* History — one slim row of lens counts (the 2×2 cards ate a third of the
   rail for four numbers). */
.lens-row { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .4rem; }
/* Reflow to the TILE's own resized width, not the viewport — a manually
   narrowed widget (edit-mode drag) never triggers a viewport media query. */
@container (max-width: 20rem) { .lens-row { grid-template-columns: repeat(2, 1fr); } }
.lens-mini {
  display: flex; flex-direction: column; align-items: center; gap: .1rem;
  padding: .5rem .25rem; border-radius: 10px; min-width: 0;
  background: var(--bg-soft); border: 1px solid var(--hairline);
}
.lens-mini:hover { border-color: color-mix(in srgb, var(--tint) 45%, transparent); }
.lens-mini .lens-glyph { width: 22px; height: 22px; font-size: 12px; border-radius: 7px; }
.lens-mini b { font-size: 15px; font-weight: 800; color: var(--fg); line-height: 1.2; }
.lens-mini-k {
  font-family: var(--mono); font-size: 8.5px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--fg-mute); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Workspaces — wrapping chips: they reflow with width AND the container
   scrolls when height runs short (a fixed row stack clipped its tail). */
#panel-launch .ql {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
  gap: .4rem; align-content: start; overflow-y: auto; min-height: 0; flex: 1;
}
#panel-launch .ql-row {
  display: grid; grid-template-columns: 26px minmax(0, 1fr);
  align-items: center; column-gap: .45rem; row-gap: .15rem;
  padding: .55rem .65rem; border-radius: 10px;
  background: var(--bg-soft); border: 1px solid var(--hairline);
}
#panel-launch .ql-glyph { width: 26px; height: 26px; font-size: 13px; border-radius: 8px; }
#panel-launch .ql-meta { grid-column: 1 / -1; }
#panel-launch .ql-row:hover { border-color: color-mix(in srgb, var(--tint, var(--portal)) 45%, transparent); background: var(--bg-soft); }
#panel-launch .ql-name { white-space: normal; font-size: 13px; line-height: 1.2; }
#panel-launch .ql-meta { white-space: normal; font-size: 10px; line-height: 1.3; }
#panel-launch .ql-go { display: none; }

/* Expenses — calm on purpose: money out is a fact to check, not a headline.
   Ink-colored focal, no coral alarm highlights, quiet list. */
#panel-subs #subs-focal { display: flex; flex-direction: column; min-height: 0; flex: 1; gap: .55rem; }
#panel-subs .up-list { min-height: 0; overflow-y: auto; flex: 1; padding-right: .15rem; }
#panel-subs .focal-stat { flex-shrink: 0; padding: 0 0 .5rem; margin-bottom: .2rem; }
#panel-subs .focal-v { font-size: 1.3rem; font-family: var(--mono); font-weight: 700; color: var(--fg); }
#panel-subs .focal-k { font-size: 10.5px; margin-top: .15rem; }
#panel-subs .up-row { grid-template-columns: 3.9rem 1fr auto; gap: .5rem; padding: .38rem .1rem; }
#panel-subs .up-when { font-size: 11px; }
#panel-subs .up-name { font-size: 12.5px; line-height: 1.25; }
#panel-subs .up-amt { font-size: 12.5px; color: var(--fg-dim); }
#panel-subs .up-row.soon .up-amt, #panel-subs .up-row.soon .up-when b { color: var(--fg); }

/* Places — the map fills the hero panel; launch rows pin beneath it. */
body[data-portal] #panel-places #dash-places-map { flex: 1; min-height: 150px; height: auto; }

/* Transcripts + TypeShit (tray residents) — compact. */
#panel-transcripts .launch-card { padding: .55rem .7rem; }
#panel-transcripts .launch-desc { font-size: 11px; }
#panel-typing .cov-stat { padding: .55rem .5rem; }

/* Thin scrollbars inside the board's scrolling bodies. */
.dash-board .up-list::-webkit-scrollbar,
.dash-board .ql::-webkit-scrollbar { width: 6px; }
.dash-board .up-list::-webkit-scrollbar-thumb,
.dash-board .ql::-webkit-scrollbar-thumb { background: var(--border-hi); border-radius: 999px; }

/* Mid widths: smalls go two-up, bigs go full-width; rows size to content
   (the one-screen ideal yields to readable widgets; the page scrolls). */
/* The 12-col grid + the user's spans hold at every desktop width — editing
   works everywhere ≥720px (the old ≤1150 override made a silent dead zone
   where edit mode rendered but nothing dragged). */
@media (max-width: 720px) {
  .dw-w2, .dw-w3, .dw-w4, .dw-w5, .dw-w6, .dw-w7, .dw-w8, .dw-w9, .dw-w10, .dw-w11, .dw-w12 { grid-column: span 12; }
  .dash-board { grid-auto-rows: minmax(6.6rem, auto); }
  #panel-console { min-height: 18rem; }
  .lens-row { grid-template-columns: repeat(2, 1fr); }
  .dw-rz { display: none !important; }  /* single-column: spans are moot */
  body[data-portal] #panel-places #dash-places-map { min-height: 220px; }
}

/* === Sub-page layout ====================================================== */
/* Per-section tone signature — mirrors the dashboard's per-widget --w-tint
   (§Single-viewport board) so each sub-page reads in the same color family as
   its dashboard widget. --tone falls back to admin-green. All the sub-page
   chrome below (headers, cards, tabs, tables, forms, bars) keys off --tone, so
   setting it once here re-colors a whole page. */
#portal-inventory        { --tone: var(--tone-mint); }
#portal-history          { --tone: var(--tone-amber); }
#portal-shopping         { --tone: var(--tone-coral); }
#portal-knowledge        { --tone: var(--tone-cyan); }
#portal-software         { --tone: var(--tone-violet); }
#portal-keychain         { --tone: var(--tone-amber); }
#portal-runner           { --tone: var(--tone-green); }
#portal-cost             { --tone: var(--tone-coral); }
#portal-calendar         { --tone: var(--tone-amber); }
#portal-school           { --tone: var(--tone-cyan); }
#portal-agent            { --tone: var(--tone-green); }
#portal-asset-value      { --tone: var(--tone-mint); }
#portal-expenses         { --tone: var(--tone-coral); }
#portal-transcripts      { --tone: var(--tone-cyan); }
#portal-places,
#portal-potential-places { --tone: var(--tone-cyan); }
#portal-mdvault          { --tone: var(--tone-cyan); }
#portal-atlas            { --tone: var(--tone-violet); }

.portal-block { margin-top: 3rem; }
.portal-block:first-of-type { margin-top: 2rem; }
/* Designed section header: a tinted tone dot + tighter title, the sub kept as a
   mono caption, and the rule recolored to the section tone — the same "defined
   chrome" the dashboard panels use, minus the heavy glyph (which stays opt-in
   per section via .pbh-glyph / .hist-glyph, where a glyph is semantic). */
.portal-block-head {
  display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; margin-bottom: 1.25rem;
  padding-bottom: .7rem;
  border-bottom: 1px solid color-mix(in srgb, var(--tone, var(--portal)) 30%, var(--hairline));
}
.portal-block-head::before {
  content: ""; width: 9px; height: 9px; flex-shrink: 0; border-radius: 3px;
  background: var(--tone, var(--portal));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--tone, var(--portal)) 16%, transparent);
}
.portal-block-head h3 { margin: 0; font-size: 1.2rem; font-weight: 800; letter-spacing: -.02em; }
.portal-block-head .hint { font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); }
/* Opt-in tinted glyph for a page's lead header (canonical form of .panel-glyph /
   .hist-glyph). When present it replaces the default tone dot. */
.portal-block-head:has(.pbh-glyph)::before { display: none; }
.pbh-glyph {
  width: 34px; height: 34px; flex-shrink: 0; display: grid; place-items: center; font-size: 16px;
  border-radius: 10px; color: var(--tint, var(--tone, var(--portal)));
  background: color-mix(in srgb, var(--tint, var(--tone, var(--portal))) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--tint, var(--tone, var(--portal))) 26%, transparent);
}
.portal-back { font-family: var(--mono); font-size: 12px; color: var(--fg-mute); }
.portal-back:hover { color: var(--portal-2); }

/* === CRUD collection ====================================================== */
.crud-toolbar { display: flex; align-items: center; gap: .75rem; margin-bottom: 1rem; }
.crud-add { font-size: 13px; }
.crud-list { display: flex; flex-direction: column; gap: .6rem; }
.crud-empty { color: var(--fg-mute); font-family: var(--mono); font-size: 13px; }
.crud-card {
  display: flex; align-items: center; gap: 1rem;
  padding: 1rem 1.25rem; border-radius: var(--radius-sm);
  background: var(--mat-1); border: 1px solid var(--hairline);
  position: relative; overflow: hidden;
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
/* Tone left-accent — a hairline tinted edge that reads the section's color
   family (matches the dashboard cards without shouting). */
.crud-card::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--tone, var(--portal)); opacity: .5;
}
.crud-card:hover {
  border-color: color-mix(in srgb, var(--tone, var(--portal)) 40%, var(--hairline));
  background: color-mix(in srgb, var(--fg) 3%, var(--mat-1));
}
.crud-card-body { flex: 1; min-width: 0; }
.crud-card-body .ttl { font-weight: 700; }
.crud-card-body .meta { font-family: var(--mono); font-size: 12px; color: var(--fg-mute); margin-top: .15rem; }
.crud-card-body .tag {
  display: inline-block; font-family: var(--mono); font-size: 10.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .05em;
  padding: .1rem .5rem; border-radius: 999px; margin-right: .35rem;
  background: color-mix(in srgb, var(--tone, var(--portal)) 14%, transparent);
  color: color-mix(in srgb, var(--tone, var(--portal-2)) 88%, var(--fg));
}
/* Asset-class glyph on owned inventory cards (⬢ physical / ◈ digital). */
.inv-class { margin-right: .35rem; font-size: 12px; vertical-align: middle; }
.inv-class-physical { color: var(--c-mint-1); }
.inv-class-digital { color: var(--c-violet-1); }
.crud-card-actions { display: flex; gap: .4rem; flex-shrink: 0; }
.crud-mini {
  background: none; border: 1px solid var(--hairline); border-radius: 8px;
  color: var(--fg-mute); font-family: var(--mono); font-size: 11px; padding: .25rem .6rem; cursor: pointer;
  transition: color var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.crud-mini:hover { color: var(--tone, var(--portal-2)); border-color: var(--tone, var(--portal-2)); }
.crud-mini.danger:hover { color: var(--c-coral-2); border-color: var(--c-coral-2); }

/* form */
.crud-form-host:empty { margin: 0; }
.crud-form {
  padding: 1.5rem; border-radius: var(--radius-sm); margin-bottom: 1rem;
  background: var(--mat-1); border: 1px solid color-mix(in srgb, var(--tone, var(--portal)) 32%, var(--hairline));
}
.crud-form-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1rem;
}
.crud-field { display: flex; flex-direction: column; gap: .35rem; }
.crud-field.full { grid-column: 1 / -1; }
.crud-field-label { font-family: var(--mono); font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; color: var(--fg-mute); }
.crud-field input, .crud-field select, .crud-field textarea {
  background: transparent; border: 1px solid var(--border-hi); border-radius: 10px;
  color: var(--fg); font: inherit; padding: .55rem .8rem; width: 100%;
}
.crud-field input:focus, .crud-field select:focus, .crud-field textarea:focus {
  outline: none; border-color: var(--tone, var(--portal-2));
}
.crud-form-actions { display: flex; gap: .75rem; margin-top: 1.25rem; }

/* === Keychain — the key-chain (build_task #182 Phase 1, redesigned) ======= */
/* Each secret is a physical KEY hung on the ring. --kc is the key's metal:
   brass (--tone amber) when live/integrated, dull when a spare. */
.kr { margin-top: 1.75rem; }
.kr-head { display: flex; align-items: center; gap: .95rem; flex-wrap: wrap; margin-bottom: 1.1rem; }
/* the keyring loop — a split ring drawn in brass */
.kr-ring {
  width: 34px; height: 34px; flex-shrink: 0; border-radius: 50%;
  border: 4px solid var(--tone-amber);
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--tone-amber) 22%, transparent);
  /* a small opening, like a split ring */
  -webkit-mask: conic-gradient(from -18deg, transparent 0 34deg, #000 34deg 360deg);
          mask: conic-gradient(from -18deg, transparent 0 34deg, #000 34deg 360deg);
}
.kr-titles { display: flex; flex-direction: column; gap: .12rem; }
.kr-titles h2 { margin: 0; font-size: 1.6rem; font-weight: 900; letter-spacing: -.03em; line-height: 1; }
.kr-sub { font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); }
/* the rail the keys hang from */
.kr-rail {
  height: 3px; margin: 0 .3rem 1.6rem; border-radius: 999px;
  background: linear-gradient(90deg, transparent,
    color-mix(in srgb, var(--tone-amber) 50%, var(--border-hi)) 8%,
    color-mix(in srgb, var(--tone-amber) 50%, var(--border-hi)) 92%, transparent);
}
.kr-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 1.6rem 1.4rem; }

.key {
  --kc: var(--fg-mute);                       /* spare = dull metal */
  position: relative;
  display: grid; grid-template-columns: auto 1fr; align-items: start; gap: 1rem;
  padding: 1.1rem 1.2rem 1rem 1rem;
  background: var(--mat-1); border: 1px solid var(--hairline);
  border-radius: 46px 18px 18px 46px;         /* round bow-end on the left */
  transition: transform var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.key-live { --kc: var(--tone-amber); }        /* integrated = live brass key */
.key:hover { transform: translateY(-2px); border-color: color-mix(in srgb, var(--kc) 45%, var(--hairline)); }
/* split-ring loop clipping the key to the rail */
.key-hole {
  position: absolute; top: -10px; left: 30px; width: 15px; height: 15px;
  border-radius: 50%; background: var(--bg);
  border: 2px solid color-mix(in srgb, var(--kc) 60%, var(--border-hi));
}
/* the round grip (bow), with a faint brass sheen + the bit hole */
.key-bow {
  width: 52px; height: 52px; flex-shrink: 0; border-radius: 50%; margin-top: .15rem;
  display: grid; place-items: center; border: 3px solid var(--kc);
  background: radial-gradient(circle at 34% 30%,
    color-mix(in srgb, var(--kc) 24%, transparent),
    color-mix(in srgb, var(--kc) 7%, transparent));
}
.key-bit { width: 14px; height: 14px; border-radius: 50%; border: 2.5px solid var(--kc); opacity: .6; }
.key-blank .key-bow { border-style: dashed; }
.key-blank .key-bit { display: none; }

.key-blade { min-width: 0; display: flex; flex-direction: column; gap: .38rem; }
.key-blade-top { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
.key-label { font-weight: 800; font-size: 15px; letter-spacing: -.01em; }
.key-flag {
  font-family: var(--mono); font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em;
  color: var(--tone-amber); background: color-mix(in srgb, var(--tone-amber) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--tone-amber) 30%, transparent);
  border-radius: 999px; padding: .08rem .45rem;
}
.key-handle {                                  /* the "cut code": get_secret("…") */
  font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); overflow-wrap: anywhere;
}
.key-value-row { display: flex; align-items: center; gap: .5rem; margin-top: .1rem; flex-wrap: wrap; }
.key-value { font-family: var(--mono); font-size: 12.5px; letter-spacing: .05em; color: var(--fg); word-break: break-all; }
.key-value.kc-unset { color: var(--fg-mute); font-style: italic; letter-spacing: normal; }
/* Notes are clamped to two lines so a long description can't stretch the key
   and distort the ring's vertical rhythm. Click toggles the full text — the
   prose stays, it just doesn't dominate the card by default. */
.key-note { font-size: 12px; color: var(--fg-dim); line-height: 1.5; cursor: pointer;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; }
.key-note.expanded { -webkit-line-clamp: unset; overflow: visible; }
.key-actions { display: flex; gap: .35rem; margin-top: .25rem; }
@media (max-width: 620px) { .kr-grid { grid-template-columns: 1fr; } }

.kc-form-hint {
  margin: .75rem 0 0; font-size: 11.5px; color: var(--fg-mute); line-height: 1.5;
}
.kc-form-hint code {
  font-family: var(--mono); font-size: 10.5px; background: var(--mat-1);
  border: 1px solid var(--hairline); border-radius: 4px; padding: .05rem .3rem;
}

/* === the console (build_task #182 Phase 2) ================================ */
.ag-shell {
  display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; height: 100%;
  border: 1px solid var(--hairline); border-radius: 14px;
  background: color-mix(in srgb, var(--bg-elev) 88%, black 6%);
  overflow: hidden;
}
/* Standalone Console page: its flex parent's height is a min-height
   (indefinite), so height:100% collapsed the shell to a tiny box that squeezed
   and obscured long output. Flex to fill + a real floor so the console gets a
   proper app-sized surface. */
#portal-agent .ag-shell { min-height: min(66vh, 42rem); }
/* Console header — identity, the model picker, and the session/save state. */
.ag-top {
  display: flex; align-items: center; gap: .7rem; flex-shrink: 0;
  padding: .55rem .9rem; border-bottom: 1px solid var(--hairline);
  background: var(--mat-1);
}
.ag-top-name {
  font-family: var(--mono); font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .1em; color: var(--portal-2);
}
.ag-model {
  font-family: var(--mono); font-size: 11.5px; color: var(--fg-dim);
  background: var(--bg-soft); border: 1px solid var(--hairline); border-radius: 8px;
  padding: .25rem .45rem; cursor: pointer; max-width: 11rem;
}
.ag-model:focus { outline: none; border-color: var(--portal-2); }
.ag-sess { margin-left: auto; font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); white-space: nowrap; }
.ag-sess a { color: var(--portal-2); }
/* Dashboard embed: the cell provides the frame, so the shell drops its own. */
.ag-embed { border: none; border-radius: 0; background: transparent; }
.ag-embed .ag-log { padding: .7rem .8rem; font-size: 12.5px; }
.ag-embed .ag-top { padding: .4rem .8rem; background: transparent; }
.ag-embed .ag-input-row { padding: .55rem .8rem; background: transparent; }
.ag-log {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 1.1rem 1.25rem; display: flex; flex-direction: column; gap: .55rem;
  font-family: var(--mono); font-size: 13.5px; line-height: 1.55;
}
.ag-empty { color: var(--fg-mute); }
.ag-msg { display: flex; gap: .55rem; align-items: baseline; }
.ag-who { flex-shrink: 0; font-weight: 700; }
.ag-msg-you .ag-who { color: var(--fg-mute); }
.ag-msg-agent .ag-who { color: var(--portal-2); }
.ag-text { white-space: pre-wrap; word-break: break-word; color: var(--fg); }
.ag-tool {
  font-size: 12px; color: var(--fg-mute); padding: .2rem .5rem;
  border-left: 2px solid color-mix(in srgb, var(--portal) 40%, transparent);
  margin-left: 1.6rem;
}
.ag-tool-name { color: var(--portal-2); }
.ag-tool-args { opacity: .8; }
.ag-tool-result {
  margin-left: 1.6rem; font-size: 12px; color: var(--fg-mute);
}
.ag-tool-result summary { cursor: pointer; }
.ag-tool-result summary:hover { color: var(--portal-2); }
.ag-tool-result-body {
  margin-top: .35rem; padding: .6rem .75rem; border-radius: 8px;
  background: var(--mat-1); border: 1px solid var(--hairline);
  white-space: pre-wrap; word-break: break-word; max-height: 220px; overflow-y: auto;
}
.ag-tool-error .ag-tool-result-body { border-color: color-mix(in srgb, var(--c-coral-2) 40%, var(--hairline)); color: var(--c-coral-2); }
.ag-tool-error summary { color: var(--c-coral-2); }
.ag-thinking { color: var(--fg-mute); font-style: italic; }
.ag-confirm {
  margin-left: 1.6rem; padding: .85rem 1rem; border-radius: 10px;
  background: color-mix(in srgb, var(--c-amber-1) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--c-amber-1) 45%, transparent);
}
.ag-confirm-text { font-size: 12.5px; color: var(--fg); margin-bottom: .6rem; }
.ag-confirm-actions { display: flex; gap: .6rem; }
.ag-input-row {
  display: flex; align-items: center; gap: .6rem;
  padding: .8rem 1rem; border-top: 1px solid var(--hairline);
  background: var(--mat-1);
}
.ag-caret { font-family: var(--mono); color: var(--portal-2); font-weight: 700; }
.ag-input-row input {
  flex: 1; background: transparent; border: none; outline: none;
  font-family: var(--mono); font-size: 14px; color: var(--fg);
}
.ag-input-row input:disabled { opacity: .5; }

/* --- Full console chrome (standalone page only; the dashboard cell stays the
   compact variant) ------------------------------------------------------- */
.ag-full .ag-top { flex-wrap: wrap; row-gap: .4rem; }
.ag-full .ag-top .ag-sess { margin-left: .4rem; }
.ag-meta {
  font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); white-space: nowrap;
}
.ag-meta b { color: var(--fg-dim); font-weight: 700; }
.ag-new { flex-shrink: 0; }
/* Capabilities strip — makes "same tools as the MCP connector" concrete. */
.ag-caps {
  display: flex; flex-wrap: wrap; align-items: center; gap: .4rem; flex-shrink: 0;
  padding: .5rem .9rem; border-bottom: 1px solid var(--hairline);
  background: color-mix(in srgb, var(--fg) 3%, transparent);
}
.ag-caps-label {
  font-family: var(--mono); font-size: 9px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .09em; color: var(--fg-mute); margin-right: .15rem;
}
.ag-cap {
  font-family: var(--mono); font-size: 10.5px; color: var(--portal-2);
  background: color-mix(in srgb, var(--portal) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--portal) 22%, transparent);
  border-radius: 999px; padding: .1rem .5rem;
}
/* Richer empty state — a lead line + clickable suggested prompts. */
.ag-empty-full { padding: 1.75rem 1.4rem; }
.ag-empty-lead {
  font-family: var(--sans); font-size: 14.5px; line-height: 1.6; color: var(--fg-dim);
  max-width: 64ch; margin: 0 0 1.1rem;
}
.ag-empty-lead b { color: var(--fg); font-weight: 700; }
.ag-suggest { display: flex; flex-wrap: wrap; gap: .5rem; }
.ag-suggest-l {
  width: 100%; font-family: var(--mono); font-size: 9.5px; text-transform: uppercase;
  letter-spacing: .09em; color: var(--fg-mute); margin-bottom: .1rem;
}
.ag-chip {
  font-family: var(--sans); font-size: 13px; color: var(--fg-dim); cursor: pointer;
  background: var(--mat-1); border: 1px solid var(--hairline); border-radius: 999px;
  padding: .42rem .85rem; transition: color var(--t-fast) var(--ease),
    border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.ag-chip:hover {
  color: var(--portal-2); border-color: color-mix(in srgb, var(--portal) 42%, var(--hairline));
  background: color-mix(in srgb, var(--portal) 6%, var(--mat-1));
}

/* === Prompts — a writing space for authoring prompts ====================== */
/* Two panes inside one bordered chassis (fills the app viewport). LEFT is the
   section spine: the site's own architecture + the ~/Developer taxonomy, nested
   exactly as they nest, doubling as the filter and the filing target. RIGHT is
   the writing: each prompt is edited IN PLACE (the card is the editor, autosaved
   on type) and set in the humanist sans at a reading measure — writing, not table
   cells. Machine detail (paths, counts, timing) stays quiet in mono. Scoped to
   #portal-composer; the .pw / .pr / .pwt classes are unique to this surface. */
.pw { display: flex; flex-direction: column; flex: 1; min-height: 0; gap: .7rem; }

.pw-top { display: flex; align-items: flex-end; gap: .8rem; padding: .1rem .1rem 0; }
.pw-title { display: flex; flex-direction: column; gap: .1rem; }
.pw-title h2 { margin: 0; font-size: 19px; letter-spacing: -.015em; }
.pw-sub { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }

.pw-body {
  flex: 1; min-height: 0; display: flex;
  border: 1px solid var(--hairline); border-radius: 16px; overflow: hidden;
  background: var(--bg-elev); box-shadow: var(--shadow-sm);
}

/* --- the section spine (left rail) --- */
.pw-rail {
  flex: none; width: 250px; overflow: auto; padding: .5rem .35rem .9rem;
  border-right: 1px solid var(--hairline);
  background: color-mix(in srgb, var(--bg-soft) 50%, transparent);
}
.pwt-row {
  display: flex; align-items: center; gap: .1rem; position: relative; min-height: 24px;
  padding: .05rem .4rem .05rem calc(.1rem + var(--d, 0) * .78rem);
  border-radius: 7px;
}
.pwt-lbl {
  flex: 1; min-width: 0; cursor: pointer; padding: .16rem .1rem; border-radius: 5px;
  font-family: var(--sans); font-size: 12.5px; color: var(--fg-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pwt-row:hover .pwt-lbl { color: var(--fg); }
.pwt-g { color: var(--fg-mute); margin-right: .35rem; }
.pwt-root { margin-top: .4rem; }
.pwt-root > .pwt-lbl { font-weight: 700; font-size: 12px; letter-spacing: .01em; color: var(--fg); }
.pwt-pseudo > .pwt-lbl { font-weight: 600; color: var(--fg); }
.pwt-row.active { background: color-mix(in srgb, var(--portal) 13%, transparent); }
.pwt-row.active::before {
  content: ""; position: absolute; left: 0; top: 3px; bottom: 3px; width: 2px;
  border-radius: 2px; background: var(--portal-2);
}
.pwt-row.active > .pwt-lbl { color: var(--portal-2); font-weight: 600; }
.pwt-caret {
  flex: none; width: 15px; height: 15px; padding: 0; font-size: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: none; cursor: pointer; color: var(--fg-mute);
  transition: transform var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.pwt-caret.open { transform: rotate(90deg); }
.pwt-caret:hover { color: var(--fg); }
.pwt-caret-none { visibility: hidden; }
.pwt-n {
  flex: none; font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute);
  background: color-mix(in srgb, var(--fg) 6%, transparent);
  border-radius: 999px; padding: .02rem .34rem; min-width: 1rem; text-align: center;
}
.pwt-row.active .pwt-n { color: var(--portal-2); background: color-mix(in srgb, var(--portal) 20%, transparent); }
.pwt-kids { position: relative; }
.pwt-kids::before {
  content: ""; position: absolute; top: 0; bottom: .1rem; width: 1px; background: var(--hairline);
  left: calc(.1rem + var(--d, 0) * .78rem + 7px);
}

/* --- the writing pane (right) --- */
.pw-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.pw-main-head {
  flex: none; display: flex; align-items: center; gap: .55rem;
  padding: .5rem .7rem; border-bottom: 1px solid var(--hairline); background: var(--mat-1);
}
.pw-scope { font-size: 12.5px; font-weight: 600; color: var(--fg);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 44%; }
.pw-scope-n { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); }
.pw-search {
  display: inline-flex; align-items: center; padding: .18rem .55rem;
  border: 1px solid var(--hairline); border-radius: 8px; background: var(--bg-soft);
}
.pw-search:focus-within { border-color: color-mix(in srgb, var(--portal) 40%, var(--hairline)); }
.pw-search input {
  background: transparent; border: none; outline: none; width: 11rem; max-width: 24vw;
  font-family: var(--sans); font-size: 12px; color: var(--fg);
}
.pw-list { flex: 1; min-height: 0; overflow: auto; }

/* one prompt = one inline editor, separated by hairlines (a document, not cards) */
.pr { position: relative; padding: .75rem 1rem .95rem 1.15rem; border-bottom: 1px solid var(--hairline);
  transition: background var(--t-fast) var(--ease); }
.pr:hover { background: color-mix(in srgb, var(--fg) 2%, transparent); }
.pr::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 2px;
  background: transparent; transition: background var(--t-fast) var(--ease);
}
.pr[data-state="dirty"]::before, .pr[data-state="saving"]::before {
  background: color-mix(in srgb, var(--portal) 45%, transparent); }
.pr[data-state="saved"]::before { background: var(--portal-2); }
.pr[data-state="error"]::before { background: var(--c-coral-2); }

.pr-meta { display: flex; align-items: center; gap: .5rem; margin-bottom: .4rem; }
.pr-target {
  display: inline-flex; align-items: center; gap: .3rem; cursor: pointer;
  border: 1px solid var(--hairline); border-radius: 999px; padding: .1rem .5rem;
  background: color-mix(in srgb, var(--fg) 4%, transparent);
  font-family: var(--mono); font-size: 10px; font-weight: 600; color: var(--fg-dim);
}
.pr-target:hover { color: var(--fg); border-color: color-mix(in srgb, var(--fg) 16%, var(--hairline)); }
.pr-target-i { color: var(--portal-2); }
.pr-target.is-unfiled, .pr-target.is-unfiled .pr-target-i { color: var(--fg-mute); }
.pr-dest {
  cursor: pointer; border: 1px solid transparent; border-radius: 999px; padding: .1rem .45rem;
  font-family: var(--mono); font-size: 9.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
}
.pr-dest[data-dest="chat"]   { color: var(--c-cyan-1);   background: color-mix(in srgb, var(--c-cyan-1) 12%, transparent); }
.pr-dest[data-dest="cowork"] { color: var(--c-violet-1); background: color-mix(in srgb, var(--c-violet-1) 12%, transparent); }
.pr-dest:hover { border-color: color-mix(in srgb, currentColor 45%, transparent); }
.pr-spacer { flex: 1; }
.pr-count, .pr-time { font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); white-space: nowrap; }
.pr-count { opacity: 0; transition: opacity var(--t-fast) var(--ease); }
.pr:focus-within .pr-count { opacity: 1; }
.pr-act {
  background: transparent; border: none; cursor: pointer; padding: .05rem .32rem; border-radius: 5px;
  font-family: var(--mono); font-size: 9.5px; font-weight: 600; color: var(--fg-mute);
  opacity: 0; transition: opacity var(--t-fast) var(--ease), color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.pr:hover .pr-act, .pr:focus-within .pr-act { opacity: 1; }
.pr-act:hover { color: var(--fg); background: color-mix(in srgb, var(--fg) 8%, transparent); }
.pr-del:hover { color: var(--c-coral-2); background: color-mix(in srgb, var(--c-coral-2) 12%, transparent); }

.pr-body {
  display: block; width: 100%; max-width: 70ch; box-sizing: border-box;
  resize: none; overflow: hidden; background: transparent; border: none; outline: none; padding: 0;
  font-family: var(--sans); font-size: 15px; line-height: 1.62; letter-spacing: -.003em;
  color: var(--fg); min-height: 1.62em;
}
.pr-body::placeholder { color: var(--fg-mute); }

.pw-empty { padding: 2.4rem 1.2rem; display: flex; flex-direction: column; align-items: flex-start; gap: .9rem; }
.pw-empty p { margin: 0; color: var(--fg-mute); font-size: 13.5px; }

/* refile popover — pick a section to file a prompt under */
.pw-pick {
  position: fixed; z-index: 120; display: flex; flex-direction: column; gap: .35rem;
  max-height: min(60vh, 420px); padding: .5rem; border-radius: 12px;
  border: 1px solid color-mix(in srgb, var(--fg) 12%, var(--hairline));
  background: var(--bg-elev); box-shadow: var(--shadow-md);
}
.pw-pick-search {
  flex: none; padding: .35rem .55rem; border: 1px solid var(--hairline); border-radius: 8px;
  background: var(--bg-soft); font-family: var(--sans); font-size: 12px; color: var(--fg); outline: none;
}
.pw-pick-search:focus { border-color: color-mix(in srgb, var(--portal) 40%, var(--hairline)); }
.pw-pick-list { overflow: auto; display: flex; flex-direction: column; gap: 1px; }
.pw-pick-opt {
  text-align: left; cursor: pointer; background: transparent; border: none; border-radius: 6px;
  padding: .28rem .5rem .28rem calc(.5rem + var(--d, 0) * .7rem);
  font-family: var(--sans); font-size: 12px; color: var(--fg-dim);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.pw-pick-opt:hover { background: color-mix(in srgb, var(--fg) 8%, transparent); color: var(--fg); }
.pw-pick-opt.cur { color: var(--portal-2); font-weight: 600; background: color-mix(in srgb, var(--portal) 12%, transparent); }

@media (max-width: 900px) {
  .pw-body { flex-direction: column; }
  .pw-rail { width: auto; max-height: 34vh; border-right: none; border-bottom: 1px solid var(--hairline); }
  .pw-search input { width: 8rem; }
}

/* =============================================================================
   AWS USAGE (portal-cost.html)                              rebuilt 2026-07-27
   -----------------------------------------------------------------------------
   Rebuilt to the Site Traffic standard and styled from the ratified taste corpus
   (~/Developer/records/skills/taste), not generic dashboard convention: r2 (2px)
   corners, shell/dense spacing (13px box padding, tight rows, 3–5 head gaps),
   small-caps mono labels, uniform 3px SPINE as the accent language, square r2
   tags rather than filled pills, elevation only on floating surfaces.

   The previous version's three complaints, addressed structurally:
     · WHITESPACE — the KPI cards, the second KPI rail and the 3-sentence prose
       note are gone. One chassis, five hairline-divided bands, no loose gutters.
     · DISPROPORTIONAL — the daily plot is 172px (was 120), stacked by category
       so composition survives a short bar, and carries a labelled MEDIAN line so
       the ~$0.44/day floor stays readable against a $9.29 spike day.
     · FINDABILITY — the bill reads as arithmetic (gross − credits = out of
       pocket) at the top; tables became ranked bars; one range lens drives
       every band.

   SERIES COLORS ARE VALIDATED, NOT PICKED BY EYE. Both themes pass all six
   checks (lightness band, chroma floor, CVD separation across ALL pairs,
   normal-vision floor, contrast vs surface) from the dataviz method against
   this site's real surfaces. Worst all-pairs CVD ΔE: 12.1 light / 12.3 dark
   (models↔other, deutan). Re-run the validator before changing any of them.
   Admin green is deliberately ABSENT — on this site green is the signed-in
   SIGNAL, never a chart series (CLAUDE.md portal visual law / KB #274).
============================================================================= */

#portal-cost {
  --ct-models:  #1467c2;   /* Bedrock + the Claude marketplace lines            */
  --ct-compute: #c2700a;   /* EC2 · Lightsail · VPC — the always-on floor       */
  --ct-other:   #a02a83;   /* S3 · Secrets Manager · Cost Explorer itself       */
  --ct-bar:     color-mix(in srgb, var(--portal) 55%, transparent);
  --ct-line:    var(--hairline);
  --ct-pad:     13px;      /* shell/dense: content boxes 12–13 outer            */
}
:root[data-theme="dark"] #portal-cost {
  --ct-models:  #3280dd;
  --ct-compute: #bf7d16;
  --ct-other:   #b13b92;
}

/* --- console head ---------------------------------------------------------- */

.ct-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 1.5rem 0 1rem;
}
.ct-head-l { display: flex; align-items: center; gap: 12px; min-width: 0; flex-wrap: wrap; }
.ct-head-r { display: flex; align-items: center; gap: 7px; margin-left: auto; flex-wrap: wrap; }

/* Cache freshness — the spine carries the state, never a coloured ground. */
.ct-fresh {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .03em;
  color: var(--fg-dim); padding: 5px 9px; border-radius: 2px;
  background: var(--mat-1); border: 1px solid var(--ct-line);
  border-left: 3px solid var(--fg-mute);
}
.ct-fresh[data-state="ok"]    { border-left-color: var(--portal); color: var(--fg); }
.ct-fresh[data-state="stale"] { border-left-color: var(--c-amber-2); }
.ct-fresh[data-state="err"]   { border-left-color: var(--c-coral-2); }
.ct-fresh-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--fg-mute); flex: none; }
.ct-fresh[data-state="ok"]    .ct-fresh-dot { background: var(--portal); }
.ct-fresh[data-state="stale"] .ct-fresh-dot { background: var(--c-amber-2); }
.ct-fresh[data-state="err"]   .ct-fresh-dot { background: var(--c-coral-2); }
.ct-src { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); letter-spacing: .02em; }

/* Dense segmented strip — compact, r2, no pill radii. */
.ct-seg {
  display: inline-flex; gap: 0; padding: 2px; border-radius: 2px;
  background: var(--mat-1); border: 1px solid var(--ct-line);
}
.ct-seg button {
  font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
  padding: 5px 11px; border: 0; border-radius: 2px; background: transparent;
  color: var(--fg-mute); transition: color 140ms var(--ease), background 140ms var(--ease);
}
.ct-seg button:hover { color: var(--fg); }
.ct-seg button[aria-selected="true"] {
  background: color-mix(in srgb, var(--portal) 14%, transparent); color: var(--fg);
}
.ct-seg-sm button { font-size: 11px; padding: 3px 9px; }

/* The price of the action rides inside the control — it spends real money. */
.ct-refresh {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  font: inherit; font-size: 12px; font-weight: 600;
  padding: 5px 10px; border-radius: 2px; color: var(--fg-dim);
  background: var(--mat-1); border: 1px solid var(--ct-line);
  transition: color 140ms var(--ease), border-color 140ms var(--ease);
}
.ct-refresh:hover:not(:disabled) { color: var(--fg); border-color: color-mix(in srgb, var(--portal) 45%, var(--ct-line)); }
.ct-refresh:disabled { opacity: .55; cursor: default; }
.ct-refresh i {
  font-family: var(--mono); font-style: normal; font-size: 9.5px; letter-spacing: .05em;
  color: var(--fg-mute); padding: 1px 4px; border-radius: 2px;
  background: color-mix(in srgb, var(--fg) 7%, transparent);
}

.ct-err {
  font-family: var(--mono); font-size: 11.5px; line-height: 1.45; color: var(--fg-dim);
  margin: 0 0 1rem; padding: 9px 11px; border-radius: 2px;
  background: var(--mat-1); border: 1px solid var(--ct-line);
  border-left: 3px solid var(--c-coral-2);
}

/* --- chassis: hairline-divided bands, one defined console ------------------ */

.ct-chassis {
  border: 1px solid var(--ct-line); border-radius: 2px;
  background: var(--mat-1); overflow: hidden;
}
.ct-band { padding: 15px var(--ct-pad); border-top: 1px solid var(--ct-line); }
.ct-chassis > .ct-band:first-child { border-top: 0; }
.ct-band-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 9px; }
.ct-band-head h3 { margin: 0; font-size: 1rem; font-weight: 800; letter-spacing: -.01em; }
.ct-band-ctl { display: inline-flex; align-items: center; gap: 9px; flex-wrap: wrap; margin-left: auto; }
.ct-hint { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }
.ct-subhead {
  font-family: var(--mono); font-size: 9.5px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--fg-mute);
  margin: 0 0 7px;
}
.ct-two { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.ct-half { min-width: 0; }

/* --- shared marks ---------------------------------------------------------- */

/* Square r2 key tags — the identity beside a label; pill grammar ranked last. */
.ct-key { width: 9px; height: 9px; border-radius: 2px; flex: none; display: inline-block; background: var(--c, var(--fg-mute)); }
.ct-legend { display: inline-flex; gap: 11px; flex-wrap: wrap; }
.ct-legend-item {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--mono); font-size: 10.5px; color: var(--fg-dim);
}

/* An inline stat run — replaces the KPI card rails that ate the old page. */
.ct-stats { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 11px; }
.ct-stat { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); letter-spacing: .04em; }
.ct-stat b {
  font-size: 13px; font-weight: 700; color: var(--fg); margin-right: 4px;
  font-variant-numeric: tabular-nums;
}

/* 2px surface gap so adjacent fills never touch. */
.ct-stack { display: flex; height: 9px; width: 100%; gap: 2px; }
.ct-stack-empty { background: color-mix(in srgb, var(--fg) 6%, transparent); border-radius: 2px; }
.ct-stack-seg { width: var(--w); background: var(--c); border-radius: 2px; min-width: 2px; }

/* Empty states show SHAPE, never a lesson (taste corpus entry 13). */
.ct-empty { padding: 6px 0 2px; }
.ct-empty-ghost { display: flex; flex-direction: column; gap: 6px; margin-bottom: 9px; }
.ct-empty-ghost span {
  height: 8px; border-radius: 2px;
  background: color-mix(in srgb, var(--fg) 5%, transparent);
}
.ct-empty-ghost span:nth-child(1) { width: 72%; }
.ct-empty-ghost span:nth-child(2) { width: 51%; }
.ct-empty-ghost span:nth-child(3) { width: 33%; }
.ct-empty-ghost span:nth-child(4) { width: 19%; }
.ct-empty p { margin: 0; font-family: var(--mono); font-size: 11px; color: var(--fg-mute); }

/* --- BAND 1: the bill, read as arithmetic --------------------------------- */

.ct-ledger { display: flex; align-items: flex-start; gap: 18px 28px; flex-wrap: wrap; }
/* Operators align to the numerals' optical middle, not to the caption baseline. */
.ct-math { display: flex; align-items: flex-start; gap: 14px; flex-wrap: wrap; }
.ct-op {
  font-size: 1.3rem; font-style: normal; font-weight: 400; line-height: 1;
  color: var(--fg-mute); margin-top: 8px;
}

.ct-fig b {
  display: block; font-size: 1.75rem; font-weight: 900; letter-spacing: -.03em;
  line-height: 1.05; font-variant-numeric: tabular-nums; color: var(--fg);
}
.ct-fig span {
  display: block; margin-top: 4px;
  font-family: var(--mono); font-size: 9.5px; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; color: var(--fg-mute);
}
.ct-fig-credit b { color: var(--fg-mute); }
/* The terminal figure is the only number that leaves the bank — spine + full ink. */
.ct-fig-net { padding-left: 11px; border-left: 3px solid var(--portal); }
.ct-fig-net b { color: var(--fg); font-size: 2rem; }

.ct-sides { display: flex; gap: 22px; flex-wrap: wrap; margin-left: auto; }
.ct-side b {
  display: block; font-family: var(--mono); font-size: 15px; font-weight: 700;
  font-variant-numeric: tabular-nums; color: var(--fg-dim);
}
.ct-side span {
  display: block; margin-top: 3px;
  font-family: var(--mono); font-size: 9px; letter-spacing: .07em;
  text-transform: uppercase; color: var(--fg-mute);
}

/* --- BAND 2: daily spend --------------------------------------------------- */

/* Top padding is headroom for the over-axis day labels, not decoration. */
.ct-chart { position: relative; padding: 16px 0 0 54px; }
.ct-plot { position: relative; height: 172px; }
.ct-tick {
  position: absolute; left: 0; right: 0; bottom: var(--y);
  border-top: 1px dashed color-mix(in srgb, var(--fg) 9%, transparent);
  pointer-events: none;
}
.ct-tick > span {
  position: absolute; right: calc(100% + 7px); top: -.55em;
  font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); white-space: nowrap;
}
.ct-tick-base { border-top: 1px solid var(--ct-line); border-top-style: solid; }

/* The everyday floor, kept legible when a spike day owns the y-axis. It reads as
   part of the axis (labelled in the same gutter as the ticks) and sits ABOVE the
   bars — a reference line you can't trace across the plot isn't one. */
.ct-med {
  position: absolute; left: 0; right: 0; bottom: var(--y); z-index: 3;
  border-top: 1px dashed color-mix(in srgb, var(--portal) 60%, transparent);
  pointer-events: none;
}
.ct-med > span {
  position: absolute; right: calc(100% + 7px); top: -.55em; white-space: nowrap;
  font-family: var(--mono); font-size: 9px; letter-spacing: .03em;
  color: color-mix(in srgb, var(--portal-2) 85%, var(--fg-mute));
}
.ct-med i { font-style: normal; }

.ct-cols { position: absolute; inset: 0; display: flex; gap: 2px; align-items: flex-end; }
.ct-col { position: relative; flex: 1; min-width: 0; height: 100%; }
/* The stack needs a DEFINITE height for the segments' percentage heights to
   resolve against — an auto-height flex item silently collapses them to 2px. */
/* Capped and centred so a 7-day range doesn't render seven 150px slabs. */
.ct-col-stack {
  position: absolute; top: 0; bottom: 0; left: 50%; transform: translateX(-50%);
  width: 100%; max-width: 72px;
  display: flex; flex-direction: column-reverse; justify-content: flex-start; gap: 2px;
}
.ct-col-seg {
  display: block; flex: none; width: 100%; height: var(--h); background: var(--c);
  border-radius: 2px 2px 0 0; min-height: 2px;
  transition: filter 140ms var(--ease);
}
.ct-col:hover .ct-col-seg { filter: brightness(1.18); }

/* A day that runs past the fitted axis: squared-off top, a cap rule, and its
   true value printed above. The number is never lost to the clip. */
.ct-col-over .ct-col-stack { border-top: 2px solid var(--fg-dim); }
.ct-col-over .ct-col-seg:last-child { border-radius: 0; }
.ct-col-lab {
  position: absolute; left: 50%; transform: translateX(-50%); bottom: calc(100% + 3px);
  font-family: var(--mono); font-size: 9.5px; font-weight: 700; color: var(--fg-dim);
  white-space: nowrap; z-index: 2; font-variant-numeric: tabular-nums;
}
.ct-xs { display: flex; gap: 2px; padding-top: 5px; }
.ct-x {
  flex: 1; min-width: 0; font-family: var(--mono); font-size: 9.5px;
  color: var(--fg-mute); text-align: center; white-space: nowrap; overflow: visible;
}

/* Surface-bordered float, present shadow (taste corpus e-13 C#1). */
.ct-tip {
  position: absolute; transform: translateX(-50%); pointer-events: none;
  background: var(--bg-elev); border: 1px solid var(--ct-line); border-radius: 2px;
  padding: 7px 9px; box-shadow: 0 12px 28px -8px rgba(0, 0, 0, .45);
  z-index: 5; min-width: 118px;
}
.ct-tip strong { display: block; font-size: 11px; font-weight: 700; margin-bottom: 4px; color: var(--fg); }
.ct-tip-row {
  display: flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: 10.5px; color: var(--fg-dim); line-height: 1.7;
}
.ct-tip-row b { margin-left: auto; color: var(--fg); font-variant-numeric: tabular-nums; }
.ct-tip-tot { border-top: 1px solid var(--ct-line); margin-top: 3px; padding-top: 3px; }

/* --- BAND 3: composition + ranked services --------------------------------- */

.ct-comp { margin-bottom: 12px; }
.ct-comp-keys { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 8px; }
.ct-comp-key {
  display: inline-flex; align-items: baseline; gap: 6px;
  font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute);
}
.ct-comp-key .ct-key { align-self: center; }
.ct-comp-key b { font-size: 12.5px; font-weight: 700; color: var(--fg); font-variant-numeric: tabular-nums; }
.ct-comp-key i { font-style: normal; font-size: 9.5px; color: var(--fg-mute); }

/* One row shape for services, models and features — learned once, read everywhere. */
.ct-rank { display: flex; flex-direction: column; }
/* The label column is capped, not elastic — a 1.5fr label column next to short
   service names is how a dense table grows a dead gutter down its middle. */
.ct-rank-row {
  display: grid; grid-template-columns: minmax(130px, 250px) minmax(0, 1fr) 74px 40px;
  align-items: center; gap: 12px; padding: 5px 0;
}
.ct-rank-row + .ct-rank-row { border-top: 1px solid var(--ct-line); }
.ct-rank-k { display: flex; align-items: center; gap: 6px; min-width: 0; }
.ct-rank-lab { font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ct-rank-note {
  font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute);
  white-space: nowrap; flex: none;
}
.ct-rank-bar { height: 8px; background: color-mix(in srgb, var(--fg) 5%, transparent); border-radius: 2px; }
/* A nonzero value always leaves a mark — an empty track would read as "none". */
.ct-rank-bar i {
  display: block; height: 8px; width: var(--w); min-width: 2px;
  border-radius: 2px; background: var(--c, var(--ct-bar));
}

/* The sub-cent tail, summed rather than listed as five empty tracks. */
.ct-rank-rest {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin-top: 8px; padding-top: 7px; border-top: 1px solid var(--ct-line);
  font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute);
}
.ct-rank-rest i { font-style: normal; font-size: 9.5px; opacity: .75; }
.ct-rank-v {
  font-family: var(--mono); font-size: 12px; font-weight: 700; text-align: right;
  font-variant-numeric: tabular-nums;
}
.ct-rank-p { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); text-align: right; }

/* --- BAND 4: reconciliation ------------------------------------------------ */

.ct-recon { margin-bottom: 13px; }
.ct-recon .ct-stats { margin-bottom: 6px; }
.ct-recon-cover {
  display: block; font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute);
  line-height: 1.5;
}
.ct-recon-cover b { color: var(--fg-dim); font-weight: 700; }

/* --- BAND 5: the call ledger ----------------------------------------------- */

.ct-table { font-size: 12px; }
.ct-row {
  display: grid; grid-template-columns: 82px minmax(120px, 1.6fr) minmax(96px, 1fr) 74px 74px 82px;
  align-items: center; gap: 10px; padding: 5px 0;
  border-top: 1px solid var(--ct-line);
}
.ct-row-head {
  border-top: 0; padding-bottom: 3px;
  font-family: var(--mono); font-size: 9px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--fg-mute);
}
.ct-row-head > span:nth-child(n+4) { text-align: right; }
.ct-row:not(.ct-row-head):hover { background: color-mix(in srgb, var(--fg) 3%, transparent); }
.ct-when { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); white-space: nowrap; }
.ct-model { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ct-feat { min-width: 0; }
.ct-tag {
  display: inline-block; max-width: 100%; font-family: var(--mono); font-size: 9.5px;
  padding: 2px 5px; border-radius: 2px; color: var(--fg-dim);
  background: color-mix(in srgb, var(--fg) 6%, transparent);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle;
}
.ct-n {
  font-family: var(--mono); font-size: 11px; text-align: right;
  font-variant-numeric: tabular-nums; color: var(--fg-dim);
}
.ct-n-cost { color: var(--fg); font-weight: 700; }

.ct-find {
  font: inherit; font-size: 11.5px; padding: 4px 8px; border-radius: 2px;
  background: var(--bg-soft); border: 1px solid var(--ct-line); color: var(--fg); width: 130px;
}
.ct-find:focus { outline: none; background: color-mix(in srgb, var(--portal) 8%, var(--bg-soft)); }

/* --- narrow ---------------------------------------------------------------- */

@media (max-width: 900px) {
  .ct-two { grid-template-columns: 1fr; gap: 16px; }
  .ct-sides { margin-left: 0; }
  .ct-fig b { font-size: 1.45rem; }
  .ct-fig-net b { font-size: 1.6rem; }
  .ct-rank-row { grid-template-columns: minmax(96px, 180px) minmax(0, 1fr) 68px 36px; }
  .ct-row { grid-template-columns: 70px minmax(90px, 1.4fr) minmax(80px, 1fr) 62px 62px 74px; }
}
@media (max-width: 620px) {
  .ct-chart { padding-left: 40px; }
  .ct-med i { display: none; }   /* the gutter can't hold "med $0.44" — the value alone does */
  .ct-row { grid-template-columns: 62px 1fr 74px; }
  .ct-row > span:nth-child(3), .ct-row > span:nth-child(4), .ct-row > span:nth-child(5) { display: none; }
  .ct-row-head > span:nth-child(6) { text-align: right; }
}

/* === Remote Build Runner (build_task #182 Phase 3) ========================= */
.rn-gate-note {
  font-family: var(--mono); font-size: 10.5px; line-height: 1.4;
  color: var(--fg-mute); align-self: center; max-width: 42ch;
}
.rn-status {
  font-family: var(--mono); font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; padding: .1rem .5rem; border-radius: 999px;
}
.rn-status-progress { background: color-mix(in srgb, var(--portal) 16%, transparent); color: var(--portal-2); }
.rn-status-ok { background: color-mix(in srgb, var(--c-mint-1) 18%, transparent); color: var(--c-mint-1); }
.rn-status-fail { background: color-mix(in srgb, var(--c-coral-2) 18%, transparent); color: var(--c-coral-2); }
.rn-status-parked { background: color-mix(in srgb, var(--c-amber-1) 18%, transparent); color: var(--c-amber-1); }

/* === Progress bars (requirements) ========================================= */
.req-card { display: block; }
.req-top { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; }
.req-top .ttl { font-weight: 700; }
.req-count { font-family: var(--mono); font-size: 12px; color: var(--fg-mute); }
.req-bar {
  height: 8px; border-radius: 999px; margin-top: .6rem; overflow: hidden;
  background: var(--bg-deep);
}
.req-bar > span {
  display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, color-mix(in srgb, var(--tone, var(--portal)) 68%, transparent), var(--tone, var(--portal)));
  transition: width var(--t-base) var(--ease);
}

/* === Tables (courses) ===================================================== */
.portal-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.portal-table th {
  text-align: left; font-family: var(--mono); font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; color: var(--fg-mute);
  padding: .6rem .75rem; border-bottom: 1px solid var(--border-hi);
}
.portal-table td { padding: .65rem .75rem; border-bottom: 1px solid var(--hairline); }
.portal-table tr:hover td { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.portal-table .num { text-align: right; font-family: var(--mono); }

/* === Segmented tabs ======================================================= */
.seg {
  display: inline-flex; gap: .25rem; padding: .3rem; border-radius: 14px;
  background: var(--bg-soft); border: 1px solid var(--hairline); flex-wrap: wrap;
}
.seg button {
  font: inherit; font-weight: 600; font-size: 13.5px; cursor: pointer;
  padding: .45rem 1rem; border-radius: 10px; border: none; background: transparent; color: var(--fg-dim);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.seg button:hover { color: var(--fg); }
.seg button[aria-selected="true"] {
  background: color-mix(in srgb, var(--tone, var(--portal)) 12%, var(--mat-1));
  color: var(--tone, var(--portal-2));
  box-shadow: var(--shadow-xs);
}
.seg-panel { display: none; margin-top: 2rem; }
.seg-panel.active { display: block; }

/* === Reference content (music suite) ===================================== */
.ref-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.25rem; }
.ref-card {
  padding: 1.5rem; border-radius: var(--radius-sm);
  background: var(--mat-1); border: 1px solid var(--hairline);
}
.ref-card h4 { margin: 0 0 .75rem; font-size: 1.05rem; }
.ref-card ul { margin: 0; padding-left: 1.1rem; color: var(--fg-dim); font-size: 14px; }
.ref-card li { margin: .3rem 0; }
.ref-card li b { color: var(--fg); font-weight: 700; }

.kbd-search { margin-bottom: 1.25rem; }
.kbd-table { width: 100%; border-collapse: collapse; font-size: 14px; }
.kbd-table td { padding: .5rem .75rem; border-bottom: 1px solid var(--hairline); }
.kbd-table td:first-child { color: var(--fg-dim); width: 60%; }
.kbd-row.is-hidden { display: none; }
kbd {
  font-family: var(--mono); font-size: 12px; font-weight: 600;
  padding: .15rem .5rem; border-radius: 7px; white-space: nowrap;
  background: var(--bg-soft); border: 1px solid var(--border-hi);
  box-shadow: 0 1px 0 var(--border-hi);
}

/* === Font tool ============================================================ */
.font-tool { display: flex; flex-direction: column; gap: 1.5rem; }
.font-controls {
  display: flex; gap: 1rem; flex-wrap: wrap; align-items: flex-end;
  padding: 1.25rem; border-radius: 14px; background: var(--mat-1); border: 1px solid var(--hairline);
}
.font-controls label { display: flex; flex-direction: column; gap: .3rem; font-size: 12px; }
.font-controls .crud-field-label { color: var(--fg-mute); }
.font-controls input[type="text"], .font-controls input[type="number"] {
  background: transparent; border: 1px solid var(--border-hi); border-radius: 10px;
  color: var(--fg); font: inherit; padding: .5rem .75rem;
}
.font-sample-input { flex: 1 1 18rem; }
.font-range { width: 9rem; }

.font-board { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1rem; }
.font-cell {
  padding: 1.25rem; border-radius: 14px; background: var(--mat-1); border: 1px solid var(--hairline);
  position: relative; transition: border-color var(--t-fast) var(--ease);
}
.font-cell.picked { border-color: var(--portal-2); box-shadow: 0 0 0 1px var(--portal-2) inset; }
.font-cell-name { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); display: flex; justify-content: space-between; align-items: center; }
.font-cell-star { background: none; border: none; cursor: pointer; font-size: 16px; color: var(--fg-mute); line-height: 1; }
.font-cell.picked .font-cell-star { color: var(--c-amber-1); }
.font-cell-sample { margin-top: .75rem; line-height: 1.25; word-break: break-word; }

/* A/B quiz */
.font-quiz { display: grid; grid-template-columns: 1fr auto 1fr; gap: 1rem; align-items: stretch; }
.font-vs {
  align-self: center; font-family: var(--mono); font-weight: 700; color: var(--fg-mute);
}
.font-duel {
  padding: 2rem 1.5rem; border-radius: 16px; cursor: pointer; text-align: center;
  background: var(--mat-1); border: 1px solid var(--hairline);
  transition: transform var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.font-duel:hover { transform: translateY(-3px); border-color: var(--portal-2); }
.font-duel .lbl { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); display: block; margin-bottom: .75rem; }
.font-duel .smp { font-size: 1.5rem; line-height: 1.3; }
.font-quiz-meta { font-family: var(--mono); font-size: 12px; color: var(--fg-mute); margin-top: .5rem; text-align: center; }

.font-ranked { display: flex; flex-direction: column; gap: .5rem; }
.font-rank-row {
  display: flex; align-items: center; gap: 1rem; padding: .6rem .9rem; border-radius: 10px;
  background: var(--mat-1); border: 1px solid var(--hairline);
}
.font-rank-row .pos { font-family: var(--mono); color: var(--portal-2); font-weight: 700; width: 1.5rem; }
.font-rank-row .nm { flex: 1; font-weight: 600; }
.font-rank-row .sc { font-family: var(--mono); font-size: 12px; color: var(--fg-mute); }

/* === Toast ================================================================ */
.rk-toast {
  position: fixed; bottom: 1.5rem; left: 50%; transform: translate(-50%, 1.5rem);
  z-index: 300; padding: .7rem 1.2rem; border-radius: 12px;
  background: var(--portal-2); color: var(--accent-fg); font-weight: 700; font-size: 14px;
  box-shadow: var(--shadow-md); opacity: 0; pointer-events: none;
  transition: opacity var(--t-fast) var(--ease), transform var(--t-base) var(--ease-spring);
}
.rk-toast.show { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }

@media (max-width: 640px) {
  .font-quiz { grid-template-columns: 1fr; }
  .font-vs { display: none; }
}

/* =============================================================================
   Private Data Layer — Inventory · History · Transcripts
   An accumulator, never a source-of-truth: a sparse record is the native state,
   not a defect, so nothing here renders "missing data" as an error.
============================================================================= */

/* Stacked CRUD card (Inventory/History read better as a block than a row). */
.crud-card.stacked { flex-direction: column; align-items: stretch; gap: .6rem; }
.crud-card.stacked .crud-card-actions { justify-content: flex-end; }
.crud-card-body .meta.wrap { white-space: pre-wrap; }
.crud-card-body .note {
  font-size: 13.5px; color: var(--fg-dim); margin-top: .35rem; white-space: pre-wrap; line-height: 1.5;
}
.crud-card-body .tag.alt {
  background: color-mix(in srgb, var(--c-violet-1) 16%, transparent); color: var(--c-violet-1);
}
.crud-card-body .tag.muted {
  background: var(--bg-soft); color: var(--fg-mute);
}

/* === Tag chips (transcripts) ============================================== */
.tagrow { display: flex; flex-wrap: wrap; gap: .4rem; align-items: center; }
.tagchip {
  display: inline-flex; align-items: center; gap: .35rem;
  font-family: var(--mono); font-size: 11px; font-weight: 600;
  padding: .2rem .55rem; border-radius: 999px;
  background: color-mix(in srgb, var(--portal) 13%, transparent); color: var(--portal-2);
  border: 1px solid color-mix(in srgb, var(--portal) 24%, transparent);
}
.tagchip.turn { background: color-mix(in srgb, var(--c-cyan-1) 13%, transparent); color: var(--c-cyan-1);
  border-color: color-mix(in srgb, var(--c-cyan-1) 26%, transparent); }
.tagchip-x { background: none; border: none; color: inherit; cursor: pointer; font-size: 13px; line-height: 1; opacity: .7; padding: 0; }
.tagchip-x:hover { opacity: 1; }
.tag-add {
  background: none; border: 1px dashed var(--border-hi); border-radius: 999px;
  color: var(--fg-mute); font-family: var(--mono); font-size: 11px; padding: .2rem .55rem; cursor: pointer;
}
.tag-add:hover { color: var(--portal-2); border-color: var(--portal-2); }

/* === Import dropzone ====================================================== */
.import-drop {
  border: 1.5px dashed var(--border-hi); border-radius: 16px; padding: 2.5rem 1.5rem;
  text-align: center; background: var(--mat-1); cursor: pointer;
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.import-drop.drag { border-color: var(--portal-2); background: color-mix(in srgb, var(--portal) 7%, var(--mat-1)); }
.import-drop .big { font-size: 1.1rem; font-weight: 700; }
.import-drop .small { font-family: var(--mono); font-size: 12px; color: var(--fg-mute); margin-top: .4rem; }
.import-log { display: flex; flex-direction: column; gap: .4rem; margin-top: 1rem; }
.import-log-row {
  font-family: var(--mono); font-size: 12.5px; padding: .5rem .75rem; border-radius: 10px;
  background: var(--mat-1); border: 1px solid var(--hairline); display: flex; gap: .6rem; align-items: center;
}
.import-log-row .ok { color: var(--portal-2); }
.import-log-row .warn { color: var(--c-amber-1); }
.import-log-row .err { color: var(--c-coral-2); }

/* === Transcript management cards ========================================== */
.tx-list { display: flex; flex-direction: column; gap: .75rem; }
.tx-card {
  padding: 1rem 1.25rem; border-radius: 14px;
  background: var(--mat-1); border: 1px solid var(--hairline);
  display: flex; flex-direction: column; gap: .6rem;
}
.tx-top { display: flex; align-items: baseline; gap: .75rem; flex-wrap: wrap; }
.tx-top .tx-title { font-weight: 700; font-size: 1.02rem; }
.tx-top .tx-title a { color: inherit; }
.tx-top .tx-title a:hover { color: var(--portal-2); }
.tx-src {
  font-family: var(--mono); font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  padding: .1rem .5rem; border-radius: 999px; background: var(--bg-soft); color: var(--fg-mute);
}
.tx-meta { font-family: var(--mono); font-size: 12px; color: var(--fg-mute); }
.tx-actions { display: flex; gap: .4rem; flex-wrap: wrap; }

/* === Explicit Failure corpus ============================================== */
.fail-list { display: flex; flex-direction: column; gap: .75rem; }
.fail-card {
  padding: 1.1rem 1.25rem; border-radius: 14px;
  background: var(--mat-1);
  border: 1px solid color-mix(in srgb, var(--c-coral-1) 22%, var(--hairline));
  border-left: 3px solid var(--c-coral-1);
  display: flex; flex-direction: column; gap: .5rem;
}
.fail-card.unconfirmed { border-left-color: var(--c-amber-1); }
.fail-what { font-weight: 700; }
.fail-line { font-size: 13.5px; color: var(--fg-dim); line-height: 1.5; }
.fail-line b { color: var(--fg); font-family: var(--mono); font-size: 11px; text-transform: uppercase;
  letter-spacing: .05em; margin-right: .4rem; }
.fail-quote {
  font-style: italic; color: var(--fg-mute); font-size: 13px; padding-left: .8rem;
  border-left: 2px solid var(--hairline);
}
.fail-foot { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  font-family: var(--mono); font-size: 11px; color: var(--fg-mute); }
.fail-badge {
  font-family: var(--mono); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  padding: .1rem .45rem; border-radius: 999px;
}
.fail-badge.ok { background: color-mix(in srgb, var(--portal) 16%, transparent); color: var(--portal-2); }
.fail-badge.pending { background: color-mix(in srgb, var(--c-amber-1) 18%, transparent); color: var(--c-amber-1); }

/* =============================================================================
   History — four lenses, four bespoke treatments (no tabs; all visible).
   Whitespace separates the lenses; each earns its own shape.
============================================================================= */
.hist-sec { margin-top: 2.75rem; }
.hist-sec-head {
  display: flex; align-items: center; gap: .85rem; margin-bottom: 1.1rem;
  padding-bottom: .7rem; border-bottom: 1px solid var(--hairline);
}
.hist-glyph {
  width: 36px; height: 36px; flex-shrink: 0; display: grid; place-items: center; font-size: 17px;
  border-radius: 11px; color: var(--tint, var(--portal));
  background: color-mix(in srgb, var(--tint, var(--portal)) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--tint, var(--portal)) 26%, transparent);
}
.hist-sec-txt { flex: 1; min-width: 0; }
.hist-sec-txt h3 { margin: 0; font-size: 1.25rem; font-weight: 800; letter-spacing: -.02em; }
.hist-sec-txt .hint { font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); }
.hist-count { font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); white-space: nowrap; }

/* --- Academic: nested transcript tree ------------------------------------- */
.acad-inst {
  padding: 1.4rem 1.5rem; border-radius: var(--radius-sm); margin-bottom: 1rem;
  background: var(--mat-1); border: 1px solid var(--hairline);
}
/* Collapsible institution — summary is the clickable header. */
.acad-inst > summary { list-style: none; cursor: pointer; display: flex; align-items: baseline; justify-content: space-between;
  gap: .75rem; flex-wrap: wrap; }
.acad-inst > summary::-webkit-details-marker { display: none; }
.acad-inst-name { display: flex; align-items: baseline; gap: .75rem; flex-wrap: wrap; }
.acad-inst-h h4 { margin: 0; font-size: 1.1rem; font-weight: 800; letter-spacing: -.01em; }
.acad-inst-name h4::before { content: "▸"; display: inline-block; margin-right: .5rem; color: var(--fg-mute); font-size: .8em;
  transition: transform var(--t-fast) var(--ease); }
.acad-inst[open] > summary .acad-inst-name h4::before { transform: rotate(90deg); }
.acad-inst-stats { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); }
.acad-inst-body { margin-top: .9rem; }
.acad-loc { font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); }
.acad-note { font-size: 13px; color: var(--fg-dim); font-style: italic; margin: .25rem 0 .6rem; }

.acad-year { margin-top: 1rem; padding-left: 1rem; border-left: 2px solid var(--border-hi); }
.acad-year > summary { list-style: none; cursor: pointer; display: flex; align-items: baseline; gap: .6rem;
  font-family: var(--mono); font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .09em; color: var(--portal-2); margin-bottom: .6rem; }
.acad-year > summary::-webkit-details-marker { display: none; }
.acad-year > summary::before { content: "▸"; color: var(--fg-mute); transition: transform var(--t-fast) var(--ease); }
.acad-year[open] > summary::before { transform: rotate(90deg); }
.acad-year-meta { font-weight: 500; text-transform: none; letter-spacing: 0; color: var(--fg-mute); }
/* Terms flow side-by-side so a transcript reads as a grid, not a tall ribbon. */
.acad-terms { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: .4rem 1.75rem; }
.acad-term { margin: 0 0 .85rem; }
.acad-term-h {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  padding-bottom: .3rem; border-bottom: 1px dashed var(--hairline); margin-bottom: .35rem;
}
.acad-term-name { font-weight: 700; font-size: 14px; }
.acad-campus {
  font-family: var(--mono); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  padding: .05rem .4rem; border-radius: 999px; margin-left: .35rem;
  background: color-mix(in srgb, var(--c-violet-1) 16%, transparent); color: var(--c-violet-1);
}
.acad-term-meta { display: inline-flex; gap: .6rem; font-family: var(--mono); font-size: 11px; }
.acad-gpa { color: var(--fg-dim); }
.acad-cr { color: var(--fg-mute); }
.acad-term.is-planned { opacity: .72; }

.acad-courses { display: flex; flex-direction: column; gap: .1rem; }
.acad-course {
  display: grid; grid-template-columns: 2.4rem 5.2rem 1fr 2rem; align-items: center; gap: .6rem;
  padding: .3rem .4rem; border-radius: 8px; font-size: 13.5px;
}
.acad-course:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.acad-code { font-family: var(--mono); font-size: 11.5px; color: var(--fg-dim); }
.acad-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.acad-ccr { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); text-align: right; }
.acad-empty { font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); padding: .2rem .4rem; }

.grade {
  font-family: var(--mono); font-size: 11px; font-weight: 700; text-align: center;
  padding: .1rem 0; border-radius: 7px; min-width: 2.4rem;
}
.grade.ace  { background: color-mix(in srgb, var(--c-mint-1) 18%, transparent);  color: var(--c-mint-1); }
.grade.good { background: color-mix(in srgb, var(--c-cyan-1) 16%, transparent);  color: var(--c-cyan-1); }
.grade.ok   { background: color-mix(in srgb, var(--c-amber-1) 18%, transparent); color: var(--c-amber-1); }
.grade.bad  { background: color-mix(in srgb, var(--c-coral-1) 20%, transparent); color: var(--c-coral-2); }
.grade.plan { background: var(--bg-soft); color: var(--fg-mute); }

.acad-aux { margin-top: 1rem; padding-top: .75rem; border-top: 1px solid var(--hairline); }
.acad-aux-h {
  font-family: var(--mono); font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--fg-mute); margin-bottom: .45rem;
}
.acad-aux-h .dim { color: var(--fg-mute); font-weight: 500; text-transform: none; letter-spacing: 0; }
.acad-line { font-size: 13.5px; color: var(--fg-dim); margin: .25rem 0; line-height: 1.45; }
.acad-line b { color: var(--fg); }
.acad-chips { display: flex; flex-wrap: wrap; gap: .35rem; }
.acad-tchip {
  font-family: var(--mono); font-size: 11px; padding: .15rem .5rem; border-radius: 999px;
  background: var(--bg-soft); border: 1px solid var(--hairline); color: var(--fg-dim);
}
.acad-tchip i { color: var(--fg-mute); font-style: normal; }

/* --- Personal: timeline --------------------------------------------------- */
.tl { position: relative; padding-left: 1.5rem; }
.tl::before {
  content: ""; position: absolute; left: 5px; top: .4rem; bottom: 2.4rem; width: 2px;
  background: linear-gradient(var(--border-hi), transparent);
}
.tl-item { position: relative; padding: 0 0 1.4rem; }
.tl-dot {
  position: absolute; left: -1.5rem; top: .25rem; width: 12px; height: 12px; border-radius: 999px;
  background: var(--tint, var(--portal)); box-shadow: 0 0 0 4px var(--bg);
}
.tl-body {
  background: var(--mat-1); border: 1px solid var(--hairline); border-radius: 14px; padding: .85rem 1.1rem;
}
.tl-top { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.tl-date { font-family: var(--mono); font-size: 11.5px; color: var(--portal-2); font-weight: 700; }
.tl-del {
  background: none; border: none; color: var(--fg-mute); cursor: pointer; font-size: 16px; line-height: 1;
  opacity: 0; transition: opacity var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.tl-item:hover .tl-del, .psy-card:hover .tl-del { opacity: .7; }
.tl-del:hover { color: var(--c-coral-2); opacity: 1; }
.tl-ttl { font-weight: 700; font-size: 1rem; margin-top: .15rem; }
.tl-cat {
  font-family: var(--mono); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  padding: .05rem .4rem; border-radius: 999px; margin-left: .35rem; vertical-align: middle;
  background: color-mix(in srgb, var(--c-coral-1) 15%, transparent); color: var(--c-coral-1);
}
.tl-place { display: block; font-family: var(--mono); font-size: 12px; color: var(--fg-mute); margin-top: .2rem; }
.tl-story { font-size: 13.5px; color: var(--fg-dim); line-height: 1.55; margin-top: .45rem; }
.tl-add {
  background: none; border: 1px dashed var(--border-hi); border-radius: 12px; color: var(--fg-mute);
  font-family: var(--mono); font-size: 12px; padding: .5rem 1rem; cursor: pointer; margin-left: -1.5rem;
}
.tl-add:hover { color: var(--portal-2); border-color: var(--portal-2); }

/* --- Psychological: three lanes ------------------------------------------- */
.psy-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.psy-lane {
  display: flex; flex-direction: column; gap: .6rem;
  padding: 1.1rem; border-radius: var(--radius-sm);
  background: var(--mat-1); border: 1px solid var(--hairline);
}
.psy-lane-h { border-bottom: 1px solid var(--hairline); padding-bottom: .5rem; }
.psy-lane-name { display: block; font-weight: 800; font-size: 1rem; letter-spacing: -.01em; }
.psy-lane-hint { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }
.psy-cards { display: flex; flex-direction: column; gap: .5rem; }
.psy-card {
  padding: .65rem .8rem; border-radius: 11px;
  background: var(--bg-soft); border: 1px solid var(--hairline);
  border-left: 3px solid color-mix(in srgb, var(--c-violet-1) 55%, transparent);
}
.psy-top { display: flex; align-items: center; justify-content: space-between; gap: .5rem; }
.psy-cond { font-weight: 700; font-size: 14px; }
.psy-full { font-size: 12px; color: var(--fg-mute); margin-top: .1rem; }
.psy-note { font-size: 12.5px; color: var(--fg-dim); line-height: 1.5; margin-top: .35rem; }
.psy-empty { font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); padding: .3rem 0; }
.psy-add { align-self: flex-start; }

/* --- Working: ledger ------------------------------------------------------ */
.work-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.work-group {
  padding: 1.1rem 1.2rem; border-radius: var(--radius-sm);
  background: var(--mat-1); border: 1px solid var(--hairline);
}
.work-kind {
  font-family: var(--mono); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .09em;
  color: var(--portal-2); margin-bottom: .65rem; padding-bottom: .4rem; border-bottom: 1px solid var(--hairline);
}
.work-job { padding: .5rem 0; }
.work-job + .work-job { border-top: 1px dashed var(--hairline); }
.work-job-h { display: flex; align-items: baseline; justify-content: space-between; gap: .75rem; }
.work-name { font-weight: 600; font-size: 13.5px; }
.work-loc { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); text-align: right; }

/* Shared history affordances: detail lists, inline add inputs, mini buttons */
.det-list { list-style: none; margin: .5rem 0 .35rem; padding: 0; display: flex; flex-direction: column; gap: .3rem; }
.det-list li { position: relative; padding-left: .95rem; font-size: 13px; color: var(--fg-dim); line-height: 1.5; }
.det-list li::before { content: ""; position: absolute; left: 0; top: .55em; width: 5px; height: 5px; border-radius: 999px; background: color-mix(in srgb, var(--portal) 55%, var(--fg-mute)); }
.hist-mini { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); background: none; border: none; cursor: pointer; padding: .2rem 0; }
.hist-mini:hover { color: var(--portal-2); }
.hist-mini.add { color: color-mix(in srgb, var(--portal-2) 80%, var(--fg-mute)); }
.hist-mini.ghost { display: inline-block; margin-top: .6rem; padding: .4rem .7rem; border: 1px dashed var(--hairline); border-radius: 10px; }
.hist-mini.ghost:hover { border-color: var(--portal-2); }
.hist-mini.del { opacity: 0; transition: opacity var(--t-fast) var(--ease); }
.hist-mini.del:hover { color: var(--c-coral-2); }
.res-card:hover .hist-mini.del, .psy-cond:hover .hist-mini.del { opacity: .6; }
.hist-mini.ok { color: var(--portal-2); font-weight: 700; }
/* Cross-links: each life-dimension lens points at where that data also lives on
   the site (Places residences/workplaces, School record, LM-Science). */
.hist-xlinks { display: flex; flex-wrap: wrap; gap: .5rem .9rem; margin-bottom: 1rem; }
.hist-xlink {
  display: inline-flex; align-items: center; gap: .4rem; text-decoration: none;
  font-family: var(--mono); font-size: 11.5px; font-weight: 600; letter-spacing: .01em;
  color: var(--portal-2); padding: .3rem .6rem; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--portal) 30%, var(--hairline));
  background: color-mix(in srgb, var(--portal) 8%, transparent);
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.hist-xlink:not(.inline) { margin-bottom: 1rem; }
.hist-xlinks .hist-xlink { margin-bottom: 0; }
.hist-xlink:hover { border-color: var(--portal-2); background: color-mix(in srgb, var(--portal) 15%, transparent); }
.hist-xlink.inline { border: 0; background: none; padding: 0; margin: 0; }
.hist-xlink.inline:hover { text-decoration: underline; }
.hist-lede { margin: 0 0 1.1rem; font-size: 13px; line-height: 1.55; color: var(--fg-dim); max-width: 70ch; }
.inline-add { display: flex; gap: .4rem; align-items: center; margin: .4rem 0; }
.inline-add input { flex: 1; min-width: 0; background: var(--bg-soft); border: 1px solid var(--hairline); border-radius: 9px;
  color: var(--fg); font: inherit; font-size: 13px; padding: .35rem .55rem; }
.inline-add input:focus { outline: none; border-color: var(--portal-2); }

/* Residency — place-centric cards on a left rail */
.res-list { position: relative; padding-left: 1.5rem; }
.res-list::before { content: ""; position: absolute; left: 5px; top: .4rem; bottom: .4rem; width: 2px; background: var(--hairline); }
.res-card { position: relative; padding: 0 0 1.3rem; }
.res-dot { position: absolute; left: -1.5rem; top: .3rem; width: 11px; height: 11px; border-radius: 999px; background: var(--tint); box-shadow: 0 0 0 4px var(--bg); }
.res-head { display: flex; align-items: baseline; gap: .6rem; }
.res-where { flex: 1; min-width: 0; display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.res-place { font-weight: 800; font-size: 1.02rem; letter-spacing: -.01em; }
.res-cat { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-mute);
  padding: .08em .45em; border-radius: 999px; background: var(--bg-soft); border: 1px solid var(--hairline); }
.res-date { font-family: var(--mono); font-size: 11.5px; color: var(--portal-2); font-weight: 700; white-space: nowrap; }
.res-label { font-size: 12.5px; color: var(--fg-mute); margin-top: .1rem; }
.res-story { font-size: 13.5px; color: var(--fg-dim); line-height: 1.55; margin-top: .45rem; }

/* Psychological — conditions as standing subcategory containers */
.psy-conds { display: flex; flex-direction: column; gap: .55rem; }
.psy-cond { font-weight: 400; font-size: 13px; padding: .6rem .7rem; border-radius: var(--radius-xs); background: var(--bg-soft); border: 1px solid var(--hairline); border-left: 2px solid color-mix(in srgb, var(--c-violet-1) 55%, transparent); }
.psy-cond-h { display: flex; align-items: baseline; justify-content: space-between; gap: .5rem; }
.psy-cond-name b { font-weight: 700; font-size: 14px; }
.psy-cond-name .psy-full { display: block; font-size: 11.5px; color: var(--fg-mute); margin-top: .1rem; }

@media (max-width: 860px) {
  .res-list { padding-left: 1.2rem; }
}

/* --- Inline add forms (personal / psychological) -------------------------- */
.hist-form {
  background: var(--mat-1); border: 1px solid color-mix(in srgb, var(--portal) 30%, var(--hairline));
  border-radius: 14px; padding: 1.1rem; margin-bottom: 1rem;
}
.hist-form.compact { padding: .85rem; margin-bottom: .5rem; display: flex; flex-direction: column; gap: .5rem; }
.hist-form-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: .85rem; }
.hist-form .crud-field.full { grid-column: 1 / -1; }

@media (max-width: 860px) {
  .psy-grid, .work-grid { grid-template-columns: 1fr; }
  .hist-form-grid { grid-template-columns: 1fr; }
  .acad-course { grid-template-columns: 2.4rem 4.6rem 1fr 1.8rem; }
}

/* =============================================================================
   School & SLU — a help suite computed from the academic transcript record.
============================================================================= */
.school-kpis { grid-template-columns: repeat(4, 1fr); margin-top: 1.5rem; margin-bottom: .6rem; }
.school-degree { height: 8px; margin: 0 0 1.5rem; }
.school-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 1rem; }
.school-grid .panel { margin: 0; }

/* GPA trend bars */
.gpa-bars { display: flex; align-items: flex-end; gap: .9rem; min-height: 130px; padding-top: .5rem; }
.gpa-bar { display: flex; flex-direction: column; align-items: center; gap: .35rem; flex: 1; min-width: 0; }
.gpa-track {
  width: 100%; max-width: 46px; height: 92px; border-radius: 8px 8px 4px 4px;
  background: var(--bg-soft); border: 1px solid var(--hairline);
  display: flex; align-items: flex-end; overflow: hidden;
}
.gpa-track > span {
  display: block; width: 100%; border-radius: 6px 6px 0 0;
  background: linear-gradient(var(--c-mint-1), var(--portal));
  transition: height var(--t-base) var(--ease);
}
.gpa-val { font-family: var(--mono); font-size: 11.5px; font-weight: 700; color: var(--fg); }
.gpa-lbl { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); white-space: nowrap; }

/* What-if calculator */
.calc { display: flex; flex-direction: column; gap: .15rem; }
.calc-row {
  display: grid; grid-template-columns: 5.2rem 1fr auto 4.2rem; align-items: center; gap: .6rem;
  padding: .3rem .4rem; border-radius: 8px; font-size: 13.5px;
}
.calc-row:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.calc-grade {
  background: transparent; border: 1px solid var(--border-hi); border-radius: 8px;
  color: var(--fg); font: inherit; font-size: 12.5px; padding: .2rem .4rem;
}
.calc-grade:focus { outline: none; border-color: var(--portal-2); }
.calc-out {
  display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap;
  margin-top: .6rem; padding-top: .7rem; border-top: 1px dashed var(--hairline);
}
.calc-out b { font-size: 1.5rem; font-weight: 900; letter-spacing: -.02em; color: var(--tone, var(--portal-2)); }
.calc-note { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); }

@media (max-width: 860px) {
  .school-kpis { grid-template-columns: repeat(2, 1fr); }
  .school-grid { grid-template-columns: 1fr; }
}

/* =============================================================================
   Subscriptions module
   -----------------------------------------------------------------------------
   A forecasting lens over the recurring Inventory items. Color is the visual
   language: each subscription carries a payment-method or category tint, shared
   across the calendar dots, breakdown bars, and chips.
============================================================================= */

/* Shared tinted pill — `--chip` is set inline to a --c-* var. */
.sub-chip {
  display: inline-flex; align-items: center; gap: .34em;
  font-family: var(--mono); font-size: 10.5px; font-weight: 600; color: var(--fg-dim);
  padding: .12em .5em .12em .42em; border-radius: 999px; white-space: nowrap;
  background: color-mix(in srgb, var(--chip) 12%, var(--bg-soft));
  border: 1px solid color-mix(in srgb, var(--chip) 26%, transparent);
}
.sub-chip::before { content: ""; width: 7px; height: 7px; border-radius: 999px; background: var(--chip); }

/* Cards + bars (overview breakdowns, forecast contribution, generic) */
.break-card, #ov-upcoming {
  padding: 1.1rem 1.2rem; border-radius: var(--radius-sm);
  background: var(--mat-1); border: 1px solid var(--hairline);
}
.break-head {
  font-family: var(--mono); font-size: 11px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--fg-dim); margin-bottom: .8rem;
}
.bar-row { display: grid; grid-template-columns: minmax(90px, 9rem) 1fr auto; align-items: center; gap: .7rem; margin: .5rem 0; }
.bar-label { font-size: 12.5px; color: var(--fg); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bar-track { height: 8px; border-radius: 999px; background: var(--bg-soft); overflow: hidden; }
.bar-fill { display: block; height: 100%; border-radius: 999px; }
.bar-val { font-family: var(--mono); font-size: 12px; color: var(--fg-dim); white-space: nowrap; }
.bar-unit { color: var(--fg-mute); font-size: .85em; }

/* Overview layout */
.sub-overview-grid { display: grid; grid-template-columns: 1.2fr 1fr; gap: 1rem; align-items: start; }
.break-grid { display: flex; flex-direction: column; gap: 1rem; }
#ov-upcoming .portal-block-head { margin-bottom: .4rem; }
.up-list { display: flex; flex-direction: column; }
.up-row { display: grid; grid-template-columns: 5.5rem 1fr auto; align-items: center; gap: .7rem; padding: .55rem .1rem; border-top: 1px solid var(--hairline); }
.up-row:first-child { border-top: none; }
.up-when { display: flex; flex-direction: column; font-size: 12.5px; }
.up-when b { font-weight: 700; }
.up-rel { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }
.up-name { display: flex; align-items: center; gap: .5rem; min-width: 0; font-size: 13.5px; }
.up-name .sub-chip { flex: none; }
.up-amt { font-family: var(--mono); font-weight: 700; color: var(--fg); }
.up-row.soon .up-amt, .up-row.soon .up-when b { color: var(--c-coral-1); }

/* === Calendar ============================================================= */
.cal-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap; margin: 1.5rem 0 1rem; }
.cal-nav { display: flex; gap: .4rem; }
.cal-btn {
  font-family: var(--mono); font-size: 13px; color: var(--fg-dim); cursor: pointer; min-width: 34px;
  background: var(--mat-1); border: 1px solid var(--hairline); border-radius: 10px; padding: .35rem .6rem;
}
.cal-btn:hover { color: var(--fg); border-color: color-mix(in srgb, var(--portal) 40%, transparent); }
.cal-today { font-weight: 700; }
.cal-title { font-size: 1.3rem; font-weight: 800; letter-spacing: -.02em; display: flex; align-items: baseline; gap: .7rem; flex-wrap: wrap; }
.cal-total { font-family: var(--mono); font-size: 12px; font-weight: 600; color: var(--portal-2); }
.cal-modes { display: inline-flex; border: 1px solid var(--hairline); border-radius: 10px; overflow: hidden; }
.cal-mode { font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); background: transparent; border: none; padding: .4rem .7rem; cursor: pointer; }
.cal-mode.on { background: color-mix(in srgb, var(--portal) 16%, var(--bg-soft)); color: var(--portal-2); }
.cal-dows { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; margin-bottom: 6px; }
.cal-dow { font-family: var(--mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; color: var(--fg-mute); text-align: center; }
.cal-cells { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.cal-cell {
  min-height: 104px; display: flex; flex-direction: column; align-items: stretch; gap: 4px;
  padding: .4rem; border-radius: var(--radius-xs); text-align: left; overflow: hidden;
  background: var(--mat-1); border: 1px solid var(--hairline);
}
.cal-cell.empty { background: transparent; border: none; min-height: 0; }
.cal-cell.today { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--portal) 45%, transparent); border-color: color-mix(in srgb, var(--portal) 55%, transparent); }
.cal-num { font-family: var(--mono); font-size: 12px; font-weight: 600; color: var(--fg-dim); }
.cal-cell.today .cal-num { color: var(--portal-2); font-weight: 800; }
.cal-charges { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cal-line { display: flex; align-items: center; gap: 4px; min-width: 0; font-size: 10.5px; line-height: 1.25; }
.cal-cdot { width: 6px; height: 6px; border-radius: 999px; flex: none; }
.cal-cname { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--fg-dim); }
.cal-camt { font-family: var(--mono); font-weight: 700; color: var(--fg); flex: none; }
.cal-more { font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); margin-top: 1px; }
.cal-detail { margin-top: 1.2rem; }
.cal-hint { font-family: var(--mono); font-size: 12.5px; color: var(--fg-mute); padding: .5rem 0; }
.cal-detail-head { display: flex; justify-content: space-between; align-items: baseline; padding: .5rem .1rem; font-size: 14px; border-bottom: 1px solid var(--hairline); }
.cal-detail-head span { font-family: var(--mono); color: var(--portal-2); font-weight: 700; }
.cal-charge { display: grid; grid-template-columns: auto 1fr auto auto; align-items: center; gap: .7rem; padding: .55rem .1rem; border-top: 1px solid var(--hairline); }
.cal-charge:first-of-type { border-top: none; }
.cc-dot { width: 9px; height: 9px; border-radius: 999px; }
.cc-name { font-size: 13.5px; }
.cc-meta { display: flex; gap: .4rem; }
.cc-amt { font-family: var(--mono); font-weight: 700; }

/* === Forecast ============================================================= */
.fc-head { margin-top: 1.5rem; display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; flex-wrap: wrap; }
.fc-controls { display: flex; align-items: center; gap: 1rem; }
.fc-slider-l { display: flex; align-items: center; gap: .7rem; font-family: var(--mono); font-size: 11.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--fg-mute); }
#fc-range { width: 220px; max-width: 50vw; accent-color: var(--portal); }
.fc-horizon { font-family: var(--mono); font-size: 13px; font-weight: 700; color: var(--portal-2); }
.fc-total { text-align: right; }
.fc-total-v { font-size: 1.8rem; font-weight: 900; letter-spacing: -.03em; color: var(--portal-2); }
.fc-total-k { display: block; font-family: var(--mono); font-size: 11px; color: var(--fg-mute); }
.fc-chart { margin: 1rem 0 1.5rem; padding: 1rem; border-radius: var(--radius-sm); background: var(--mat-1); border: 1px solid var(--hairline); }
.fc-svg { width: 100%; height: auto; display: block; overflow: visible; }
.fc-grid { stroke: var(--hairline); stroke-width: 1; }
.fc-axis { fill: var(--fg-mute); font-family: var(--mono); font-size: 11px; }
.fc-area { fill: color-mix(in srgb, var(--portal) 16%, transparent); stroke: none; }
.fc-line { fill: none; stroke: var(--portal-2); stroke-width: 2.5; stroke-linejoin: round; }
.fc-drop { stroke: var(--c-coral-1); stroke-width: 1.4; stroke-dasharray: 4 4; opacity: .7; }
.fc-drop-l { fill: var(--c-coral-1); font-family: var(--mono); font-size: 10.5px; }
.fc-rto { font-family: var(--mono); font-size: 10.5px; color: var(--c-coral-1); }

/* === Methods ============================================================== */
.m-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 1rem; }
.m-card { padding: 1rem 1.1rem; border-radius: var(--radius-sm); background: var(--mat-1); border: 1px solid var(--hairline); border-left: 3px solid var(--chip); }
.m-head { display: flex; justify-content: space-between; align-items: baseline; gap: .5rem; margin-bottom: .7rem; padding-bottom: .6rem; border-bottom: 1px solid var(--hairline); }
.m-method { font-weight: 800; font-size: 1.05rem; }
.m-totals { font-family: var(--mono); font-size: 11.5px; color: var(--fg-dim); text-align: right; }
.m-row { display: flex; justify-content: space-between; align-items: center; gap: .6rem; padding: .35rem 0; font-size: 13px; }
.m-name { display: flex; align-items: center; gap: .5rem; min-width: 0; }
.m-amt { font-family: var(--mono); font-weight: 600; white-space: nowrap; }

/* === All (list) =========================================================== */
.sub-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: .8rem; }
.sub-card { display: block; padding: .9rem 1rem; border-radius: var(--radius-sm); background: var(--mat-1); border: 1px solid var(--hairline); border-left: 3px solid var(--iv, var(--hairline)); }
.sub-card:hover { border-color: color-mix(in srgb, var(--portal) 40%, transparent); border-left-color: var(--iv, var(--portal)); }
.iv-badge { font-family: var(--mono); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  color: var(--iv); padding: .12em .5em; border-radius: 999px; background: color-mix(in srgb, var(--iv) 14%, var(--bg-soft)); border: 1px solid color-mix(in srgb, var(--iv) 28%, transparent); }
.sub-sched { font-family: var(--mono); font-size: 10.5px; color: var(--c-amber-2); margin-top: .45rem; }
.sub-top { display: flex; justify-content: space-between; align-items: baseline; gap: .6rem; }
.sub-name { font-weight: 700; font-size: 14.5px; }
.sub-amt { font-family: var(--mono); font-weight: 700; white-space: nowrap; }
.sub-meta { display: flex; flex-wrap: wrap; align-items: center; gap: .45rem; margin-top: .5rem; }
.sub-tag { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--c-coral-1); border: 1px solid color-mix(in srgb, var(--c-coral-1) 30%, transparent); border-radius: 999px; padding: .1em .5em; }
.sub-next { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); margin-left: auto; }
/* Rent-to-own: bar fills toward the right as payoff nears; figures on the right. */
.rto-flow { display: flex; align-items: center; gap: .7rem; margin-top: .7rem; }
.rto-bar { flex: 1; height: 7px; border-radius: 999px; background: var(--bg-soft); overflow: hidden; }
.rto-bar span { display: block; height: 100%; background: linear-gradient(90deg, color-mix(in srgb, var(--c-mint-1) 55%, var(--c-amber-1)), var(--c-mint-1)); border-radius: 999px; }
/* Rent-to-own is red: completing one moves it out of subscriptions and into
   "owned" in Inventory — a distinct outcome from an ordinary subscription. */
.rto-bar.rto span { background: linear-gradient(90deg, color-mix(in srgb, var(--c-coral-2) 70%, #7a1d1d), var(--c-coral-2)); }
.sub-card.is-rto .iv-badge { color: var(--c-coral-2); background: color-mix(in srgb, var(--c-coral-2) 14%, var(--bg-soft)); border-color: color-mix(in srgb, var(--c-coral-2) 30%, transparent); }
.rto-side { display: flex; flex-direction: column; align-items: flex-end; line-height: 1.2; white-space: nowrap; }
.rto-side b { font-family: var(--mono); font-size: 11.5px; color: var(--fg); }
.rto-side span { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }
.sub-card.needs { border-style: dashed; }
.sub-card.needs .sub-meta { font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); }
.sub-flag { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--c-amber-2); }
.sub-needs-head { grid-column: 1 / -1; font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: .07em; color: var(--fg-mute); margin-top: .6rem; }

/* Inventory billing line on recurring items */
.crud-card-body .meta.billing { color: var(--portal-2); opacity: .9; }

/* === Hub modules ========================================================== */
.panel-focal { border-color: color-mix(in srgb, var(--c-coral-1) 22%, var(--hairline)); }
.focal-stat { display: flex; flex-direction: column; padding: .2rem 0 .9rem; margin-bottom: .4rem; border-bottom: 1px solid var(--hairline); }
.focal-v { font-size: 2.4rem; font-weight: 900; letter-spacing: -.03em; line-height: 1; color: var(--c-coral-1); }
.focal-k { font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); margin-top: .35rem; }
.panel-focal .up-row { text-decoration: none; }
.panel-focal .up-name { color: var(--fg); }

.launch-row { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; }
.launch-card { display: flex; align-items: center; gap: .6rem; padding: .7rem .8rem; border-radius: var(--radius-xs);
  background: var(--bg-soft); border: 1px solid var(--hairline); }
.launch-card:hover { border-color: color-mix(in srgb, var(--tint) 45%, transparent); }
.launch-glyph { width: 30px; height: 30px; flex: none; display: grid; place-items: center; border-radius: 9px; font-size: 15px;
  color: var(--tint); background: color-mix(in srgb, var(--tint) 14%, transparent); }
.launch-txt { display: flex; flex-direction: column; min-width: 0; }
.launch-name { font-weight: 700; font-size: 13.5px; }
.launch-desc { font-size: 11.5px; color: var(--fg-mute); }
@media (max-width: 520px) { .launch-row { grid-template-columns: 1fr; } }
/* Same fix as .lens-row above — key it to the tile's own width. */
@container (max-width: 20rem) { .launch-row { grid-template-columns: 1fr; } }

.cov-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: .6rem; }
.cov-stat { padding: .7rem .5rem; text-align: center; border-radius: var(--radius-xs); background: var(--bg-soft);
  border: 1px solid var(--hairline); border-top: 2px solid var(--tint); }
.cov-v { display: block; font-size: 1.5rem; font-weight: 900; letter-spacing: -.02em; color: var(--tint); line-height: 1; }
.cov-k { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-mute); }
.block-action { display: block; margin-top: .8rem; text-align: center; font-family: var(--mono); font-size: 12px; font-weight: 600;
  color: var(--portal-2); padding: .55rem; border-radius: var(--radius-xs); border: 1px dashed var(--hairline); }
.block-action:hover { background: var(--bg-soft); border-color: color-mix(in srgb, var(--portal) 40%, transparent); }

.lens-grid { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; }
.lens-cell { display: flex; align-items: center; gap: .55rem; padding: .65rem .75rem; border-radius: var(--radius-xs);
  background: var(--bg-soft); border: 1px solid var(--hairline); }
.lens-cell:hover { border-color: color-mix(in srgb, var(--tint) 45%, transparent); }
.lens-glyph { width: 26px; height: 26px; flex: none; display: grid; place-items: center; border-radius: 8px; font-size: 13px;
  color: var(--tint); background: color-mix(in srgb, var(--tint) 14%, transparent); }
.lens-name { font-size: 13px; font-weight: 600; flex: 1; min-width: 0; }
.lens-n { font-family: var(--mono); font-weight: 700; color: var(--fg-dim); }

/* Month navigator — Today sits centered (out of the ›-arrow path). */
.mnav { display: flex; align-items: center; gap: .6rem; margin: .3rem 0 .8rem; }
.mnav-arrow { flex: none; width: 38px; height: 38px; font-size: 18px; cursor: pointer;
  background: var(--mat-1); border: 1px solid var(--hairline); border-radius: 11px; color: var(--fg-dim); }
.mnav-arrow:hover { color: var(--fg); border-color: color-mix(in srgb, var(--portal) 40%, transparent); }
.mnav-mid { flex: 1; display: flex; flex-direction: column; align-items: center; gap: .15rem; }
.mnav-title { font-weight: 800; font-size: 1.15rem; letter-spacing: -.02em; }
.mnav-total { font-family: var(--mono); font-size: 11.5px; color: var(--portal-2); }
.mnav-today { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); background: none; border: none; cursor: pointer; margin-top: .1rem; }
.mnav-today:hover { color: var(--portal-2); }

/* Coming-up: a single defined card, tight columns, a sum footer row. */
.ov-card { border: 1px solid var(--hairline); border-radius: var(--radius-sm); background: var(--mat-1); overflow: hidden; }
.ml-row { display: grid; grid-template-columns: 6rem 1fr auto; align-items: center; gap: 1rem; padding: .6rem 1.1rem; border-top: 1px solid var(--hairline); }
.ml-row:first-child { border-top: none; }
.ml-date { display: flex; flex-direction: column; line-height: 1.2; }
.ml-date b { font-size: 14px; font-weight: 700; }
.ml-rel { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }
.ml-name { display: flex; align-items: center; gap: .5rem; min-width: 0; font-size: 14px; }
.ml-amt { font-family: var(--mono); font-weight: 700; font-size: 14px; }
.ml-row.soon .ml-amt, .ml-row.soon .ml-date b { color: var(--c-coral-1); }
.ml-row.past { opacity: .5; }
.ml-sum { display: grid; grid-template-columns: 6rem 1fr auto; align-items: baseline; gap: 1rem; padding: .7rem 1.1rem; border-top: 2px solid var(--border-hi, var(--fg-mute)); background: var(--bg-soft); }
.ml-sum-month { grid-column: 1 / 3; font-weight: 700; font-size: 13.5px; }
.ml-sum-total { font-family: var(--mono); font-weight: 800; font-size: 15px; color: var(--portal-2); }
@media (max-width: 560px) { .ml-row, .ml-sum { grid-template-columns: 4.5rem 1fr auto; gap: .5rem; padding-left: .7rem; padding-right: .7rem; } }

/* Payment Routing — money flow: subscriptions → router → card */
.r-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 1rem; }
.r-card { padding: 1rem 1.1rem; border-radius: var(--radius-sm); background: var(--mat-1); border: 1px solid var(--hairline); border-top: 3px solid var(--chip); }
.r-card-head { display: flex; justify-content: space-between; align-items: baseline; gap: .5rem; flex-wrap: wrap; margin-bottom: .8rem; padding-bottom: .6rem; border-bottom: 1px solid var(--hairline); }
.r-card-name { font-weight: 800; font-size: 1.1rem; display: flex; align-items: center; gap: .45rem; }
.r-card-name::before { content: ""; width: 10px; height: 10px; border-radius: 3px; background: var(--chip); }
.r-card-totals { font-family: var(--mono); font-size: 11px; color: var(--fg-dim); text-align: right; }
.r-routers { display: flex; flex-direction: column; gap: .7rem; }
.r-router { border-left: 2px solid var(--rc); padding-left: .7rem; }
.r-router-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: .25rem; }
.r-flow { font-family: var(--mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; color: var(--rc); }
.r-router-n { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }
.r-sub { display: flex; justify-content: space-between; align-items: center; gap: .6rem; padding: .3rem 0; font-size: 13px; }
.r-sub-name { display: flex; align-items: center; gap: .5rem; min-width: 0; }
.r-sub-amt { font-family: var(--mono); font-weight: 600; white-space: nowrap; }

/* Forecast filters — per-item checkboxes grouped by toggleable category */
.fc-hint { font-family: var(--mono); font-size: 10px; font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--fg-mute); margin-left: .5rem; }
.fc-cat { margin: .7rem 0; }
.fc-cat-h { display: inline-flex; align-items: center; gap: .45rem; background: none; border: none; cursor: pointer; padding: 0 0 .35rem; }
.fc-cat-box { font-size: 13px; color: var(--portal-2); }
.fc-cat-h.off .fc-cat-box { color: var(--fg-mute); }
.fc-item { display: grid; grid-template-columns: 18px minmax(120px, 14rem) 1fr auto; align-items: center; gap: .7rem; padding: .3rem 0 .3rem .4rem; cursor: pointer; }
.fc-item input { accent-color: var(--portal); width: 15px; height: 15px; }
.fc-name { font-size: 13px; color: var(--fg); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fc-amt { font-family: var(--mono); font-size: 12px; color: var(--fg-dim); white-space: nowrap; }
.fc-item.off { opacity: .42; }
.fc-item.off .bar-fill { filter: grayscale(.7); }

/* Payment Routing — schedule subgroups + the payment-method registry */
.r-sched { margin-top: .55rem; }
.r-sched-h { font-family: var(--mono); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; color: var(--fg-mute); margin-bottom: .15rem; }
.r-sub { display: grid; grid-template-columns: 4.5rem 1fr auto; align-items: center; gap: .6rem; padding: .3rem 0; font-size: 13px; }
.r-sub-when { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); white-space: nowrap; }
.r-kind { font-family: var(--mono); font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; margin-left: .5rem; padding: .1em .45em; border-radius: 999px; }
.r-kind-credit { color: var(--c-violet-1); background: color-mix(in srgb, var(--c-violet-1) 14%, transparent); }
.r-kind-debit { color: var(--c-cyan-1); background: color-mix(in srgb, var(--c-cyan-1) 14%, transparent); }
.r-kind-manual { color: var(--c-amber-2); background: color-mix(in srgb, var(--c-amber-1) 16%, transparent); }
.pm-manage { grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  margin-top: .4rem; padding-top: 1rem; border-top: 1px dashed var(--hairline); }
.pm-list { display: flex; flex-wrap: wrap; gap: .5rem; }
.pm-pill { font-family: var(--mono); font-size: 11.5px; display: inline-flex; align-items: center; gap: .4rem; padding: .25em .6em; border-radius: 999px;
  background: color-mix(in srgb, var(--chip) 12%, var(--bg-soft)); border: 1px solid color-mix(in srgb, var(--chip) 28%, transparent); }
.pm-pill i { color: var(--fg-mute); font-style: normal; font-size: 10px; }
.pm-form { grid-column: 1 / -1; display: flex; gap: .4rem; align-items: center; margin-top: .6rem; flex-wrap: wrap; }
.pm-form input, .pm-form select { background: var(--bg-soft); border: 1px solid var(--hairline); border-radius: 9px; color: var(--fg); font: inherit; font-size: 13px; padding: .35rem .55rem; }
.pm-form input:focus, .pm-form select:focus { outline: none; border-color: var(--portal-2); }

/* All tab — schedule sections */
.sched-sec { margin-top: 1.75rem; }
.sched-sec:first-child { margin-top: 0; }
.sched-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: .8rem; padding-bottom: .45rem; border-bottom: 1px solid var(--hairline); }
.sched-head h4 { margin: 0; font-size: 1.05rem; font-weight: 800; letter-spacing: -.01em; }
.sched-meta { font-family: var(--mono); font-size: 11.5px; color: var(--portal-2); }

@media (max-width: 720px) {
  .sub-overview-grid { grid-template-columns: 1fr; }
  .cal-cell { padding: .3rem; min-height: 88px; }
  .fc-head { flex-direction: column; align-items: flex-start; }
  .fc-total { text-align: left; }
  .fc-item { grid-template-columns: 18px 1fr auto; }
  .fc-item .bar-track { display: none; }
}

/* =============================================================================
   Subscriptions rev 2 — forecast presets + monthly columns, calendar timeframes
============================================================================= */

/* --- forecast horizon presets (replaces the segmented slider) ------------ */
.fc-controls-l { font-family: var(--mono); font-size: 11.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--fg-mute); }
.fc-presets { display: inline-flex; gap: .25rem; padding: .25rem; border-radius: 11px; background: var(--bg-soft); border: 1px solid var(--hairline); }
.fc-preset {
  font-family: var(--mono); font-size: 12px; font-weight: 700; cursor: pointer;
  padding: .35rem .7rem; border-radius: 8px; border: none; background: transparent; color: var(--fg-dim);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.fc-preset:hover { color: var(--fg); }
.fc-preset.on { background: var(--mat-1); color: var(--portal-2); box-shadow: var(--shadow-xs); }

/* --- forecast monthly column chart --------------------------------------- */
.fc-bar { transition: opacity var(--t-fast) var(--ease); }
.fc-bar:hover { opacity: .82; }
.fc-bar-v { fill: var(--fg-dim); font-family: var(--mono); font-size: 11px; font-weight: 700; }
.fc-baseline { stroke: var(--fg-mute); stroke-width: 1.3; stroke-dasharray: 5 4; opacity: .8; }
.fc-baseline-l { fill: var(--fg-mute); font-family: var(--mono); font-size: 10.5px; }

/* --- forecast toggle list: pack categories into columns ------------------ */
.fc-cats { columns: 2; column-gap: 1.75rem; margin-top: .4rem; }
.fc-cat { break-inside: avoid; -webkit-column-break-inside: avoid; }
.fc-cat:first-child { margin-top: 0; }
@media (max-width: 760px) { .fc-cats { columns: 1; } }

/* --- routing: stop the name/chip/amount overlap -------------------------- */
.r-sub-name { min-width: 0; overflow: hidden; }
.r-sub-nm { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.r-sub-name .sub-chip { flex: none; }
.r-sub-amt { flex: none; }

/* --- calendar: own tab, Month / Quarter / Year timeframes ---------------- */
.cal-controls { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.cal-range { display: inline-flex; gap: .2rem; padding: .22rem; border-radius: 11px; background: var(--bg-soft); border: 1px solid var(--hairline); }
.cal-rbtn {
  font-family: var(--mono); font-size: 11.5px; font-weight: 700; cursor: pointer;
  padding: .35rem .65rem; border-radius: 8px; border: none; background: transparent; color: var(--fg-dim);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.cal-rbtn:hover { color: var(--fg); }
.cal-rbtn.on { background: var(--mat-1); color: var(--portal-2); box-shadow: var(--shadow-xs); }

.cal-grid-q { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.cal-grid-y { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; }
.cal-month.compact .cal-m-h {
  display: flex; align-items: baseline; justify-content: space-between; gap: .5rem;
  font-weight: 700; font-size: 13px; margin-bottom: .4rem;
}
.cal-month.compact .cal-m-h span { font-family: var(--mono); font-size: 11px; color: var(--portal-2); }
.cal-month.compact .cal-dow { font-size: 9px; }
.cal-month.compact .cal-dows, .cal-month.compact .cal-cells { gap: 3px; }
/* compact day cells: number + a row of charge dots (visual density over text) */
.cal-cell.mini { min-height: 0; aspect-ratio: 1 / 1; padding: .2rem .25rem; display: flex; flex-direction: column; gap: 2px; }
.cal-cell.mini .cal-num { font-size: 10px; }
.cal-dots { display: flex; flex-wrap: wrap; gap: 2px; align-content: flex-start; }
.cal-dot { width: 5px; height: 5px; border-radius: 999px; }
@media (max-width: 1000px) { .cal-grid-y { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 760px) { .cal-grid-q, .cal-grid-y { grid-template-columns: repeat(2, 1fr); } }

/* =============================================================================
   Dashboard — clickable affordances + in-place modals (stay inside Portal)
============================================================================= */
/* KPI cards are now links/buttons. */
.kpi-link { display: block; width: 100%; text-align: left; cursor: pointer; font: inherit; color: inherit;
  transition: border-color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease), background var(--t-fast) var(--ease); }
.kpi-link:hover { border-color: color-mix(in srgb, var(--portal) 45%, transparent); transform: translateY(-2px); }
/* Strip cells don't float on hover — they glow in place (they share edges). */
.dash-strip .kpi-link:hover { transform: none; background: color-mix(in srgb, var(--fg) 4%, var(--cell-bg)); }

/* Clickable panel headers (the whole header navigates / opens its module). */
[data-open] .panel-head, [data-open-modal] .panel-head { cursor: pointer; }
[data-open] .panel-head h3, [data-open-modal] .panel-head h3 { transition: color var(--t-fast) var(--ease); }
[data-open] .panel-head:hover h3, [data-open-modal] .panel-head:hover h3 { color: var(--portal-2); }
/* The action links can be <button>s now. */
.panel-link[type="button"] { font: inherit; font-family: var(--mono); font-size: 11.5px; background: none; border: none; cursor: pointer; padding: 0; }

/* Modal scaffold — sits above the header chrome (banner 120). */
.dash-modal-backdrop { position: fixed; inset: 0; z-index: 300; display: grid; place-items: center; padding: 4vh 4vw;
  background: rgba(0,0,0,.55); backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px);
  opacity: 0; pointer-events: none; transition: opacity .18s var(--ease); }
.dash-modal-backdrop.open { opacity: 1; pointer-events: auto; }
.dash-modal { width: min(760px, 96vw); max-height: 92vh; overflow: auto; position: relative;
  background: var(--mat-1); border: 1px solid var(--border-hi); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); padding: 1.4rem 1.5rem 1.6rem;
  transform: translateY(10px) scale(.985); transition: transform .2s var(--ease-spring); }
.dash-modal-backdrop.open .dash-modal { transform: none; }
.dash-modal-close { position: absolute; top: .9rem; right: .9rem; width: 34px; height: 34px; border-radius: 999px;
  border: 1px solid var(--hairline); background: var(--bg-soft); color: var(--fg-dim); font-size: 18px; line-height: 1; cursor: pointer; }
.dash-modal-close:hover { color: var(--fg); border-color: var(--border-hi); }
.dash-modal-head { display: flex; align-items: baseline; gap: .7rem; margin-bottom: 1rem; padding-right: 2.5rem; }
.dash-modal-head h3 { margin: 0; font-size: 1.25rem; font-weight: 800; letter-spacing: -.02em; }
.dash-modal-head .dm-sub { font-family: var(--mono); font-size: 12px; color: var(--fg-mute); }
/* The calendar reuses .cal-* ; trim its in-modal top margin. */
.dash-modal .cal-head { margin-top: 0; }

/* TypeShit telemetry (ff- prefix kept as reversible internal plumbing) */
.ff-spark { margin-bottom: 1.1rem; }
.ff-spark-h, .ff-runs-h { font-family: var(--mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: .07em; color: var(--fg-mute); margin-bottom: .4rem; }
.ff-spark-svg { width: 100%; height: 80px; display: block; background: var(--bg-soft); border: 1px solid var(--hairline); border-radius: var(--radius-sm); }
.ff-runs { display: flex; flex-direction: column; gap: .3rem; }
.ff-run { display: grid; grid-template-columns: 1fr auto auto; align-items: center; gap: 1rem;
  padding: .4rem .7rem; border-radius: 10px; background: var(--bg-soft); border: 1px solid var(--hairline); font-family: var(--mono); font-size: 12.5px; }
.ff-run-wpm { font-weight: 700; color: var(--portal-2); }
.ff-run-wpm i { font-style: normal; color: var(--fg-mute); font-size: .8em; margin-left: .25rem; }
.ff-run-acc { color: var(--fg-dim); }
.ff-run-mode { color: var(--fg-mute); text-transform: uppercase; font-size: 10.5px; letter-spacing: .05em; }

/* TypeShit dashboard widget — three lanes (Arcade / Free Type / Trainers),
   mirroring the app's own menu, each reporting from whichever data source
   actually exists for that mode — not one wpm-shaped stat block reused across
   all three (that was the "still looks like Fast Fingers" complaint). */
.ts-lanes { display: flex; flex-direction: column; gap: .3rem; }
.ts-lane {
  display: flex; align-items: center; gap: .65rem; color: inherit;
  padding: .5rem .6rem; border-radius: 10px; border: 1px solid transparent;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.ts-lane:hover { background: color-mix(in srgb, var(--tint, var(--portal)) 8%, transparent); border-color: color-mix(in srgb, var(--tint, var(--portal)) 30%, transparent); }
.ts-lane-no { font-family: var(--mono); font-size: 10.5px; font-weight: 700; color: var(--tint, var(--portal)); width: 18px; flex-shrink: 0; }
.ts-lane-name { flex: 1; font-weight: 600; font-size: 13.5px; min-width: 0; }
.ts-lane-val { font-family: var(--mono); font-size: 12.5px; color: var(--fg); white-space: nowrap; text-align: right; }
.ts-lane-val small { color: var(--fg-mute); font-weight: 500; margin-left: .15rem; }
.ts-lane-empty .ts-lane-val { color: var(--fg-mute); }

/* Telemetry modal — sectioned Free Type / Challenge Points / Arcade / Trainers,
   instead of one flat wpm block (the modal gets the same treatment as the
   compact widget above, for the same reason). */
.ts-modal-section { margin-bottom: 1.35rem; }
.ts-modal-section:last-child { margin-bottom: 0; }
.ts-modal-section-h {
  font-family: var(--mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--fg-mute); margin-bottom: .6rem; padding-bottom: .4rem; border-bottom: 1px solid var(--hairline);
  display: flex; justify-content: space-between; gap: .5rem;
}
.ts-modal-section-h span:last-child { text-transform: none; letter-spacing: 0; opacity: .8; }
.ts-axes { display: grid; grid-template-columns: repeat(2, 1fr); gap: .5rem; }
.ts-axis-card { padding: .6rem .7rem; border-radius: 10px; background: var(--bg-soft); border: 1px solid var(--hairline); }
.ts-axis-name { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-mute); margin-bottom: .3rem; }
.ts-axis-top { display: flex; align-items: baseline; gap: .4rem; }
.ts-axis-key { font-weight: 700; font-size: 14px; color: var(--fg); }
.ts-axis-n { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); }
.ts-arcade-row, .ts-trainers-row {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: .65rem .8rem; border-radius: 10px; background: var(--bg-soft); border: 1px solid var(--hairline);
}
.ts-arcade-v, .ts-trainers-v { font-family: var(--mono); font-weight: 700; font-size: 15px; color: var(--fg); }
.ts-arcade-v small, .ts-trainers-v small { font-weight: 500; color: var(--fg-mute); margin-left: .3rem; font-size: .75em; }
@media (max-width: 560px) { .ts-axes { grid-template-columns: 1fr; } }

/* === Subscriptions: money-flow Sankey (category → router → card) =========== */
.sk-wrap { overflow-x: auto; margin-top: .5rem; padding: .5rem 0 1rem; }
.sk-svg { width: 100%; min-width: 660px; height: auto; display: block; }
.sk-link { opacity: .36; transition: opacity var(--t-fast) var(--ease); }
.sk-link:hover { opacity: .62; }
.sk-node { stroke: var(--bg); stroke-width: .5; }
.sk-label { fill: var(--fg-dim); font-family: var(--sans); font-size: 12px; font-weight: 600; }
.sk-val { fill: var(--fg-mute); font-family: var(--mono); font-size: 10.5px; font-weight: 700; }

/* === Asset Value: a catalog of owned things, valued at MSRP =============== */
/* KPIs — the collection's total value leads; the two class cards carry a left
   accent in their family color so the physical/digital split reads at a glance. */
.av-kpi { position: relative; }
.av-kpi-total .kpi-v { color: var(--portal-2); }
.av-kpi-total { border-color: color-mix(in srgb, var(--portal) 32%, transparent); }
.av-kpi-physical { border-left: 3px solid var(--c-mint-1); }
.av-kpi-digital { border-left: 3px solid var(--c-violet-1); }

/* Composition — a slim proportion strip (physical vs digital share of MSRP),
   then one full-width value bar per class, each labelled with a small key. */
.av-comp-split {
  display: flex; align-items: stretch; gap: 4px;
  height: 24px; border-radius: 8px; overflow: hidden; margin: .2rem 0 .6rem;
}
.av-split-seg {
  min-width: 0; display: flex; align-items: center; padding: 0 .8rem;
  font-family: var(--mono); font-size: 11.5px; font-weight: 700;
  white-space: nowrap; overflow: hidden;
}
.av-split-seg span { overflow: hidden; text-overflow: ellipsis; }
.av-split-seg.physical { justify-content: flex-start; background: color-mix(in srgb, var(--c-mint-1) 26%, var(--bg)); color: var(--c-mint-1); }
.av-split-seg.digital { justify-content: flex-end; background: color-mix(in srgb, var(--c-violet-1) 26%, var(--bg)); color: var(--c-violet-1); }
.av-classbars { display: flex; flex-direction: column; gap: .5rem; }
.av-classbar-k {
  display: flex; align-items: baseline; justify-content: space-between;
  font-family: var(--mono); font-size: 10.5px; font-weight: 700;
  color: var(--fg-dim); margin-bottom: .18rem;
}
.av-classbar-k span:last-child { color: var(--portal-2); }
.av-comp-bar {
  display: flex; align-items: stretch; gap: 3px;
  height: 42px; border-radius: 10px; overflow: hidden;
}
.av-seg {
  flex: 1 1 0; min-width: 0; overflow: hidden; border-radius: 6px;
  padding: .25rem .5rem; display: flex; align-items: center;
  border: 1px solid color-mix(in srgb, var(--fg) 7%, transparent);
  transition: filter var(--t-fast) var(--ease);
}
.av-seg:hover { filter: brightness(1.1); }
.av-seg.is-more { border-style: dashed; }
.av-seg-l { min-width: 0; display: flex; align-items: baseline; gap: .35rem; line-height: 1.15; }
.av-seg-n {
  font-weight: 800; font-size: 11px; color: #0a0c10;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.av-seg-v { font-family: var(--mono); font-size: 10px; font-weight: 700; color: color-mix(in srgb, #0a0c10 72%, transparent); flex: none; }
.av-seg-l.more .av-seg-n,
.av-seg-l.more .av-seg-v { color: var(--fg-dim); }

/* Catalog — one unified ledger. A toolbar (class filter + sort), then the rows;
   each is a plate: glyph · name + product-id · MSRP meter · MSRP stamp. */
.av-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: .75rem; flex-wrap: wrap; margin: .25rem 0 .9rem;
}
.av-chips, .av-sort { display: flex; align-items: center; gap: .4rem; }
.av-chip {
  display: inline-flex; align-items: center; gap: .4rem;
  font: 600 12.5px/1 var(--sans); color: var(--fg-dim);
  padding: .42rem .7rem; border-radius: 999px; cursor: pointer;
  background: var(--bg-soft); border: 1px solid var(--hairline);
  transition: border-color var(--t-fast) var(--ease), color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.av-chip:hover { border-color: var(--border-hi); color: var(--fg); }
.av-chip.on { color: var(--fg); border-color: color-mix(in srgb, var(--tone-mint) 55%, transparent); background: color-mix(in srgb, var(--tone-mint) 12%, var(--panel)); }
.av-chip-n { font-family: var(--mono); font-size: 10.5px; font-weight: 700; color: var(--fg-mute); }
.av-chip.on .av-chip-n { color: var(--portal-2); }
.av-sort-k { font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--fg-mute); }
.av-sortbtn {
  font: 600 12px/1 var(--sans); color: var(--fg-dim); cursor: pointer;
  padding: .38rem .6rem; border-radius: 8px; background: transparent; border: 1px solid transparent;
  transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.av-sortbtn:hover { color: var(--fg); }
.av-sortbtn.on { color: var(--fg); background: var(--bg-soft); border-color: var(--hairline); }

/* Dense ledger: two columns of tight, hairline-divided single-line rows — no
   per-row cards. Packs ~2× the holdings per screen. columns fill top→bottom,
   so col 1 is the top of the ranking, col 2 continues it. */
.av-items { columns: 2; column-gap: 1.75rem; }
.av-item {
  display: grid; grid-template-columns: 14px minmax(0, 1fr) 54px 56px;
  align-items: center; column-gap: .55rem;
  padding: .24rem .15rem; break-inside: avoid;
  border-bottom: 1px solid var(--hairline);
  transition: background var(--t-fast) var(--ease);
}
.av-item:hover { background: var(--bg-soft); }
.av-item-glyph { font-size: 10.5px; text-align: center; line-height: 1; }
.av-item-physical .av-item-glyph { color: var(--c-mint-2); }
.av-item-digital .av-item-glyph { color: var(--c-violet-2); }
:root[data-theme="dark"] .av-item-physical .av-item-glyph { color: var(--c-mint-1); }
:root[data-theme="dark"] .av-item-digital .av-item-glyph { color: var(--c-violet-1); }
.av-item-main { min-width: 0; display: flex; align-items: baseline; gap: .4rem; overflow: hidden; }
.av-item-n { font-weight: 600; font-size: 12.5px; color: var(--fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 0 1 auto; }
.av-ident { display: flex; align-items: baseline; gap: .3rem; min-width: 0; flex: 1 1 auto; overflow: hidden; }
.av-maker { font-size: 10.5px; color: var(--fg-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 0 1 auto; }
.av-dot { color: var(--fg-mute); opacity: .5; }
/* The product id, in mono — the "base point," compact. */
.av-sku { display: inline-flex; align-items: baseline; gap: .25rem; flex: 0 1 auto; min-width: 0;
  font-family: var(--mono); font-size: 9.5px; font-weight: 500; color: var(--fg-mute); }
.av-sku-k { font-size: 8px; font-weight: 700; letter-spacing: .06em; color: var(--fg-dim); opacity: .8; }
.av-sku { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.av-meter { width: 54px; height: 4px; }
.av-item.is-free .bar-fill { opacity: 0; }
.av-item-v { font-family: var(--mono); font-weight: 700; font-size: 11.5px; color: var(--portal-2); text-align: right; }
.av-free { color: var(--fg-mute); font-weight: 600; font-size: 11px; }
.av-catalog-foot {
  display: flex; align-items: baseline; justify-content: space-between;
  margin-top: .5rem; padding-top: .45rem; border-top: 1px solid var(--border-hi);
  font-family: var(--mono); font-size: 11px; font-weight: 700;
}
.av-catalog-foot span:first-child { color: var(--fg-mute); }
.av-catalog-foot span:last-child { color: var(--portal-2); }

@media (prefers-reduced-motion: reduce) {
  .av-seg, .av-item { transition: none; }
  .av-seg:hover { transform: none; }
}
@media (max-width: 720px) {
  .av-comp-bar { height: 46px; }
  .av-items { columns: 1; }
  .av-item { grid-template-columns: 14px minmax(0, 1fr) 54px 56px; }
}
.sk-head { fill: var(--fg-mute); font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: .12em; }

/* =============================================================================
   Calendar module (portal-calendar.*)  —  PORTAL-REDESIGN-BRIEF §4.3
   Builds on the existing .cal-* vocabulary; these are the additions the
   standalone aggregator needs (legend, agenda, .ics subscribe cards, form).
============================================================================= */
.cal-legend { display: flex; flex-wrap: wrap; gap: .9rem; margin: .25rem 0 1rem; }
.cal-legend-chip { display: inline-flex; align-items: center; gap: .4rem; font-family: var(--mono); font-size: 11.5px; color: var(--fg-dim); }
.cal-legend-note { font-size: 9.5px; color: var(--fg-mute); text-transform: uppercase; letter-spacing: .06em; }
.cal-cell.out { opacity: .42; }
.cal-cell.out .cal-num { color: var(--fg-mute); }
.cal-charge-tag { font-family: var(--mono); font-size: 9.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-mute); border: 1px solid var(--hairline); border-radius: 6px; padding: .1rem .35rem; }
.cal-agenda { margin-top: .5rem; }
.cal-agenda-day { padding: .55rem .1rem .25rem; border-top: 1px solid var(--hairline); margin-top: .4rem; }
.cal-agenda-day:first-child { border-top: none; margin-top: 0; }
.cal-agenda-date { font-family: var(--mono); font-size: 12px; font-weight: 700; color: var(--portal-2); }
.cal-onenote { font-size: 13px; color: var(--fg-mute); max-width: 60ch; margin: .25rem 0 1.25rem; line-height: 1.5; }
.cal-feeds { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 1rem; }
.cal-feed-card { border: 1px solid var(--hairline); border-radius: 12px; padding: 1rem; background: var(--bg-soft); }
.cal-feed-head { display: inline-flex; align-items: center; gap: .5rem; margin-bottom: .8rem; font-size: 14px; }
.cal-feed-actions { display: flex; gap: .5rem; flex-wrap: wrap; }
.cal-form { margin: 1rem 0 1.25rem; padding: 1.1rem; border: 1px solid var(--hairline); border-radius: 12px; background: var(--bg-soft); }
.btn-sm { padding: .4rem .7rem; font-size: 12px; }
.btn-ghost { background: transparent; border: 1px solid transparent; color: var(--fg-dim); }
.btn-ghost:hover { color: var(--fg); border-color: var(--hairline); }
.btn.danger, .btn-ghost.danger { color: var(--c-coral-1, #ff6b6b); }

/* Expenses · One-offs ledger cards (portal-expenses.js One-offs panel) */
.exp-card-top { display: flex; align-items: baseline; justify-content: space-between; gap: .6rem; }
.exp-name { font-weight: 700; font-size: 15px; }
.exp-amt { font-family: var(--mono); font-weight: 700; color: var(--fg); }
.exp-meta { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; margin-top: .4rem; font-size: 12px; color: var(--fg-dim); }
.exp-kind { font-family: var(--mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: .05em; border: 1px solid var(--hairline); border-radius: 6px; padding: .1rem .4rem; color: var(--fg-mute); }
.exp-kind.rec { color: var(--portal-2); border-color: color-mix(in srgb, var(--portal) 40%, transparent); }
.exp-date { font-family: var(--mono); color: var(--fg-mute); }
.exp-bits { color: var(--fg-mute); }

/* =============================================================================
   Shopping module (portal-shopping.*)  —  PORTAL-REDESIGN-BRIEF §4.4
============================================================================= */
.shop-addbar { display: flex; gap: .6rem; margin-top: 1.25rem; }
.shop-addbar input { flex: 1; min-width: 0; padding: .6rem .8rem; border: 1px solid var(--hairline); border-radius: 10px; background: var(--bg-soft); color: var(--fg); font-size: 14px; }
.shop-addbar-inline { margin: .5rem 0 1rem; }
.shop-cat-in { max-width: 160px; flex: 0 1 160px !important; }
.shop-row { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: .6rem .2rem; border-top: 1px solid var(--hairline); flex-wrap: wrap; }
.shop-row:first-of-type { border-top: none; }
.shop-row-main { display: flex; align-items: center; gap: .55rem; flex-wrap: wrap; min-width: 0; }
.shop-row-actions { display: flex; gap: .4rem; align-items: center; }
.shop-name, .shop-name-btn { font-weight: 600; font-size: 15px; color: var(--fg); }
.shop-name-btn { background: none; border: none; cursor: pointer; padding: 0; text-align: left; }
.shop-name-btn:hover { color: var(--portal-2); text-decoration: underline; }
.shop-qty { font-family: var(--mono); font-size: 12px; color: var(--fg-dim); }
.shop-cat, .shop-date { font-family: var(--mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: .04em; color: var(--fg-mute); border: 1px solid var(--hairline); border-radius: 6px; padding: .08rem .35rem; }
.shop-onlist { font-family: var(--mono); font-size: 10px; color: var(--portal-2); border: 1px solid color-mix(in srgb, var(--portal) 40%, transparent); border-radius: 6px; padding: .08rem .35rem; }
.shop-avail { display: inline-flex; gap: .3rem; flex-wrap: wrap; }
.shop-avail-count { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); }
.shop-avail-count.has-neg { color: var(--c-coral-1, #ff6b6b); }
.shop-chip { display: inline-flex; align-items: center; gap: .25rem; font-size: 10.5px; border: 1px solid var(--hairline); border-radius: 7px; padding: .08rem .4rem; color: var(--fg-dim); }
.shop-chip.inferred { opacity: .72; border-style: dashed; }
.shop-chip.grain-negative { color: var(--c-coral-1, #ff6b6b); border-color: color-mix(in srgb, var(--c-coral-1, #ff6b6b) 40%, transparent); }
.shop-chip-g { font-size: 11px; }
.shop-strength { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); margin-left: auto; }
/* detail drawer */
.shop-drawer-backdrop { position: fixed; inset: 0; background: rgba(0,0,0,.45); z-index: 60; }
.shop-drawer { position: fixed; top: 0; right: 0; height: 100dvh; width: min(440px, 92vw); background: var(--bg); border-left: 1px solid var(--hairline); box-shadow: -12px 0 40px rgba(0,0,0,.3); z-index: 61; padding: 1.4rem; overflow-y: auto; }
.shop-drawer-head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.shop-drawer-head h3 { margin: 0; font-size: 1.3rem; }
.shop-drawer-close { background: none; border: none; font-size: 1.6rem; line-height: 1; color: var(--fg-mute); cursor: pointer; }
.shop-drawer-meta { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; margin: .5rem 0 1rem; }
.shop-amz { font-size: 12px; color: var(--portal-2); }
.shop-drawer-sub { font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: var(--portal-2); margin: 1.2rem 0 .5rem; }
.shop-avail-list { display: flex; flex-direction: column; gap: .35rem; }
.shop-avail-row { display: flex; align-items: center; gap: .5rem; }
.shop-assert-form, .shop-purchase-form { display: flex; gap: .4rem; align-items: center; margin-top: .7rem; flex-wrap: wrap; }
.shop-assert-form select, .shop-assert-form input, .shop-purchase-form select, .shop-purchase-form input { padding: .35rem .5rem; border: 1px solid var(--hairline); border-radius: 8px; background: var(--bg-soft); color: var(--fg); font-size: 12.5px; }
.shop-assert-slot { display: inline-flex; }
.shop-route-controls { display: flex; gap: .6rem; margin: .5rem 0 1rem; flex-wrap: wrap; }
.shop-route-sel { padding: .5rem .7rem; border: 1px solid var(--hairline); border-radius: 10px; background: var(--bg-soft); color: var(--fg); }
.shop-route-head { font-family: var(--mono); font-size: 12px; color: var(--portal-2); margin-bottom: .5rem; }
.shop-route-list { padding-left: 1.4rem; display: flex; flex-direction: column; gap: .35rem; }
.shop-route-items { color: var(--fg-mute); font-size: 12.5px; }
.shop-route-unmatched { margin-top: .8rem; font-size: 12.5px; color: var(--c-coral-1, #ff6b6b); }

/* =============================================================================
   SLU module (portal-school.*)  —  PORTAL-REDESIGN-BRIEF §4.5
   Audit tree + planner. The Record tab reuses the existing .kpi/.panel/.gpa-*/
   .acad-*/.calc-* vocabulary.
============================================================================= */
.slu-headline { display: flex; align-items: baseline; gap: .6rem; margin: 1.25rem 0 1rem; }
.slu-open-n { font-size: 2rem; font-weight: 800; color: var(--portal-2); font-family: var(--mono); }
.slu-open-l { color: var(--fg-dim); }
.slu-block { border: 1px solid var(--hairline); border-radius: 14px; padding: 1.1rem 1.2rem; margin-bottom: 1rem; background: var(--bg-soft); }
.slu-block-head { display: flex; align-items: center; gap: .7rem; }
.slu-block-head h3 { margin: 0; font-size: 1.1rem; }
.slu-status { margin-left: auto; font-family: var(--mono); font-size: 10.5px; font-weight: 700; letter-spacing: .05em; padding: .12rem .5rem; border-radius: 7px; }
.slu-status.incomplete { color: var(--c-amber-1, #e0a64a); border: 1px solid color-mix(in srgb, var(--c-amber-1, #e0a64a) 45%, transparent); }
.slu-status.ok { color: var(--c-mint-1, #4ad6a0); border: 1px solid color-mix(in srgb, var(--c-mint-1, #4ad6a0) 45%, transparent); }
.slu-status.info { color: var(--fg-mute); border: 1px solid var(--hairline); }
.slu-meter { height: 8px; border-radius: 99px; background: var(--mat-1, rgba(127,127,127,.15)); overflow: hidden; margin: .8rem 0 .4rem; }
.slu-meter span { display: block; height: 100%; background: var(--tone, var(--portal)); border-radius: 99px; }
.slu-meter span.over { background: var(--c-amber-1, #e0a64a); }
.slu-meter-lbl { display: flex; gap: .8rem; font-family: var(--mono); font-size: 11.5px; color: var(--fg-dim); }
.slu-gpa { color: var(--fg-mute); }
.slu-truth { margin-top: .6rem; font-size: 12.5px; color: var(--c-amber-1, #e0a64a); background: color-mix(in srgb, var(--c-amber-1, #e0a64a) 9%, transparent); border-radius: 8px; padding: .45rem .65rem; }
.slu-note { margin-top: .5rem; font-size: 12.5px; color: var(--fg-mute); }
.slu-slots { margin-top: .9rem; display: flex; flex-direction: column; gap: .1rem; }
.slu-slot { display: flex; align-items: center; gap: .6rem; padding: .45rem .2rem; border-top: 1px solid var(--hairline); }
.slu-slot:first-child { border-top: none; }
.slu-slot-ic { font-size: 14px; width: 1.1rem; text-align: center; flex: none; }
.slu-slot.still_needed .slu-slot-ic { color: var(--c-amber-1, #e0a64a); }
.slu-slot.in_progress .slu-slot-ic { color: var(--c-cyan-1, #4ab8d6); }
.slu-slot.satisfied .slu-slot-ic { color: var(--c-mint-1, #4ad6a0); }
.slu-slot.satisfied { opacity: .68; }
.slu-slot-txt { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.slu-slot-label { font-weight: 600; font-size: 13.5px; }
.slu-slot-rule { font-size: 12px; color: var(--fg-dim); }
.slu-slot.still_needed .slu-slot-rule { color: var(--c-amber-2, var(--fg-dim)); }
.slu-slot-cr { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); flex: none; }
.slu-buckets { margin-top: .6rem; display: flex; flex-direction: column; gap: .3rem; }
.slu-bucket { display: flex; gap: .6rem; align-items: center; font-size: 12.5px; color: var(--fg-dim); }
.slu-bucket-tag { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-mute); border: 1px solid var(--hairline); border-radius: 6px; padding: .06rem .35rem; }
/* planner */
.slu-axis-h { font-family: var(--mono); font-size: 11.5px; text-transform: uppercase; letter-spacing: .08em; color: var(--tone, var(--portal-2)); margin: 1.5rem 0 .3rem; }
.slu-axis-sub { color: var(--fg-mute); font-size: 13px; margin: 0 0 .7rem; }
.slu-fit-form { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }
.slu-fit-form input { padding: .5rem .7rem; border: 1px solid var(--hairline); border-radius: 9px; background: var(--bg-soft); color: var(--fg); font-size: 13px; }
.slu-fit-attr { flex: 1; min-width: 180px; }
.slu-fit-result { margin-top: .8rem; display: flex; flex-direction: column; gap: .4rem; }
.slu-fit-hit { display: flex; align-items: center; gap: .5rem; }
.slu-fit-check { color: var(--c-mint-1, #4ad6a0); font-weight: 800; }
.slu-fit-block { color: var(--fg-mute); font-size: 12px; }
.slu-fit-none { color: var(--fg-mute); font-size: 13px; }
.slu-targets { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: .7rem; margin-top: .3rem; }
.slu-target { border: 1px solid var(--hairline); border-radius: 10px; padding: .7rem .8rem; display: flex; flex-direction: column; gap: .2rem; }
.slu-target-label { font-weight: 600; font-size: 13px; }
.slu-target-rule { font-size: 11.5px; color: var(--c-amber-1, #e0a64a); }
.slu-target-block { font-size: 10.5px; color: var(--fg-mute); font-family: var(--mono); }
.slu-sentinel { margin-top: .7rem; font-size: 12.5px; color: var(--fg-mute); background: var(--mat-1, rgba(127,127,127,.08)); border: 1px dashed var(--hairline); border-radius: 9px; padding: .6rem .8rem; line-height: 1.5; }
.slu-sections { display: flex; flex-direction: column; gap: .3rem; margin: .5rem 0; }
.slu-section { display: flex; align-items: center; gap: .5rem; font-size: 13px; }
.slu-sched-out { margin-top: .6rem; display: flex; flex-direction: column; gap: .35rem; }
.slu-sched-ok { color: var(--c-mint-1, #4ad6a0); font-size: 13px; }
.slu-sched-bad { color: var(--c-coral-1, #ff6b6b); font-size: 13px; }

/* Single-view layout — Record leads full width; Audit + Planner two columns so
   the workspace stays tight instead of spread down the page. */
.slu-work { display: grid; grid-template-columns: 1.45fr 1fr; gap: 1.9rem; align-items: start; margin-top: 2.75rem; }
.slu-col { min-width: 0; }
.slu-col > .portal-block-head { margin-bottom: 1rem; }
.slu-col #slu-planner .slu-axis-h:first-child { margin-top: .2rem; }
.slu-col #slu-audit .slu-block:last-child { margin-bottom: 0; }
@media (max-width: 900px) { .slu-work { grid-template-columns: 1fr; gap: 1.25rem; } }

/* =============================================================================
   Software module (portal-software.*)  —  PORTAL-REDESIGN-BRIEF §4.7
============================================================================= */
/* --- Workspace header (reusable .ws-* shell) ---------------------------- */
/* Gives a workspace a Dashboard-grade masthead: a big tinted glyph + title,
   then a live stat strip pushed to the right. --tone drives the accent. */
/* --- The bench: one workbench, one viewport ----------------------------- */
/* Two admin-guarded sections (#portal-software, #portal-runner) reveal as
   display:contents, flattening their children into ONE grid so the Build Queue
   canvas and the Runner rail sit side by side under a shared masthead — no more
   stacked full-page sections. --portal-chrome-h is the live nav+subnav height. */
main.shop-bench {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(286px, 340px);
  grid-template-rows: auto auto minmax(0, 1fr) auto;
  grid-template-areas:
    "head    head"
    "gate    gate"
    "canvas  rail"
    "journal rail";
  column-gap: .8rem;
  min-height: calc(100dvh - var(--portal-chrome-h, 120px) - 1rem);
}
#portal-software:not([hidden]),
#portal-runner:not([hidden]) { display: contents; }
.shop-bench .ws-head       { grid-area: head; }
.shop-bench .sw-runner-gate { grid-area: gate; }
.shop-bench .sw-queue-hero { grid-area: canvas; min-height: 0; display: flex; flex-direction: column; }
.shop-bench .rn-rail       { grid-area: rail; min-height: 0; }
.shop-bench .sw-journal    { grid-area: journal; }

.ws-head {
  display: flex; align-items: center; gap: .8rem; flex-wrap: wrap;
  margin: .5rem 0 .7rem;
}
.ws-actions { display: flex; gap: .5rem; }
.ws-actions .btn { flex-shrink: 0; }
.ws-glyph {
  width: 38px; height: 38px; flex-shrink: 0; display: grid; place-items: center; font-size: 19px;
  border-radius: 11px; color: var(--tone, var(--portal));
  background: color-mix(in srgb, var(--tone, var(--portal)) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--tone, var(--portal)) 28%, transparent);
}
.ws-title { display: flex; flex-direction: column; gap: .1rem; }
.ws-title h2 { margin: 0; font-size: 1.4rem; font-weight: 900; letter-spacing: -.03em; line-height: 1; }
.ws-kicker { font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); }
.ws-strip { margin-left: auto; display: flex; gap: .55rem; flex-wrap: wrap; }
.ws-stat {
  display: flex; flex-direction: column; align-items: flex-start; gap: .1rem; cursor: pointer;
  min-width: 5.2rem; padding: .5rem .8rem; border-radius: var(--radius-xs);
  background: var(--mat-1); border: 1px solid var(--hairline);
  border-left: 3px solid var(--ws-c, var(--tone, var(--portal)));
  transition: border-color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.ws-stat:hover { background: color-mix(in srgb, var(--ws-c, var(--tone)) 7%, var(--mat-1)); }
.ws-stat-n { font-size: 1.35rem; font-weight: 900; letter-spacing: -.02em; line-height: 1; color: var(--ws-c, var(--tone, var(--portal-2))); }
.ws-stat-k { font-family: var(--mono); font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; color: var(--fg-mute); }
.ws-stat-pending  { --ws-c: var(--c-amber-1); }
.ws-stat-building { --ws-c: var(--portal-2); }
.ws-stat-shipped  { --ws-c: var(--c-mint-1); }

/* --- Build Runner approval gate (MM #225) ------------------------------- */
/* Only shows when a request is pending. Amber = "this spends money, needs YOU". */
.sw-runner-gate {
  margin: 0 0 .8rem;
  padding: 1rem 1.1rem 1.15rem;
  border: 1px solid color-mix(in srgb, var(--c-amber-1) 45%, transparent);
  border-radius: 14px;
  background: color-mix(in srgb, var(--c-amber-1) 7%, var(--mat-1));
}
.sw-runner-gate .portal-block-head { margin-bottom: .9rem; }
.sw-runner-gate .pbh-glyph { color: var(--c-amber-1); }
.sw-rq-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: .8rem; }
.sw-rq-card {
  display: flex; flex-direction: column; gap: .5rem;
  padding: .85rem .9rem;
  border: 1px solid color-mix(in srgb, var(--c-amber-1) 30%, var(--line, transparent));
  border-radius: 11px;
  background: var(--mat-2, var(--mat-1));
}
.sw-rq-head { display: flex; align-items: center; gap: .5rem; }
.sw-rq-badge {
  font-family: var(--mono); font-size: 9.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em;
  color: var(--c-amber-1);
  padding: .12rem .45rem; border-radius: 999px;
  background: color-mix(in srgb, var(--c-amber-1) 16%, transparent);
}
.sw-rq-src { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); margin-left: auto; }
.sw-rq-title { font-weight: 800; font-size: 1rem; letter-spacing: -.01em; }
.sw-rq-meta { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); }
.sw-rq-preview { font-size: .85rem; color: var(--fg-soft, var(--fg-mute)); margin: 0; }
.sw-rq-cost { font-size: .78rem; line-height: 1.35; color: var(--fg-mute); margin: .1rem 0 .2rem; }
.sw-rq-actions { display: flex; gap: .5rem; flex-wrap: wrap; }

/* --- Build Queue hero + demoted Site History journal -------------------- */
/* The hero is the canvas cell: the inline form (auto) stacks over the board,
   which flexes to fill the rest of the viewport height. */
#sw-queue { flex: 1 1 auto; min-height: 0; display: flex; }
.sw-queue-hero .btn { flex-shrink: 0; }
.sw-q-col.pulse { animation: sw-q-pulse .9s var(--ease); }
@keyframes sw-q-pulse {
  0%, 100% { box-shadow: 0 0 0 0 transparent; }
  30% { box-shadow: 0 0 0 3px color-mix(in srgb, var(--portal) 45%, transparent); border-color: var(--portal-2); }
}
.sw-journal {
  margin-top: .75rem; border: 1px solid var(--hairline); border-radius: var(--radius-sm);
  background: var(--mat-1); overflow: hidden;
}
.sw-journal > summary {
  display: flex; align-items: center; gap: .7rem; padding: .95rem 1.15rem; cursor: pointer;
  list-style: none; user-select: none;
}
.sw-journal > summary::-webkit-details-marker { display: none; }
.sw-journal > summary:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.sw-journal-glyph {
  width: 26px; height: 26px; flex-shrink: 0; display: grid; place-items: center; font-size: 13px;
  border-radius: 8px; color: var(--tone, var(--portal));
  background: color-mix(in srgb, var(--tone, var(--portal)) 14%, transparent);
}
.sw-journal-title { font-weight: 800; font-size: 1rem; letter-spacing: -.01em; }
.sw-journal-sub { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); }
.sw-journal-count { margin-left: auto; font-family: var(--mono); font-size: 11px; color: var(--fg-mute); }
.sw-journal-chev { font-size: 12px; color: var(--fg-mute); transition: transform var(--t-fast) var(--ease); }
.sw-journal[open] .sw-journal-chev { transform: rotate(180deg); }
.sw-journal-body { padding: 0 1.15rem 1.15rem; }
.sw-journal-body .sw-watch-card:first-child { margin-top: .25rem; }
@media (max-width: 620px) {
  .ws-strip { margin-left: 0; width: 100%; }
  .sw-journal-sub { display: none; }
}
.sw-watch-card { border: 1px solid var(--hairline); border-radius: 14px; padding: 1rem 1.2rem; background: var(--bg-soft); margin-top: 1.25rem; }
.sw-watch-list { display: flex; flex-direction: column; gap: .5rem; margin-top: .6rem; }
.sw-watch-item { font-size: 13px; line-height: 1.5; color: var(--fg-dim); padding-left: .9rem; border-left: 2px solid color-mix(in srgb, var(--portal) 35%, transparent); }
.sw-watch-lead { font-weight: 700; color: var(--fg); margin-right: .4rem; }
.sw-entry { border-top: 1px solid var(--hairline); padding: .9rem .1rem; }
.sw-entry:first-of-type { border-top: none; }
.sw-entry-head { display: flex; align-items: baseline; gap: .6rem; flex-wrap: wrap; }
.sw-entry-date { font-family: var(--mono); font-size: 11.5px; color: var(--portal-2); font-weight: 700; }
.sw-entry-title { font-weight: 700; font-size: 14.5px; }
.sw-entry-watchflag { margin-left: auto; font-family: var(--mono); font-size: 10px; color: var(--c-amber-1, #e0a64a); border: 1px solid color-mix(in srgb, var(--c-amber-1, #e0a64a) 40%, transparent); border-radius: 6px; padding: .05rem .35rem; }
.sw-entry-summary { margin: .45rem 0 .2rem; font-size: 13px; color: var(--fg-dim); line-height: 1.55; }
.sw-entry-watch { font-size: 12.5px; color: var(--c-amber-1, #e0a64a); background: color-mix(in srgb, var(--c-amber-1, #e0a64a) 8%, transparent); border-radius: 8px; padding: .4rem .6rem; margin-top: .35rem; line-height: 1.5; }
.sw-entry-watch-l { font-weight: 700; }
.sw-entry-details { margin-top: .5rem; }
.sw-entry-details summary { font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); cursor: pointer; }
.sw-entry-body { margin-top: .5rem; padding: .8rem 1rem; background: var(--bg-soft); border: 1px solid var(--hairline); border-radius: 10px; font-size: 12.5px; line-height: 1.55; white-space: pre-wrap; overflow-x: auto; font-family: var(--mono); color: var(--fg-dim); }
.sw-kb-top { display: flex; align-items: baseline; gap: .5rem; flex-wrap: wrap; }
.sw-kb-kind { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: .05em; color: var(--portal-2); border: 1px solid color-mix(in srgb, var(--portal) 35%, transparent); border-radius: 6px; padding: .06rem .35rem; }
.sw-kb-title { font-weight: 700; font-size: 14px; }
/* Long notes clamp to ~6 lines so the store stays scannable as it grows; click
   a body to expand it. Model Memory is agent-written and dense — findability first. */
.sw-kb-body { margin-top: .45rem; font-size: 12.5px; color: var(--fg-dim); line-height: 1.55; white-space: pre-wrap; cursor: pointer;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 6; overflow: hidden; }
.sw-kb-body.expanded { -webkit-line-clamp: unset; overflow: visible; }
.sw-kb-tags { display: flex; gap: .3rem; flex-wrap: wrap; margin-top: .5rem; }
.sw-kb-tag { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); border: 1px solid var(--hairline); border-radius: 6px; padding: .05rem .35rem; }
/* Provenance tier — YOU-SAID (law, green) vs MINE (inference, muted). */
.kb-prov { font-family: var(--mono); font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em; border-radius: 6px; padding: .06rem .4rem; }
.kb-prov-yousaid { color: var(--c-mint-1, #3fb27f); border: 1px solid color-mix(in srgb, var(--c-mint-1, #3fb27f) 45%, transparent); background: color-mix(in srgb, var(--c-mint-1, #3fb27f) 12%, transparent); }
.kb-prov-mine { color: var(--fg-mute); border: 1px solid var(--hairline); }
.kb-prov-mixed { color: var(--portal-2); border: 1px solid color-mix(in srgb, var(--portal) 35%, transparent); }
.kb-area { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); }
/* v3 lifecycle chips — neutral graphite; status carries state, not decoration */
.kb-status { font-family: var(--mono); font-size: 9.5px; text-transform: uppercase; letter-spacing: .06em; border-radius: 6px; padding: .06rem .4rem; border: 1px solid var(--hairline); color: var(--fg-mute); }
.kb-status-superseded { text-decoration: line-through; opacity: .8; }
.kb-status-snapshot { color: var(--c-amber-1); border-color: color-mix(in srgb, var(--c-amber-1) 40%, transparent); }
.kb-status-active { color: var(--portal-2); border-color: color-mix(in srgb, var(--portal) 35%, transparent); }
/* Agent-primary framing + search toolbar. */
.kb-lede { margin: 0 0 1rem; font-size: 13px; line-height: 1.6; color: var(--fg-dim); max-width: 82ch; }
.kb-lede code { font-family: var(--mono); font-size: 11.5px; background: var(--mat-1); border: 1px solid var(--hairline); border-radius: 4px; padding: .04rem .3rem; }
.kb-toolbar { display: flex; align-items: center; gap: .8rem; margin-bottom: 1rem; }
.kb-search { flex: 1; min-width: 0; background: var(--bg-soft); border: 1px solid var(--hairline); border-radius: 10px;
  color: var(--fg); font: inherit; font-size: 13px; padding: .5rem .8rem; }
.kb-search:focus { outline: none; border-color: color-mix(in srgb, var(--portal) 50%, var(--hairline)); }
.kb-count { font-family: var(--mono); font-size: 11.5px; color: var(--fg-mute); flex-shrink: 0; }
.crud-card.is-hidden { display: none; }

/* --- Build Queue (forward lane) — three status columns ------------------- */
/* Defined-height kanban: the board is locked to (roughly) the app viewport
   minus the chrome + the two headers above it, so lopsided column counts (8
   shipped vs 1 pending) never stretch the page — each column scrolls its own
   cards instead. --portal-chrome-h is the live nav+subnav height (layout.js). */
.sw-q-board {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .75rem;
  flex: 1 1 auto; width: 100%; height: 100%; min-height: 18rem;
}
.sw-q-col { display: flex; flex-direction: column; min-height: 0; background: var(--bg-soft); border: 1px solid var(--hairline); border-radius: 14px; padding: .8rem .7rem; }
.sw-q-col-head { display: flex; align-items: baseline; gap: .5rem; padding: 0 .2rem .6rem; border-bottom: 1px solid var(--hairline); flex-shrink: 0; }
/* Per-column scroll — the head stays pinned, the cards scroll. */
.sw-q-cards { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 0 .25rem; margin: 0 -.25rem; }
.sw-q-cards::-webkit-scrollbar { width: 7px; }
.sw-q-cards::-webkit-scrollbar-thumb { background: var(--border-hi); border-radius: 999px; }
.sw-q-cards::-webkit-scrollbar-track { background: transparent; }
.sw-q-col-name { font-weight: 800; font-size: 12px; text-transform: uppercase; letter-spacing: .05em; }
.sw-q-col-count { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); margin-left: auto; }
/* Pending leans amber (waiting), building leans the portal accent (active),
   shipped greens out (done) — the lane reads its own state at a glance. */
.sw-q-col-pending .sw-q-col-name { color: var(--c-amber-1, #e0a64a); }
.sw-q-col-building .sw-q-col-name { color: var(--portal-2); }
.sw-q-col-shipped .sw-q-col-name { color: var(--c-mint-1, #3fb27f); }
.sw-q-empty { font-size: 12px; color: var(--fg-mute); padding: .6rem .3rem; font-style: italic; }
/* A build is a COMPACT ROW by default (one line) — expands to full detail on
   click. ~a tenth of the old card, so the board reads as a dense workshop.
   [RYDER-VERDICT] builds "should be minimized… i was expecting like 95%." */
.sw-q-card { border: 1px solid var(--hairline); border-radius: 8px; margin-top: .3rem; background: var(--bg); border-left: 3px solid var(--hairline); overflow: hidden; }
.sw-q-pending  { border-left-color: var(--c-amber-1, #e0a64a); }
.sw-q-building { border-left-color: var(--portal-2); }
.sw-q-shipped  { border-left-color: var(--c-mint-1, #3fb27f); }
.sw-q-row { display: flex; align-items: center; gap: .5rem; width: 100%; text-align: left; cursor: pointer;
  background: none; border: 0; padding: .4rem .55rem; color: var(--fg); font: inherit; }
.sw-q-row:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.sw-q-tick { width: 7px; height: 7px; border-radius: 999px; flex-shrink: 0; background: var(--hairline); }
.sw-q-pending  .sw-q-tick { background: var(--c-amber-1, #e0a64a); }
.sw-q-building .sw-q-tick { background: var(--portal-2); }
.sw-q-shipped  .sw-q-tick { background: var(--c-mint-1, #3fb27f); }
.sw-q-title { font-weight: 600; font-size: 12.5px; line-height: 1.3; flex: 1; min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sw-q-shipped .sw-q-title { color: var(--fg-dim); }
.sw-q-chev { font-size: 10px; color: var(--fg-mute); flex-shrink: 0; transition: transform var(--t-fast) var(--ease); }
.sw-q-card.open .sw-q-chev { transform: rotate(90deg); }
.sw-q-det { display: none; padding: 0 .55rem .55rem; }
.sw-q-card.open .sw-q-det { display: block; }
.sw-q-scope { margin: .1rem 0 .5rem; font-size: 12px; color: var(--fg-dim); line-height: 1.5; }
.sw-q-metarow { font-size: 11px; line-height: 1.45; display: flex; gap: .4rem; margin-bottom: .5rem; }
.sw-q-meta-l { font-family: var(--mono); font-size: 9.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-mute); padding-top: .12rem; flex: none; }
.sw-q-meta-v { color: var(--fg-dim); min-width: 0; overflow-wrap: anywhere; }
.sw-q-brief { margin-bottom: .5rem; }
.sw-q-brief summary { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); cursor: pointer; }
.sw-q-brief-body { margin-top: .45rem; padding: .7rem .8rem; background: var(--bg-soft); border: 1px solid var(--hairline); border-radius: 9px; font-size: 11.5px; line-height: 1.55; white-space: pre-wrap; overflow-x: auto; font-family: var(--mono); color: var(--fg-dim); }
.sw-q-actions { display: flex; flex-wrap: wrap; gap: .35rem; }
@media (max-width: 760px) {
  /* Stack + flow naturally on mobile (the page scrolls, not each column). */
  .sw-q-board { grid-template-columns: 1fr; height: auto; min-height: 0; }
  .sw-q-cards { overflow: visible; }
}

/* --- Build Runner rail (right side of the bench) ------------------------- */
/* Compact contained surface: request form pinned at top, the Runs list scrolls
   its own overflow so the rail never grows the page past one viewport. */
.rn-rail {
  display: flex; flex-direction: column; gap: .7rem;
  background: var(--mat-1); border: 1px solid var(--hairline);
  border-radius: var(--radius-xs); padding: .8rem .8rem .7rem;
}
.rn-rail-head { display: flex; align-items: center; gap: .5rem; }
.rn-rail-glyph { color: var(--portal-2); font-size: 13px; }
.rn-rail-title { font-weight: 800; font-size: .95rem; letter-spacing: -.01em; }
.rn-rail-tag {
  margin-left: auto; font-family: var(--mono); font-size: 9.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em; color: var(--fg-mute);
  border: 1px solid var(--hairline); border-radius: 6px; padding: .06rem .35rem;
}
/* The runner form, compacted to a single narrow column in the rail. */
.rn-rail #rn-trigger { flex-shrink: 0; }
.rn-rail .crud-form { padding: .8rem; margin-bottom: 0; }
.rn-rail .crud-form-grid { grid-template-columns: 1fr; gap: .6rem; }
.rn-rail .crud-field input, .rn-rail .crud-field select, .rn-rail .crud-field textarea { padding: .45rem .6rem; }
.rn-rail .crud-form-actions { flex-direction: column; align-items: stretch; gap: .5rem; margin-top: .8rem; }
.rn-rail .crud-form-actions .btn { width: 100%; }
.rn-rail .rn-gate-note { font-size: 10.5px; line-height: 1.4; }
/* Runs: pinned head, own-scroll body so the list stays inside the rail. */
.rn-runs-sec { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto; border-top: 1px solid var(--hairline); padding-top: .6rem; }
.rn-runs-head { display: flex; align-items: baseline; gap: .5rem; margin-bottom: .5rem; flex-shrink: 0; }
.rn-runs-title { font-weight: 800; font-size: 12px; text-transform: uppercase; letter-spacing: .05em; }
.rn-rail #rn-runs { flex: 1 1 auto; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: .5rem; margin: 0 -.15rem; padding: 0 .15rem; }
.rn-rail #rn-runs::-webkit-scrollbar { width: 7px; }
.rn-rail #rn-runs::-webkit-scrollbar-thumb { background: var(--border-hi); border-radius: 999px; }
.rn-rail #rn-runs::-webkit-scrollbar-track { background: transparent; }
/* Run cards compress to the narrow rail. */
.rn-rail #rn-runs .crud-card { padding: .6rem .7rem; gap: .5rem; border-radius: var(--radius-xs); }
.rn-rail #rn-runs .crud-empty { font-size: 12px; }

/* --- Bench responsive: below the split, stack rail under the canvas ------ */
@media (max-width: 900px) {
  main.shop-bench {
    grid-template-columns: 1fr;
    grid-template-areas: "head" "gate" "canvas" "rail" "journal";
    min-height: 0;
  }
  .shop-bench .sw-queue-hero { display: block; }
  .sw-q-board { height: auto; min-height: 22rem; }
  .shop-bench .rn-rail { margin-top: .8rem; }
  .rn-rail #rn-runs { max-height: 24rem; }
}


/* =============================================================================
   CALENDAR — "The Aggregator"  (consolidated single-surface redesign)
   -----------------------------------------------------------------------------
   Fresh `cx-` namespace on purpose: the legacy `.cal-*` vocabulary is still
   reused by the Dashboard mini-calendar and the Expenses month strip, so none
   of it is touched here. Mission-control register: heavy Inter mastheads, all
   quantitative data in mono, a per-day spend spine as the signature, month grid
   and a linked rail (day editor · upcoming · Apple feeds) on one scroll.
============================================================================= */
/* Edge-to-edge: the calendar is one full-bleed surface (no side gutter, no
   floating max-width card). Cancels main's --pad-x the same way Places / the
   dash strip do — [RYDER-VERDICT] "make it end to end with no gutters". */
#portal-calendar { max-width: none; }
/* No top gutter: the rich header meets the top of the surface, not a strip of page
   background above it (overrides the shared `main > section` .9rem top padding). */
body[data-portal] main > section#portal-calendar { padding-top: 0; }

/* Opaque neutral scrollbar track — app chrome. (The fixed radial accent wash
   that once leaked a full-height tinted strip here is now removed outright in
   app mode — body[data-portal]::before is dead, see global.css — but an opaque
   track is correct app form regardless.) Theme-aware. */
html:has(body[data-portal]) { scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--fg) 26%, transparent) var(--bg); }
html:has(body[data-portal])::-webkit-scrollbar { width: 12px; height: 12px; }
html:has(body[data-portal])::-webkit-scrollbar-track { background: var(--bg); }
html:has(body[data-portal])::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--fg) 24%, transparent); border-radius: 999px;
  border: 3px solid var(--bg); background-clip: padding-box; }
html:has(body[data-portal])::-webkit-scrollbar-thumb:hover { background: var(--fg-mute); }
html:has(body[data-portal])::-webkit-scrollbar-corner { background: var(--bg); }
.cx { display: flex; flex-direction: column; gap: 0;
  margin-inline: calc(-1 * var(--pad-x));
  /* structural line weights — adapt to theme via --fg (dark fg on light, light on dark) */
  --cx-line: color-mix(in srgb, var(--fg) 13%, transparent);
  --cx-line-soft: color-mix(in srgb, var(--fg) 7%, transparent);
  --cx-recess: color-mix(in srgb, var(--fg) 3.5%, transparent); }

/* THE CHASSIS — one framed console spanning edge to edge. The spine band, the
   stream band, the month matrix and the rail are all tethered inside a single
   bordered surface, divided by shared rules. No side rounding, no gutter — it
   meets the viewport; only the top/bottom hairlines define it. */
.cx-chassis { border-block: 1px solid var(--cx-line); border-inline: 0; border-radius: 0;
  overflow: hidden; background: var(--bg-elev); }

/* --- masthead — the rich header, full-bleed. It IS the band: the recessed
   gradient + bottom hairline fill edge-to-edge (same width as the chassis), so no
   page background shows around it. Only the content is inset by --pad-x. -------- */
.cx-masthead { display: flex; flex-direction: column; gap: .7rem;
  padding: 1rem var(--pad-x) 1.05rem;
  /* Opaque base (bg-elev) UNDER the recess tint so the fixed accent wash can't
     bleed green through the header — the band matches the chassis surface below. */
  background: linear-gradient(180deg, var(--cx-recess), transparent), var(--bg-elev);
  border-bottom: 1px solid var(--cx-line); }
.cx-eyebrow { display: inline-flex; align-items: center; gap: .55rem; font-family: var(--mono);
  font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .18em; color: var(--portal-2); }
.cx-eyebrow-dot { width: 7px; height: 7px; border-radius: 999px; background: var(--portal-2);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--portal-2) 55%, transparent); animation: cx-pulse 2.6s ease-out infinite; }
.cx-eyebrow-sub { color: var(--fg-mute); letter-spacing: .1em; text-transform: none; font-weight: 500; }
.cx-eyebrow-sub::before { content: "/"; margin-right: .55rem; color: var(--hairline); color: var(--fg-mute); opacity: .5; }
@keyframes cx-pulse { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--portal-2) 50%, transparent); }
  70% { box-shadow: 0 0 0 7px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }

/* Rich header — three balanced zones: [Today] · ‹ July 2026 › · ＋. The center
   auto column keeps the month title dead-centered; the 1fr flanks hold the Today
   nav control (left) and the New-event ＋ (right), so neither pulls the title off
   axis. A soft recessed band gives the header its weight. */
.cx-mast-row { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 1rem; }
.cx-mast-left { justify-self: start; display: inline-flex; align-items: center; gap: .5rem; }
.cx-mast-right { justify-self: end; display: inline-flex; align-items: center; gap: .5rem; }
/* Month-nav group: [‹ July 2026 ›] — arrows flank the title as one control. */
.cx-monthnav { justify-self: center; display: inline-flex; align-items: center; gap: .55rem; }
.cx-title { margin: 0; font-weight: 900; line-height: .95; letter-spacing: -.04em;
  font-size: clamp(1.9rem, 4vw, 2.8rem); display: flex; align-items: baseline; gap: .45rem;
  text-align: center; }
.cx-title-mo { color: var(--fg); }
.cx-title-yr { color: var(--fg-mute); font-weight: 500; letter-spacing: -.02em; font-size: .5em;
  font-family: var(--mono); align-self: center; }

.cx-nav-btn { font-family: var(--mono); font-size: 12px; font-weight: 600; color: var(--fg-dim);
  background: transparent; border: 1px solid var(--hairline); border-radius: 10px; padding: .42rem .7rem; cursor: pointer;
  transition: background .15s, color .15s, border-color .15s; }
.cx-nav-btn:hover { color: var(--fg); background: var(--mat-1); border-color: var(--border); }
/* Flanking arrows: square, sized to sit beside the big title. */
.cx-monthnav .cx-nav-arrow { font-size: 20px; line-height: 1; width: 2.3rem; height: 2.3rem;
  display: inline-flex; align-items: center; justify-content: center; padding: 0; background: var(--bg-soft); }
.cx-nav-today { font-weight: 700; color: var(--portal-2); background: var(--bg-soft); }

/* New event, reduced to a single animated-motion ＋ disc. Idle: a slow breathing
   glow. Hover/focus: the ＋ spins a quarter turn and the disc lifts. */
.cx-new { display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
  width: 2.6rem; height: 2.6rem; color: var(--accent-fg);
  background: linear-gradient(180deg, var(--portal), var(--portal-2)); border: none; border-radius: 999px;
  box-shadow: 0 8px 22px -10px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,.28);
  transition: transform .18s cubic-bezier(.2,.8,.2,1), box-shadow .18s;
  animation: cx-new-breathe 3.2s ease-in-out infinite; }
.cx-new:hover, .cx-new:focus-visible { transform: translateY(-1px) scale(1.06);
  box-shadow: 0 16px 34px -10px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,.34); }
.cx-new-plus { font-size: 20px; line-height: 1; font-weight: 400;
  transition: transform .3s cubic-bezier(.2,.8,.2,1); }
.cx-new:hover .cx-new-plus, .cx-new:focus-visible .cx-new-plus { transform: rotate(90deg); }
@keyframes cx-new-breathe {
  0%, 100% { box-shadow: 0 8px 22px -10px var(--accent-glow), inset 0 1px 0 rgba(255,255,255,.28); }
  50% { box-shadow: 0 10px 28px -8px var(--accent-glow), 0 0 0 4px color-mix(in srgb, var(--portal) 14%, transparent), inset 0 1px 0 rgba(255,255,255,.28); }
}

/* --- spend spine band (the signature) ------------------------------------- */
/* Relocated to the foot of the chassis: divide it from the grid above with a TOP
   hairline, and let the recess shade rise from the bottom edge. */
.cx-spine-wrap { padding: 1rem 1.2rem 1.1rem; border-top: 1px solid var(--cx-line);
  background: linear-gradient(0deg, var(--cx-recess), transparent); }
.cx-spine-head { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin-bottom: .7rem; }
.cx-spine-label { font-family: var(--mono); font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .16em; color: var(--fg-mute); }
.cx-spine-hint { font-family: var(--mono); font-size: 11.5px; color: var(--fg-dim); }

.cx-spine { display: flex; align-items: flex-end; gap: 2px; height: 78px; }
.cx-spine-day { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; align-items: center;
  gap: 3px; cursor: pointer; border-radius: 6px; padding: 2px 0 3px; transition: background .15s; height: 100%;
  justify-content: flex-end; }
.cx-spine-day:hover { background: color-mix(in srgb, var(--fg) 5%, transparent); }
.cx-spine-day.wknd .cx-spine-num { color: var(--fg-mute); opacity: .6; }
/* Selected/today are marked on the NUMBER only (a ring / a filled chip) — never a
   full-height column outline, which on an empty day reads as a tall ghost bar. */
.cx-spine-day.is-sel .cx-spine-num { color: var(--portal-2); font-weight: 800;
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--portal) 55%, transparent);
  border-radius: 5px; padding: 2px 4px; }
.cx-spine-pips { display: flex; gap: 2px; height: 6px; align-items: center; }
.cx-spine-pip { width: 4px; height: 4px; border-radius: 999px; }
.cx-spine-track { flex: 1; min-height: 0; width: 100%; display: flex; align-items: flex-end; justify-content: center; }
.cx-spine-bar { width: min(11px, 78%); border-radius: 3px 3px 1px 1px; height: var(--h, 0%);
  min-height: 0; background: transparent; }
.cx-spine-bar.has { background: linear-gradient(180deg, var(--bc), color-mix(in srgb, var(--bc) 55%, transparent));
  transform-origin: bottom; animation: cx-rise .55s cubic-bezier(.2,.8,.2,1) both; animation-delay: var(--delay, 0ms); }
@keyframes cx-rise { from { transform: scaleY(0); } to { transform: scaleY(1); } }
.cx-spine-day:not(.is-sel):not(.is-today) .cx-spine-track::after { content: ""; }
.cx-spine-num { font-family: var(--mono); font-size: 9.5px; font-weight: 600; color: var(--fg-dim); line-height: 1; }
.cx-spine-day.is-today .cx-spine-num { color: var(--accent-fg); background: var(--portal-2); font-weight: 800;
  border-radius: 5px; padding: 2px 4px; box-shadow: 0 0 14px -2px var(--accent-glow); }

/* Stream filters lead the foot block; the spend spine reads beneath them. The
   chips band bleeds to the wrap's top edge (it used to bleed to the bottom). */
.cx-streams { display: flex; flex-wrap: wrap; gap: .5rem; margin: -1rem -1.2rem 1rem;
  padding: .85rem 1.2rem; border-bottom: 1px solid var(--cx-line); background: var(--cx-recess); }
.cx-stream { display: inline-flex; align-items: center; gap: .5rem; font-family: var(--mono);
  font-size: 12px; color: var(--fg-dim); background: var(--bg-soft); border: 1px solid var(--hairline);
  border-radius: 999px; padding: .4rem .7rem .4rem .55rem; cursor: pointer;
  transition: background .15s, border-color .15s, color .15s, opacity .15s; }
.cx-stream:hover { border-color: color-mix(in srgb, var(--sc) 45%, transparent); color: var(--fg); }
.cx-stream-dot { width: 9px; height: 9px; border-radius: 999px; background: var(--sc);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--sc) 18%, transparent); flex: none; }
.cx-stream-name { font-weight: 600; letter-spacing: .01em; }
.cx-stream-meta { display: inline-flex; align-items: center; gap: .4rem; margin-left: .1rem; }
.cx-stream-count { color: var(--fg-mute); font-size: 11px; }
.cx-stream-amt { color: var(--fg); font-weight: 700; padding-left: .4rem;
  border-left: 1px solid var(--hairline); }
.cx-stream.off { opacity: .5; background: transparent; }
.cx-stream.off .cx-stream-dot { background: transparent; box-shadow: inset 0 0 0 1.5px var(--sc); }
.cx-stream.off .cx-stream-name { text-decoration: line-through; text-decoration-color: var(--fg-mute); }

/* --- body: month matrix | rail, split by a structural rule ---------------- */
.cx-body { display: grid; grid-template-columns: minmax(0, 1fr) 360px; align-items: stretch; }
.cx-grid-wrap { min-width: 0; display: flex; flex-direction: column; border-right: 1px solid var(--cx-line); }

/* weekday header = a labeled band with column ticks */
.cx-dows { display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid var(--cx-line);
  background: var(--cx-recess); }
.cx-dow { font-family: var(--mono); font-size: 10px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .12em; color: var(--fg-mute); text-align: center; padding: .5rem 0;
  border-right: 1px solid var(--cx-line-soft); }
.cx-dow:nth-child(7) { border-right: none; }
.cx-dow.wknd { color: color-mix(in srgb, var(--fg-mute) 65%, var(--portal)); }
.cx-dow-min { display: none; }

/* the matrix: cells share edges (no gaps, no per-cell radius) = a real grid */
.cx-cells { flex: 1; display: grid; grid-template-columns: repeat(7, 1fr); grid-auto-rows: minmax(100px, 1fr); }
.cx-cell { position: relative; display: flex; flex-direction: column; gap: 5px; min-width: 0;
  padding: .5rem .55rem; background: transparent; cursor: pointer;
  border-right: 1px solid var(--cx-line-soft); border-bottom: 1px solid var(--cx-line-soft);
  transition: background .12s; }
.cx-cell:nth-child(7n) { border-right: none; }
.cx-cell:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.cx-cell.out { background: var(--cx-recess); }
.cx-cell.out .cx-cell-num { color: var(--fg-mute); opacity: .5; }
.cx-cell.wknd:not(.out) { background: color-mix(in srgb, var(--fg) 2%, transparent); }
/* today/selected are structural states of a matrix cell — an inset frame + fill,
   not a floating ring. Today reads green; a non-today selection reads neutral. */
.cx-cell.today { background: color-mix(in srgb, var(--portal) 9%, transparent);
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--portal) 55%, transparent); z-index: 1; }
.cx-cell.sel { box-shadow: inset 0 0 0 2px var(--portal-2); z-index: 2; }
.cx-cell.today.sel { box-shadow: inset 0 0 0 2px var(--portal-2); }
/* day whose right-click menu is open — a soft tint that reads under sel/today rings */
.cx-cell.cx-cell-ctx { background: color-mix(in srgb, var(--portal) 15%, transparent); }

/* right-click option menu — floats at the cursor, portal graphite */
.cx-ctx { position: fixed; z-index: 3000; min-width: 172px; padding: 4px;
  background: var(--bg-elev); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 14px 34px rgba(0,0,0,.42), 0 3px 10px rgba(0,0,0,.3);
  animation: cx-ctx-in .11s ease; }
.cx-ctx-head { font-family: var(--mono); font-size: 9.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .09em; color: var(--fg-mute); padding: .42rem .55rem .34rem; }
.cx-ctx-item { display: flex; align-items: center; gap: .55rem; width: 100%; text-align: left;
  font-family: inherit; font-size: 12.5px; font-weight: 500; color: var(--fg); background: transparent;
  border: none; border-radius: 7px; padding: .5rem .55rem; cursor: pointer; transition: background .1s, color .1s; }
.cx-ctx-item:hover { background: color-mix(in srgb, var(--portal) 16%, transparent); color: var(--portal-2); }
.cx-ctx-ico { font-family: var(--mono); width: 1rem; text-align: center; color: var(--portal-2); flex: none; }
.cx-ctx-item.danger { color: var(--c-coral-2); }
.cx-ctx-item.danger:hover { background: color-mix(in srgb, var(--c-coral-2) 15%, transparent); color: var(--c-coral-2); }
.cx-ctx-item.danger .cx-ctx-ico { color: var(--c-coral-2); }
.cx-ctx-sep { height: 1px; background: var(--cx-line); margin: 4px 2px; }
@keyframes cx-ctx-in { from { opacity: 0; transform: translateY(-3px) scale(.98); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .cx-ctx { animation: none; } }
.cx-cell-top { display: flex; align-items: baseline; justify-content: space-between; gap: .3rem; }
.cx-cell-num { font-family: var(--mono); font-size: 12.5px; font-weight: 700; color: var(--fg-dim); }
.cx-cell.today .cx-cell-num { color: var(--accent-fg); background: var(--portal-2); border-radius: 6px;
  padding: 0 .34rem; line-height: 1.5; font-weight: 800; }
.cx-cell-sum { font-family: var(--mono); font-size: 10px; font-weight: 700; color: var(--fg-mute); }
.cx-cell-lines { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cx-line { display: flex; align-items: center; gap: 5px; min-width: 0; font-size: 11px; line-height: 1.3; }
.cx-line-dot { width: 6px; height: 6px; border-radius: 999px; flex: none; }
.cx-line-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--fg); font-weight: 500; }
.cx-line.sub .cx-line-name { color: var(--fg-dim); font-weight: 400; }
.cx-line-amt { font-family: var(--mono); font-size: 10.5px; font-weight: 700; color: var(--fg); flex: none; }
.cx-line-time { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); flex: none; }
.cx-cell-more { font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); margin-top: 1px; }

/* --- rail: stacked panels tethered inside the chassis (no floating cards) -- */
.cx-rail { position: relative; min-width: 0; }
/* Absolutely-filled so the rail's own content (esp. the open event form) can't
   push the shared grid row taller — the month grid alone sizes the row; this
   inner column scrolls, and the upcoming stream shrinks, to absorb the form. */
.cx-rail-inner { position: absolute; inset: 0; display: flex; flex-direction: column;
  min-height: 0; overflow-y: auto; scrollbar-width: thin; }

/* Day card = a "focus" panel headed by a physical DATE TILE (a tear-off calendar
   block). The tile is the structural anchor — the number lives centered inside
   its own bordered object, so nothing is a giant numeral floating out of line. */
.cx-daycard { flex: none; padding: 2rem 1.2rem 1.15rem; border-bottom: 1px solid var(--cx-line);
  background: var(--cx-recess); }
/* The daycard is a <section> and the first among its siblings, so global.css's
   marketing-rhythm rule `section:first-of-type { padding-top: 0 }` (0,1,1)
   silently beat `.cx-daycard` (0,1,0) and flattened the tile against the rail's
   top line. This selector (0,2,0) restores the intended air. */
.cx-rail-inner > .cx-daycard { padding-top: 1.35rem; }
.cx-daycard.is-today { background: linear-gradient(180deg, color-mix(in srgb, var(--portal) 8%, transparent), transparent 60%); }

.cx-day-head { display: flex; align-items: stretch; gap: .85rem; margin-bottom: .95rem; }
.cx-datetile { flex: none; width: 62px; display: flex; flex-direction: column; align-items: stretch;
  border: 1px solid var(--cx-line); border-radius: 10px; overflow: hidden; background: var(--bg-elev);
  box-shadow: var(--shadow-xs); }
.cx-dt-dow { text-align: center; font-family: var(--mono); font-size: 9px; font-weight: 700; letter-spacing: .12em;
  color: var(--fg-mute); padding: .22rem 0; background: var(--cx-line-soft); }
.cx-dt-num { text-align: center; font-size: 1.85rem; font-weight: 900; letter-spacing: -.04em; line-height: 1.05;
  color: var(--fg); padding: .18rem 0 .05rem; }
.cx-dt-mo { text-align: center; font-family: var(--mono); font-size: 8.5px; font-weight: 600; letter-spacing: .08em;
  color: var(--fg-mute); padding-bottom: .28rem; }
.cx-datetile.is-today { border-color: color-mix(in srgb, var(--portal) 55%, transparent);
  box-shadow: 0 8px 20px -10px var(--accent-glow); }
.cx-datetile.is-today .cx-dt-dow { background: var(--portal-2); color: var(--accent-fg); }
.cx-datetile.is-today .cx-dt-num { color: var(--portal-2); }

.cx-day-info { display: flex; flex-direction: column; align-items: flex-end; justify-content: center;
  gap: .15rem; margin-left: auto; text-align: right; }
.cx-day-today { font-family: var(--mono); font-size: 8.5px; font-weight: 700; letter-spacing: .12em;
  color: var(--accent-fg); background: var(--portal-2); border-radius: 5px; padding: .14rem .4rem; }
.cx-day-when-lab { font-family: var(--mono); font-size: 9px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--fg-mute); }
.cx-day-total { font-family: var(--mono); font-size: 1.5rem; font-weight: 800; letter-spacing: -.02em; line-height: 1;
  color: var(--fg); }
.cx-daycard.is-today .cx-day-total { color: var(--portal-2); }
.cx-day-count { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }

.cx-day-list { display: flex; flex-direction: column; }

/* An agenda item = a compact row + an in-place detail drawer. Shared by the
   selected-day card (expandable) and the Upcoming stream (tap-to-navigate). */
.cx-day-item { border-top: 1px solid var(--cx-line-soft); }
.cx-day-list > .cx-day-item:first-child { border-top: none; }
.cx-day-item.past .cx-day-row { opacity: .48; }
.cx-day-item.past .cx-day-timechip { color: var(--fg-mute); }

.cx-day-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: .55rem; padding: .5rem .1rem; }
.cx-day-row.tap { cursor: pointer; border-radius: 8px; transition: background .12s; }
.cx-day-row.tap:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.cx-day-dot { width: 8px; height: 8px; border-radius: 999px; background: var(--rc); flex: none;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--rc) 16%, transparent); align-self: start; margin-top: 5px; }
.cx-day-end { display: inline-flex; align-items: center; gap: .4rem; justify-self: end; flex: none; }

.cx-day-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.cx-day-line1 { display: flex; align-items: baseline; gap: .4rem; min-width: 0; }
.cx-day-timechip { font-family: var(--mono); font-size: 10.5px; font-weight: 700; color: var(--portal-2);
  flex: none; font-variant-numeric: tabular-nums; }
.cx-day-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12.5px; font-weight: 500; color: var(--fg); }
.cx-day-meta { display: flex; align-items: center; gap: .3rem; min-width: 0; font-family: var(--mono);
  font-size: 10px; color: var(--fg-mute); }
.cx-day-meta > * { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cx-route { display: inline-flex; align-items: center; gap: .28rem; min-width: 0; }
.cx-route-r { color: var(--fg-dim); }
.cx-route-arrow { opacity: .55; }
.cx-route-c { color: var(--fg-dim); font-weight: 600; }
.cx-meta-sep { opacity: .5; }
.cx-meta-pin { color: var(--fg-mute); opacity: .7; font-size: 8px; }

.cx-day-amt { font-family: var(--mono); font-size: 11.5px; font-weight: 700; color: var(--fg); font-variant-numeric: tabular-nums; }
.cx-join { font-family: var(--mono); font-size: 10px; font-weight: 700; text-decoration: none;
  color: var(--accent-fg); background: var(--portal-2); border-radius: 6px; padding: .16rem .42rem;
  line-height: 1.2; white-space: nowrap; }
.cx-join:hover { filter: brightness(1.08); }

.cx-chev { font-family: var(--mono); font-size: 13px; line-height: 1; color: var(--fg-mute);
  background: transparent; border: 1px solid var(--hairline); border-radius: 6px; width: 1.35rem; height: 1.35rem;
  cursor: pointer; transition: transform .18s, color .15s, border-color .15s; }
.cx-chev:hover { color: var(--portal-2); border-color: color-mix(in srgb, var(--portal) 40%, transparent); }
.cx-day-item.open .cx-chev { transform: rotate(90deg); color: var(--portal-2); }

.cx-day-detail { display: none; flex-direction: column; gap: .35rem; padding: .05rem .1rem .7rem 1.5rem; }
.cx-day-item.open .cx-day-detail { display: flex; }
.cx-detail-row { display: flex; align-items: baseline; gap: .5rem; font-size: 12px; min-width: 0; }
.cx-detail-row.full { flex-direction: column; gap: .2rem; }
.cx-detail-lab { font-family: var(--mono); font-size: 9px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--fg-mute); flex: none; min-width: 3rem; }
.cx-detail-val { color: var(--fg-dim); min-width: 0; overflow-wrap: anywhere; }
.cx-detail-link { color: var(--portal-2); text-decoration: none; overflow-wrap: anywhere; }
.cx-detail-link:hover { text-decoration: underline; }
.cx-detail-notes { color: var(--fg-dim); font-size: 12px; line-height: 1.5; white-space: pre-wrap; overflow-wrap: anywhere; }
.cx-detail-acts { display: flex; gap: .4rem; margin-top: .25rem; }

/* "now" hairline in today's agenda — everything above already happened. */
.cx-now-line { display: flex; align-items: center; gap: .5rem; padding: .3rem .1rem; }
.cx-now-lab { font-family: var(--mono); font-size: 9px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .1em; color: var(--portal-2); flex: none; }
.cx-now-rule { flex: 1; height: 1px; background: linear-gradient(90deg, var(--portal-2), transparent); }

.cx-tag { font-family: var(--mono); font-size: 8.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--fg-mute); border: 1px solid var(--hairline); border-radius: 5px; padding: .08rem .3rem; white-space: nowrap; }
.cx-mini { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); background: transparent;
  border: 1px solid var(--hairline); border-radius: 6px; padding: .18rem .5rem; cursor: pointer; transition: color .15s, border-color .15s; }
.cx-mini:hover { color: var(--portal-2); border-color: color-mix(in srgb, var(--portal) 40%, transparent); }
.cx-mini.danger:hover { color: var(--c-coral-2); border-color: color-mix(in srgb, var(--c-coral-2) 45%, transparent); }
.cx-day-add { margin-top: .95rem; width: 100%; font-family: var(--mono); font-size: 11.5px; font-weight: 700;
  color: var(--portal-2); background: color-mix(in srgb, var(--portal) 7%, transparent);
  border: 1px solid color-mix(in srgb, var(--portal) 28%, transparent); border-radius: 9px;
  padding: .58rem; cursor: pointer; transition: background .15s, border-color .15s; }
.cx-day-add:hover { border-color: color-mix(in srgb, var(--portal) 55%, transparent);
  background: color-mix(in srgb, var(--portal) 13%, transparent); }
.cx-empty { font-family: var(--mono); font-size: 12px; color: var(--fg-mute); padding: .5rem 0; }

/* Upcoming stream — the tethered lower panel of the rail; scrolls INSIDE itself
   so a 60-day list can never stretch the page into a mile-long column. */
.cx-upcoming { display: flex; flex-direction: column; min-height: 0; flex: 1 1 auto;
  padding: 1.1rem 1.2rem .4rem; }
.cx-sec-head { display: flex; align-items: baseline; justify-content: space-between; gap: .7rem;
  margin-bottom: .5rem; flex: none; }
.cx-sec-head h3 { margin: 0; font-size: 1rem; font-weight: 800; letter-spacing: -.01em; }
.cx-sec-hint { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }
.cx-stream-list { display: flex; flex-direction: column; overflow-y: auto; min-height: 0;
  max-height: min(52vh, 560px); padding-right: .35rem; margin-right: -.35rem;
  scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--portal) 35%, transparent) transparent;
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 10px, #000 calc(100% - 14px), transparent 100%); }
.cx-stream-list::-webkit-scrollbar { width: 7px; }
.cx-stream-list::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--portal) 30%, transparent);
  border-radius: 999px; }
.cx-stream-list::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--portal) 50%, transparent); }
.cx-up-day { display: flex; align-items: baseline; gap: .45rem; padding: .7rem .1rem .3rem;
  border-top: 1px solid var(--hairline); margin-top: .3rem; }
.cx-up-day:first-child { border-top: none; margin-top: 0; padding-top: .2rem; }
.cx-up-dow { font-family: var(--mono); font-size: 9.5px; font-weight: 700; letter-spacing: .08em; color: var(--fg-mute); }
.cx-up-date { font-family: var(--mono); font-size: 14px; font-weight: 800; color: var(--fg); }
.cx-up-mo { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); text-transform: uppercase; }
.cx-up-day.today .cx-up-date, .cx-up-day.today .cx-up-dow { color: var(--portal-2); }
.cx-up-badge { font-family: var(--mono); font-size: 8.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--accent-fg); background: var(--portal-2); border-radius: 4px; padding: .1rem .3rem; margin-left: auto; align-self: center; }
/* Stream shares the agenda-item row; day headers do the separating, so items sit
   flush under a header and only rule between siblings within the same day. */
.cx-stream-list .cx-day-item { border-top: none; }
.cx-stream-list .cx-day-item + .cx-day-item { border-top: 1px solid var(--cx-line-soft); }
.cx-stream-list .cx-day-row { padding: .4rem .1rem .4rem .2rem; }

/* feeds disclosure (Subscribe, demoted) — the rail's tethered footer panel */
.cx-feeds { flex: none; border-top: 1px solid var(--cx-line); background: var(--cx-recess); }
.cx-feeds-sum { display: flex; align-items: center; gap: .6rem; padding: .85rem 1.2rem; cursor: pointer; list-style: none;
  font-family: var(--mono); font-size: 12px; font-weight: 600; color: var(--fg-dim); }
.cx-feeds-sum::-webkit-details-marker { display: none; }
.cx-feeds-ico { color: var(--portal-2); font-size: 14px; }
.cx-feeds-title { flex: 1; }
.cx-feeds-chev { color: var(--fg-mute); transition: transform .2s; }
.cx-feeds[open] .cx-feeds-chev { transform: rotate(90deg); }
.cx-feeds[open] .cx-feeds-sum { color: var(--fg); border-bottom: 1px solid var(--cx-line); }
.cx-feeds-body { padding: 1rem 1.2rem 1.2rem; display: flex; flex-direction: column; gap: 1rem; }
.cx-feeds-note { margin: 0; font-size: 12px; line-height: 1.55; color: var(--fg-mute); }
.cx-feed-grid { display: grid; grid-template-columns: 1fr 1fr; gap: .7rem; }
.cx-feed { border: 1px solid var(--hairline); border-left: 2px solid var(--fc); border-radius: 10px;
  background: var(--bg-elev); padding: .7rem .8rem; }
.cx-feed-h { display: flex; align-items: center; gap: .45rem; margin-bottom: .6rem; }
.cx-feed-dot { width: 8px; height: 8px; border-radius: 999px; background: var(--fc); }
.cx-feed-name { font-size: 12.5px; font-weight: 700; }
.cx-feed-actions { display: flex; gap: .4rem; flex-wrap: wrap; }
.cx-feed-sub, .cx-feed-copy { font-family: var(--mono); font-size: 10.5px; font-weight: 600; cursor: pointer;
  border-radius: 8px; padding: .32rem .55rem; text-decoration: none; border: 1px solid var(--hairline); }
.cx-feed-sub { color: var(--accent-fg); background: var(--portal-2); border-color: transparent; }
.cx-feed-copy { color: var(--fg-dim); background: transparent; }
.cx-feed-copy:hover { color: var(--fg); border-color: color-mix(in srgb, var(--portal) 40%, transparent); }

/* --- Google Calendar pull (one-way IN, lives under the Apple feeds) -------- */
.cx-gcal { border-top: 1px solid var(--cx-line-soft); padding-top: .9rem;
  display: flex; flex-direction: column; gap: .6rem; }
.cx-gcal-head { display: flex; align-items: center; gap: .45rem; }
.cx-gcal-dot { width: 8px; height: 8px; border-radius: 999px; background: #4285F4; }
.cx-gcal-title { font-size: 12.5px; font-weight: 700; }
.cx-gcal-row { display: flex; gap: .4rem; align-items: stretch; }
.cx-gcal-row .cx-in { flex: 1; min-width: 0; }
.cx-gcal-stat { display: flex; align-items: center; justify-content: space-between;
  gap: .6rem; flex-wrap: wrap; }
.cx-gcal-txt { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }
.cx-gcal-acts { display: flex; gap: .4rem; }

/* --- multi-day span bars: one contiguous ribbon across the grid ------------ */
/* Segments bleed over the cell's inline padding (and the 1px cell border) on
   every edge that continues into a neighbor, so adjacent segments read as ONE
   bar. Lanes keep a span's vertical slot stable from cell to cell; `empty`
   spacers hold a lane open where an overlapping span is absent. */
.cx-cell-spans { display: flex; flex-direction: column; gap: 2px; }
.cx-span-seg { height: 15px; display: flex; align-items: center; min-width: 0;
  background: color-mix(in srgb, var(--sc) 24%, transparent);
  margin-left: calc(-.55rem - 1px); margin-right: -.55rem; }
.cx-span-seg.s-start { margin-left: 0; border-left: 3px solid var(--sc);
  border-radius: 4px 0 0 4px; }
.cx-span-seg.s-end { margin-right: 0; border-radius: 0 4px 4px 0; }
.cx-span-seg.s-start.s-end { border-radius: 4px; }
.cx-span-seg.empty { visibility: hidden; }
.cx-span-lab { font-size: 10px; font-weight: 600; color: var(--fg); padding: 0 .35rem;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 560px) {
  .cx-span-seg { margin-left: calc(-.38rem - 1px); margin-right: -.38rem; }
  .cx-span-seg.s-start { margin-left: 0; }
  .cx-span-seg.s-end { margin-right: 0; }
}

/* multi-day continuation lines in the month grid read quieter than day one */
.cx-line.span-cont { opacity: .72; }

/* --- subscriptions read as OVERHEAD, not events ---------------------------- */
/* Grid cell: named pills are gone; the day's recurring spend settles into one
   quiet ledger line at the cell's foot (hover reveals the itemization). */
.cx-line-ovh { display: flex; align-items: baseline; justify-content: space-between; gap: .3rem;
  margin-top: auto; padding-top: 3px; border-top: 1px dashed var(--cx-line-soft); }
.cx-ovh-lab { font-family: var(--mono); font-size: 8.5px; font-weight: 600;
  letter-spacing: .09em; text-transform: uppercase; color: var(--fg-mute); }
.cx-ovh-amt { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }
/* Day card: the charges group under their own small ledger header + total. */
.cx-ovh { display: block; margin-top: .9rem; border-top: 1px dashed var(--cx-line);
  padding-top: .6rem; }
.cx-ovh-head { display: flex; align-items: baseline; justify-content: space-between;
  margin-bottom: .3rem; }
.cx-ovh-title { font-family: var(--mono); font-size: 9.5px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--fg-mute); }
.cx-ovh-total { font-family: var(--mono); font-size: 11.5px; font-weight: 700; color: var(--fg-dim); }

/* --- classes read as a timetable, not ad-hoc events ------------------------ */
/* A slim tick: colored rule + mono time + course code (no dot, no pill). */
.cx-line.cls { border-left: 2px solid var(--lc); padding-left: .35rem; }
.cx-line.cls .cx-line-time { font-family: var(--mono); font-size: 9.5px; font-weight: 600;
  color: var(--lc); flex: none; }
.cx-line.cls .cx-line-name { font-family: var(--mono); font-size: 10px; }
.cx-detail-src { font-size: 11px; line-height: 1.5; color: var(--fg-mute);
  font-style: italic; margin-top: .2rem; }

/* =============================================================================
   REMINDERS ON THE CALENDAR (2026-07-27)
   -----------------------------------------------------------------------------
   Reminders stopped being a separate page and became a stream on this grid. The
   whole visual argument is one control: a TICKABLE CIRCLE that replaces the
   category dot wherever a reminder appears — month cell, day card, upcoming,
   tray. Same object, same affordance, four places. Colour comes from the server
   palette (--cx-rem, published by the module); overdue borrows the coral tone,
   completion is carried by shape + strike, never by a second hue.
============================================================================= */
.cx { --cx-rem: #FF2D55; }
.cx-tick { --tc: var(--lc, var(--rc, var(--cx-rem)));
  flex: none; width: 13px; height: 13px; padding: 0; border-radius: 999px; cursor: pointer;
  background: transparent; border: 1.5px solid color-mix(in srgb, var(--tc) 70%, transparent);
  position: relative; transition: background .13s, border-color .13s, transform .13s; }
.cx-tick:hover { border-color: var(--tc); transform: scale(1.12); }
.cx-tick.pri { box-shadow: 0 0 0 2px color-mix(in srgb, var(--tc) 22%, transparent); }
.cx-tick.on { background: var(--tc); border-color: var(--tc); }
/* the check itself — drawn, not a glyph, so it stays crisp at 13px */
.cx-tick.on::after { content: ""; position: absolute; left: 3.2px; top: 1.1px; width: 3.4px; height: 6.4px;
  border: solid var(--bg-elev); border-width: 0 1.7px 1.7px 0; transform: rotate(42deg); }

/* month-grid line */
.cx-line.rem .cx-line-name { color: var(--fg); }
.cx-line.rem.done .cx-line-name { color: var(--fg-mute); text-decoration: line-through; }
.cx-line.rem.done .cx-line-time { opacity: .5; }
.cx-line.rem.over .cx-line-name { color: var(--c-coral-2); }
/* --- drag to reschedule: one mechanism, both kinds of thing --------------- */
/* Anything the site owns — a reminder, a manual event, a multi-day span bar —
   is grabbable from any view and dropped on a day. Projections (charges,
   classes) and Google rows are deliberately not draggable and say so by simply
   not offering the grab cursor. --cx-drag-c is set at dragstart to the dragged
   thing's stream colour, so the drop target reads as *that* thing landing. */
/* Grab cursor only where dragging is the row's PRIMARY verb — grid pills, span
   bars, tray rows. Agenda rows keep `pointer` (their primary verb is expand);
   they still drag, the cursor just doesn't oversell it. */
.cx-line.rem[draggable="true"], .cx-line.movable, .cx-span-seg.movable,
.cx-tray-row { cursor: grab; }
.cx-line.cx-dragging, .cx-tray-row.cx-dragging, .cx-day-row.cx-dragging,
.cx-span-seg.cx-dragging { opacity: .4; }
body.cx-dragging-item { cursor: grabbing; }
body.cx-dragging-item .cx-cell { border-color: color-mix(in srgb, var(--cx-drag-c, var(--portal-2)) 22%, transparent); }
.cx-cell.cx-drop { background: color-mix(in srgb, var(--cx-drag-c, var(--portal-2)) 16%, transparent);
  box-shadow: inset 0 0 0 2px var(--cx-drag-c, var(--portal-2)); z-index: 3; }
.cx-daycard.cx-drop { box-shadow: inset 0 0 0 2px var(--cx-drag-c, var(--portal-2)); }

/* day card: the reminders band across the top of the day (Apple's all-day rail) */
.cx-rembar { display: block; margin-bottom: .55rem; padding-bottom: .35rem;
  border-bottom: 1px dashed var(--cx-line); }
.cx-rembar-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: .1rem; }
.cx-rembar-title { font-family: var(--mono); font-size: 9.5px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: color-mix(in srgb, var(--cx-rem) 72%, var(--fg-mute)); }
.cx-rembar-n { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }
.cx-day-item.rem.done .cx-day-name { color: var(--fg-mute); text-decoration: line-through; }
.cx-day-item.rem.over .cx-day-name { color: var(--c-coral-2); }
.cx-day-meta.over .cx-meta-txt, .cx-detail-val.over { color: var(--c-coral-2); }
.cx-day-item.rem .cx-tick { align-self: start; margin-top: 3px; }
.cx-mini.on { color: var(--portal-2); border-color: color-mix(in srgb, var(--portal) 40%, transparent); }

/* the day's two add buttons — the two kinds of thing a day can hold */
.cx-day-adds { display: grid; grid-template-columns: 1fr 1fr; gap: .45rem; margin-top: .95rem; }
.cx-day-adds .cx-day-add { margin-top: 0; }
.cx-day-add.alt { color: var(--cx-rem); background: color-mix(in srgb, var(--cx-rem) 7%, transparent);
  border-color: color-mix(in srgb, var(--cx-rem) 26%, transparent); }
.cx-day-add.alt:hover { background: color-mix(in srgb, var(--cx-rem) 13%, transparent);
  border-color: color-mix(in srgb, var(--cx-rem) 52%, transparent); }

/* --- the tray: the loading dock for the grid ------------------------------ */
.cx-tray { flex: none; display: flex; flex-direction: column; min-height: 0;
  padding: .9rem 1.2rem 1rem; border-top: 1px solid var(--cx-line); background: var(--cx-recess); }
.cx-tray .cx-sec-head h3 { color: var(--fg); }
.cx-tray-add { display: flex; gap: .4rem; margin: .15rem 0 .55rem; }
.cx-tray-add .cx-in { flex: 1; min-width: 0; font-size: 12px; padding: .4rem .5rem; }
.cx-tray-addbtn { flex: none; width: 2rem; font-family: var(--mono); font-size: 14px; line-height: 1;
  color: var(--accent-fg); background: linear-gradient(180deg, var(--portal), var(--portal-2));
  border: none; border-radius: 8px; cursor: pointer; }
.cx-tray-lists { display: flex; flex-wrap: wrap; gap: .25rem; margin-bottom: .5rem; }
.cx-tray-chip { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); background: transparent;
  border: 1px solid var(--hairline); border-radius: 999px; padding: .1rem .45rem; cursor: pointer; }
.cx-tray-chip.on { color: var(--fg); border-color: color-mix(in srgb, var(--cx-rem) 50%, transparent);
  background: color-mix(in srgb, var(--cx-rem) 12%, transparent); }
.cx-tray-body { display: flex; flex-direction: column; min-height: 0; overflow-y: auto;
  max-height: min(34vh, 340px); scrollbar-width: thin; padding-right: .25rem; margin-right: -.25rem; }
.cx-tray-band { display: flex; align-items: baseline; gap: .4rem; padding: .45rem 0 .2rem; }
.cx-tray-band-k { font-family: var(--mono); font-size: 9px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--fg-mute); }
.cx-tray-band.over .cx-tray-band-k { color: var(--c-coral-2); }
.cx-tray-band-n { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); }
.cx-tray-row { display: flex; align-items: center; gap: .5rem; padding: .34rem .15rem; cursor: grab;
  border-top: 1px solid var(--cx-line-soft); }
.cx-tray-row:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); border-radius: 7px; }
.cx-tray-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.cx-tray-name { font-size: 12.5px; color: var(--fg); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cx-tray-row.pri .cx-tray-name { font-weight: 600; }
.cx-tray-meta { font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cx-tray-act { flex: none; font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute);
  background: transparent; border: 1px solid var(--hairline); border-radius: 6px;
  padding: .14rem .4rem; cursor: pointer; white-space: nowrap; }
.cx-tray-act:hover { color: var(--cx-rem); border-color: color-mix(in srgb, var(--cx-rem) 45%, transparent); }
.cx-tray-donetoggle { align-self: flex-start; margin-top: .45rem; font-family: var(--mono); font-size: 10.5px;
  color: var(--fg-mute); background: transparent; border: none; padding: .2rem 0; cursor: pointer; }
.cx-tray-donetoggle:hover { color: var(--fg); }

/* --- composer: segmented head (Event | Reminder) -------------------------- */
.cx-form-headrow { display: flex; align-items: center; justify-content: space-between;
  gap: .6rem; margin-bottom: .75rem; }
.cx-form-headrow .cx-form-head { margin-bottom: 0; }
.cx-seg { display: inline-flex; padding: 2px; gap: 2px; background: var(--bg-elev);
  border: 1px solid var(--hairline); border-radius: 999px; }
.cx-seg-b { font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: .04em;
  color: var(--fg-mute); background: transparent; border: none; border-radius: 999px;
  padding: .22rem .6rem; cursor: pointer; transition: background .13s, color .13s; }
.cx-seg-b.on { color: var(--accent-fg); background: var(--portal-2); }
.cx-form.rem .cx-seg-b.on { background: var(--cx-rem); }
.cx-form.rem { border-color: color-mix(in srgb, var(--cx-rem) 32%, var(--hairline)); }
.cx-form.rem .cx-form-head { color: var(--cx-rem); }
.cx-form.rem .cx-btn.primary { background: var(--cx-rem); }
.cx-check { display: inline-flex; align-items: center; gap: .4rem; font-size: 12px; color: var(--fg-dim);
  padding: .45rem .1rem; }
.cx-check input { accent-color: var(--cx-rem); }
.cx-form-note { margin: .6rem 0 0; font-family: var(--mono); font-size: 10px; line-height: 1.5; color: var(--fg-mute); }

/* --- inline event form ---------------------------------------------------- */
.cx-form-host:empty { display: none; }
.cx-form { border: 1px solid color-mix(in srgb, var(--portal) 30%, var(--hairline)); border-radius: var(--radius-xs);
  background: var(--bg-soft); padding: .9rem; margin-bottom: 1rem; }
.cx-form-head { font-family: var(--mono); font-size: 10.5px; font-weight: 700; text-transform: uppercase;
  letter-spacing: .12em; color: var(--portal-2); margin-bottom: .75rem; }
.cx-form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: .6rem; }
.cx-field { display: flex; flex-direction: column; gap: .25rem; min-width: 0; }
.cx-field.full { grid-column: 1 / -1; }
.cx-field-lab { font-family: var(--mono); font-size: 9.5px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .06em; color: var(--fg-mute); }
.cx-in { font-family: inherit; font-size: 12.5px; color: var(--fg); background: var(--bg-elev);
  border: 1px solid var(--hairline); border-radius: 8px; padding: .45rem .55rem; width: 100%; }
.cx-in:focus { outline: none; border-color: var(--portal-2); box-shadow: 0 0 0 3px var(--accent-soft); }
textarea.cx-in { resize: vertical; min-height: 2.2rem; }
.cx-form-actions { display: flex; gap: .5rem; margin-top: .85rem; flex-wrap: wrap; }
.cx-btn { font-family: var(--mono); font-size: 11.5px; font-weight: 700; cursor: pointer;
  border-radius: 9px; padding: .5rem .85rem; border: 1px solid var(--hairline); background: transparent; color: var(--fg-dim); }
.cx-btn.primary { color: var(--accent-fg); background: linear-gradient(180deg, var(--portal), var(--portal-2)); border-color: transparent; }
.cx-btn.ghost:hover { color: var(--fg); border-color: color-mix(in srgb, var(--portal) 35%, transparent); }
.cx-btn.danger { color: var(--c-coral-2); margin-left: auto; }
.cx-btn.danger:hover { border-color: color-mix(in srgb, var(--c-coral-2) 45%, transparent); }

/* --- responsive reflow ---------------------------------------------------- */
@media (max-width: 980px) {
  /* stack: matrix on top, rail below — divide them with a horizontal rule */
  .cx-body { grid-template-columns: 1fr; }
  .cx-grid-wrap { border-right: none; border-bottom: 1px solid var(--cx-line); }
  .cx-feed-grid { grid-template-columns: 1fr 1fr; }
  /* stacked: the rail flows naturally below the grid — undo the desktop fill */
  .cx-rail { position: static; }
  .cx-rail-inner { position: static; overflow: visible; }
}
@media (max-width: 560px) {
  .cx-title { font-size: clamp(2rem, 11vw, 2.6rem); }
  .cx-dow-full { display: none; } .cx-dow-min { display: inline; }
  .cx-cells { grid-auto-rows: minmax(76px, 1fr); }
  .cx-cell { padding: .35rem .38rem; }
  .cx-cell-top { min-width: 0; }
  .cx-cell-sum { display: none; }       /* redundant with per-line amounts; drops min-width pressure */
  .cx-cell-lines .cx-line-name { font-size: 10px; }
  /* 31 columns on a phone: let numbers clip instead of forcing the page wider */
  .cx-spine { height: 60px; gap: 1px; }
  .cx-spine-day { overflow: hidden; }
  .cx-spine-num { font-size: 8px; }
  .cx-form-grid, .cx-feed-grid { grid-template-columns: 1fr; }
  /* Tight phones: shrink the header gaps + arrows so [Today] ‹ July › ＋ still fits
     one row without shoving the title off center. */
  .cx-masthead { padding: .8rem var(--pad-x) .85rem; }
  .cx-mast-row { gap: .35rem; }
  .cx-monthnav { gap: .3rem; }
  .cx-monthnav .cx-nav-arrow { width: 2rem; height: 2rem; font-size: 18px; }
  .cx-nav-today { padding: .38rem .55rem; }
  .cx-new { width: 2.3rem; height: 2.3rem; }
}
@media (prefers-reduced-motion: reduce) {
  .cx-spine-bar.has { animation: none; }
  .cx-eyebrow-dot { animation: none; }
  .cx-new { animation: none; }
  .cx-cell, .cx-new, .cx-new-plus { transition: none; }
}

/* =============================================================================
   Expenses — one-page money board
   -----------------------------------------------------------------------------
   The 5-way segmented toggle is gone: every lens (coming up, forecast +
   include-filters, breakdown, one-offs, money flow, all recurring) renders at
   once as a panel of one 3×2 grid. On desktop the section locks to the
   viewport bottom and each panel absorbs its own overflow; smaller screens
   fall back to a flowing 2- then 1-column stack with capped panel heights.
   Deliberately small type — density is the feature.
============================================================================= */

/* Compact KPI strip */
#portal-expenses .exp-kpis { grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr)); gap: .5rem; margin-bottom: .6rem; }
body[data-portal] #portal-expenses .kpi { padding: .45rem .7rem; }
body[data-portal] #portal-expenses .kpi-v { font-size: 1.12rem; }
body[data-portal] #portal-expenses .kpi-k { margin-top: .12rem; font-size: 9.5px; }
body[data-portal] #portal-expenses .kpi-sub { margin-top: .05rem; font-size: 10px; }

/* The board */
.exp-grid {
  display: grid; gap: .6rem;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr) minmax(0, 5fr);
  grid-template-rows: minmax(0, 1.08fr) minmax(0, 1fr);
  grid-template-areas: "coming forecast breakdown" "oneoffs routing recurring";
}
#p-coming    { grid-area: coming; }
#p-forecast  { grid-area: forecast; }
#p-breakdown { grid-area: breakdown; }
#p-oneoffs   { grid-area: oneoffs; }
#p-routing   { grid-area: routing; }
#p-recurring { grid-area: recurring; }

/* Desktop: the board IS the page — lock to the viewport, no page scroll. */
@media (min-width: 1101px) and (min-height: 620px) {
  body[data-portal] main > section#portal-expenses {
    height: calc(100dvh - var(--portal-chrome-h, 120px));
    display: flex; flex-direction: column; overflow: hidden;
    padding-bottom: .8rem;
  }
  #portal-expenses .exp-grid { flex: 1; min-height: 0; }
}
@media (max-width: 1100px) {
  .exp-grid { grid-template-columns: 1fr 1fr; grid-template-rows: none; grid-template-areas: none; }
  #portal-expenses .exp-panel { grid-area: auto; max-height: 30rem; }
}
@media (max-width: 720px) {
  .exp-grid { grid-template-columns: 1fr; }
}

.exp-panel {
  display: flex; flex-direction: column; min-height: 0; min-width: 0; overflow: hidden;
  border: 1px solid var(--hairline); border-radius: var(--radius-sm); background: var(--mat-1);
}
.exp-panel-h {
  flex: none; display: flex; align-items: baseline; gap: .6rem;
  padding: .48rem .7rem; border-bottom: 1px solid var(--hairline);
  font-family: var(--mono); font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em; color: var(--fg-dim);
}
.exp-panel-h i {
  font-style: normal; font-weight: 400; text-transform: none; letter-spacing: 0;
  color: var(--fg-mute); margin-left: auto; text-align: right; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.exp-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: .6rem .7rem; }
.exp-scroll::-webkit-scrollbar, #ov-month .ov-card::-webkit-scrollbar { width: 6px; }
.exp-scroll::-webkit-scrollbar-thumb, #ov-month .ov-card::-webkit-scrollbar-thumb { background: var(--border-hi); border-radius: 999px; }

/* Card/category chip-color toggle in the Coming-up header */
.exp-modes { display: inline-flex; margin-left: auto; border: 1px solid var(--hairline); border-radius: 7px; overflow: hidden; }
.exp-mode {
  font-family: var(--mono); font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em;
  padding: .2rem .5rem; border: none; background: transparent; color: var(--fg-mute); cursor: pointer;
}
.exp-mode.on { background: color-mix(in srgb, var(--portal) 14%, var(--bg-soft)); color: var(--portal-2); }

/* --- Coming up: stepper pinned, the month card scrolls -------------------- */
#ov-month { flex: 1; min-height: 0; display: flex; flex-direction: column; padding: .5rem .7rem .65rem; }
#ov-month .mnav { margin: 0 0 .45rem; gap: .45rem; }
#ov-month .mnav-arrow { width: 26px; height: 26px; font-size: 14px; border-radius: 8px; }
#ov-month .mnav-mid { gap: .05rem; }
#ov-month .mnav-title { font-size: .95rem; }
#ov-month .mnav-total { font-size: 10.5px; }
#ov-month .mnav-today { font-size: 10px; margin-top: 0; }
#ov-month .ov-card { flex: 1; min-height: 0; overflow-y: auto; }
#portal-expenses .ml-row { grid-template-columns: 4.6rem 1fr auto; gap: .5rem; padding: .36rem .6rem; }
#portal-expenses .ml-date b { font-size: 12px; }
#portal-expenses .ml-rel { font-size: 9.5px; }
#portal-expenses .ml-name { font-size: 12px; gap: .35rem; }
#portal-expenses .ml-amt { font-size: 12px; }
#portal-expenses .ml-sum { grid-template-columns: 4.6rem 1fr auto; gap: .5rem; padding: .45rem .6rem; }
#portal-expenses .ml-sum-month { font-size: 11.5px; }
#portal-expenses .ml-sum-total { font-size: 12.5px; }
#portal-expenses .sub-chip { font-size: 9px; }

/* --- Forecast: controls + chart pinned, the include-list scrolls ---------- */
#portal-expenses #fc-head {
  flex: none; display: flex; align-items: center; justify-content: space-between;
  gap: .8rem; flex-wrap: wrap; padding: .5rem .7rem 0;
}
#portal-expenses .fc-controls { gap: .6rem; }
#portal-expenses .fc-controls-l { font-size: 9.5px; }
#portal-expenses .fc-presets { padding: .15rem; gap: .15rem; border-radius: 9px; }
#portal-expenses .fc-preset { font-size: 10.5px; padding: .22rem .5rem; border-radius: 6px; }
#portal-expenses .fc-total { text-align: right; }
#portal-expenses .fc-total-v { font-size: 1.25rem; }
#portal-expenses .fc-total-k { font-size: 9.5px; }
#portal-expenses .fc-chart { flex: none; margin: .5rem .7rem; padding: .5rem; }
#p-forecast .exp-scroll { padding-top: 0; }
#portal-expenses .fc-cats { columns: 1; margin-top: 0; }
#portal-expenses .fc-cat { margin: .45rem 0; }
#portal-expenses .fc-cat-h { padding-bottom: .25rem; }
#portal-expenses .fc-item { grid-template-columns: 15px minmax(90px, 11rem) 1fr auto; gap: .5rem; padding: .16rem 0 .16rem .3rem; }
#portal-expenses .fc-item input { width: 13px; height: 13px; }
#portal-expenses .fc-name { font-size: 11.5px; }
#portal-expenses .fc-amt { font-size: 10.5px; }

/* --- Nested .break-card wrappers flatten inside panels -------------------- */
.exp-panel .break-card { border: none; background: transparent; padding: 0; border-radius: 0; }
.exp-panel .break-card + .break-card { margin-top: .8rem; padding-top: .7rem; border-top: 1px dashed var(--hairline); }
.exp-panel .break-head { margin-bottom: .45rem; font-size: 10px; }
#portal-expenses .bar-row { grid-template-columns: minmax(70px, 7.5rem) 1fr auto; gap: .5rem; margin: .3rem 0; }
#portal-expenses .bar-label { font-size: 11.5px; }
#portal-expenses .bar-val { font-size: 10.5px; }
#portal-expenses .bar-track { height: 6px; }

/* --- Money flow (sankey scales down; registry pills shrink) --------------- */
#portal-expenses .sk-wrap { margin-top: 0; padding: 0 0 .4rem; }
#portal-expenses .sk-svg { min-width: 460px; }
#portal-expenses .pm-manage { margin-top: .2rem; padding-top: .6rem; }
#portal-expenses .pm-pill { font-size: 10px; }

/* --- All recurring: single-column compact cards ---------------------------- */
#portal-expenses .sched-sec { margin-top: .9rem; }
#portal-expenses .sched-sec:first-child { margin-top: 0; }
#portal-expenses .sched-head { margin-bottom: .45rem; padding-bottom: .3rem; }
#portal-expenses .sched-head h4 { font-size: .85rem; }
#portal-expenses .sched-meta { font-size: 10px; }
#portal-expenses .sub-list { grid-template-columns: 1fr; gap: .4rem; }
#portal-expenses .sub-card { padding: .5rem .65rem; }
#portal-expenses .sub-name { font-size: 12.5px; }
#portal-expenses .sub-amt { font-size: 11.5px; }
#portal-expenses .sub-meta { margin-top: .3rem; gap: .35rem; }
#portal-expenses .iv-badge { font-size: 8.5px; }
#portal-expenses .sub-next { font-size: 9.5px; }
#portal-expenses .sub-sched { font-size: 9.5px; margin-top: .35rem; }
#portal-expenses .rto-flow { margin-top: .45rem; gap: .5rem; }

/* --- One-offs ledger compacted --------------------------------------------- */
#portal-expenses .crud-add { font-size: 11.5px; padding: .35rem .7rem; }
#portal-expenses .crud-list { gap: .45rem; }
#portal-expenses .crud-card { padding: .55rem .7rem; }
#portal-expenses .exp-name { font-size: 12.5px; }
#portal-expenses .exp-amt { font-size: 12px; }
#portal-expenses .exp-meta { font-size: 10.5px; margin-top: .25rem; gap: .4rem; }
#portal-expenses .exp-kind { font-size: 9px; }

/* === YouTube module (portal-youtube.html) — YOUTUBE-SCRAPER-BRIEF §10 ====== */
#portal-youtube { --yt: #dc2626; }
:root[data-theme="dark"] #portal-youtube { --yt: #f87171; }
#portal-youtube .ws-stat.yt-err .ws-stat-n { color: var(--yt); }
.yt-empty { color: var(--fg-mute); font-size: 13px; padding: .9rem 0; }

/* --- Videos: the thumbnail catalog (the mini knowledge browser) ------------ */
.yt-videos {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(15.5rem, 1fr));
  gap: .9rem; margin-top: 1rem;
}
.yt-v-card {
  display: flex; flex-direction: column; gap: .35rem; text-decoration: none;
  color: var(--fg); border: 1px solid var(--hairline); border-radius: 12px;
  background: var(--bg-soft); padding: .55rem .55rem .7rem;
  transition: border-color .12s, transform .12s;
}
.yt-v-card:hover { border-color: var(--yt); transform: translateY(-1px); }
.yt-v-thumbwrap {
  position: relative; display: block; aspect-ratio: 16 / 9;
  border-radius: 8px; overflow: hidden; background: var(--bg);
}
.yt-v-thumb { width: 100%; height: 100%; object-fit: cover; display: block; }
.yt-v-dur {
  position: absolute; right: 6px; bottom: 6px; font-family: var(--mono);
  font-size: 10px; font-weight: 700; color: #fff; background: rgba(0,0,0,.75);
  border-radius: 5px; padding: .08rem .35rem;
}
.yt-v-title {
  font-size: 13px; font-weight: 700; line-height: 1.3; padding: 0 .2rem;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.yt-v-meta {
  display: flex; gap: .55rem; flex-wrap: wrap; padding: 0 .2rem;
  font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute);
}
.yt-v-meta .yt-v-ch { color: var(--yt); font-weight: 600; }
.yt-v-counts { font-family: var(--mono); font-size: 10px; color: var(--fg-dim); padding: 0 .2rem; }
.yt-v-tags { display: flex; gap: .3rem; flex-wrap: wrap; padding: 0 .2rem; }
.yt-v-tags span {
  font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute);
  border: 1px solid var(--hairline); border-radius: 999px; padding: .06rem .45rem;
}
.yt-enqueue-row { display: flex; gap: .6rem; margin: 1rem 0 1.2rem; max-width: 44rem; }
.yt-enqueue-row input {
  flex: 1 1 auto; font: inherit; font-size: 13.5px; padding: .55rem .75rem;
  border-radius: 10px; border: 1px solid var(--hairline);
  background: var(--bg); color: var(--fg);
}
.yt-enqueue-row input:focus { outline: none; border-color: var(--yt); }
#yt-bulk-toggle.on { border-color: var(--yt); color: var(--yt); }
/* Bulk intake: paste a whole block; every YouTube link in it gets queued. */
.yt-bulk { max-width: 44rem; margin: -.4rem 0 1.2rem; }
.yt-bulk textarea {
  width: 100%; min-height: 7.5rem; font: inherit; font-size: 13px;
  font-family: var(--mono); line-height: 1.6; padding: .6rem .75rem;
  border-radius: 10px; border: 1px solid var(--hairline);
  background: var(--bg); color: var(--fg); resize: vertical;
}
.yt-bulk textarea:focus { outline: none; border-color: var(--yt); }
.yt-bulk-foot { display: flex; align-items: center; gap: .6rem; margin-top: .45rem; }
.yt-queue { display: flex; flex-direction: column; gap: .45rem; }
.yt-q-row {
  display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
  border: 1px solid var(--hairline); border-radius: 11px;
  background: var(--bg-soft); padding: .55rem .8rem; font-size: 12.5px;
}
.yt-q-status {
  font-family: var(--mono); font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .07em;
  border-radius: 999px; padding: .14rem .55rem; flex: none;
  border: 1px solid var(--hairline); color: var(--fg-mute);
}
.yt-q-row.st-pending .yt-q-status    { color: #d97706; border-color: #d97706; }
.yt-q-row.st-processing .yt-q-status { color: #0891b2; border-color: #0891b2; }
.yt-q-row.st-done .yt-q-status       { color: #059669; border-color: #059669; }
.yt-q-row.st-error .yt-q-status      { color: var(--yt); border-color: var(--yt); }
.yt-q-thumb {
  width: 52px; aspect-ratio: 16 / 9; object-fit: cover; border-radius: 6px;
  flex: none; background: var(--bg); display: block;
}
.yt-q-vid { font-family: var(--mono); font-size: 11.5px; color: var(--fg-dim); flex: none; }
.yt-q-url {
  color: var(--fg-dim); text-decoration: none; max-width: 26rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.yt-q-url:hover { color: var(--fg); text-decoration: underline; }
.yt-q-when { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); margin-left: auto; }
.yt-q-open { font-size: 12px; font-weight: 600; color: var(--portal-2); text-decoration: none; }
.yt-q-open:hover { text-decoration: underline; }
.yt-q-error { flex-basis: 100%; color: var(--yt); font-family: var(--mono); font-size: 11px; }

.yt-profiles {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: .7rem; margin-top: 1rem;
}
.yt-p-card {
  text-align: left; cursor: pointer; border: 1px solid var(--hairline);
  border-radius: 12px; background: var(--bg-soft); padding: .75rem .9rem;
  display: flex; flex-direction: column; gap: .3rem; color: var(--fg);
  transition: border-color .12s, transform .12s;
}
.yt-p-card:hover { border-color: var(--yt); transform: translateY(-1px); }
.yt-p-kind {
  align-self: flex-start; font-family: var(--mono); font-size: 9.5px;
  font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
  border-radius: 999px; padding: .12rem .5rem; border: 1px solid var(--hairline);
  color: var(--fg-mute);
}
.yt-p-kind.k-creator   { color: var(--yt); border-color: var(--yt); }
.yt-p-kind.k-cohost    { color: #d97706; border-color: #d97706; }
.yt-p-kind.k-commenter { color: #0891b2; border-color: #0891b2; }
.yt-p-name { font-weight: 800; font-size: 14.5px; letter-spacing: -.01em; }
.yt-p-handle { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); }
.yt-p-counts { font-family: var(--mono); font-size: 10.5px; color: var(--fg-dim); }

/* --- Avatars: the creator's face (channels.data.avatar) or a monogram ------ */
.yt-avatar {
  position: relative; flex: none; display: inline-flex; align-items: center;
  justify-content: center; width: 40px; height: 40px; border-radius: 50%;
  overflow: hidden; background: hsl(var(--ah, 220), 42%, 46%); color: #fff;
  font-weight: 800; line-height: 1; user-select: none;
}
.yt-avatar-mono { font-size: .8em; }
.yt-avatar-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* --- Creators: the primary surface — photo-led cards ----------------------- */
.yt-creators { grid-template-columns: repeat(auto-fill, minmax(16.5rem, 1fr)); }
.yt-creator-card { flex-direction: row; align-items: center; gap: .75rem; padding: .8rem .9rem; }
.yt-creator-avatar { width: 52px; height: 52px; font-size: 19px; }
.yt-creator-card:hover .yt-creator-avatar { box-shadow: 0 0 0 2px var(--yt); }
.yt-creator-body { display: flex; flex-direction: column; gap: .18rem; min-width: 0; }
.yt-creator-body .yt-p-name {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* --- People who've commented: lighter, denser ------------------------------ */
.yt-commenters { grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr)); gap: .5rem; }
.yt-commenter-card { flex-direction: row; align-items: center; gap: .6rem; padding: .55rem .7rem; }
.yt-commenter-avatar { width: 34px; height: 34px; font-size: 13px; }
.yt-commenter-card .yt-p-name { font-size: 13px; }
.yt-commenter-card .yt-p-counts { font-size: 10px; }

/* AI-summary one-liner on a video card (youtube_summary.py). */
.yt-v-summary {
  font-size: 11.5px; line-height: 1.42; color: var(--fg-dim); padding: 0 .2rem;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
#yt-summ-backfill { font-size: 11px; padding: .25rem .6rem; }

.yt-profile-detail {
  margin-top: 1.2rem; border: 1px solid var(--hairline); border-radius: 14px;
  background: var(--bg-soft); padding: 1rem 1.2rem 1.2rem;
}
.yt-pd-head { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; }
.yt-pd-avatar { width: 48px; height: 48px; font-size: 18px; }
.yt-pd-headtext { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.yt-pd-head h3 { margin: 0; font-size: 1.15rem; font-weight: 800; letter-spacing: -.02em; }
/* Dossier vitals: the catalog of work is the credibility signal. */
.yt-pd-stats {
  display: flex; gap: 1.2rem; flex-wrap: wrap; margin-top: .8rem;
  padding: .6rem .8rem; border: 1px solid var(--hairline); border-radius: 10px;
  background: var(--bg);
}
.yt-pd-stat { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); display: flex; flex-direction: column; gap: .1rem; }
.yt-pd-stat b { font-size: 13.5px; color: var(--fg); font-weight: 700; }
/* "Your read" — Ryder's own credibility text, edited in place. */
.yt-pd-read { display: flex; flex-direction: column; align-items: flex-start; gap: .5rem; }
.yt-pd-read-text { font-size: 13.5px; line-height: 1.6; white-space: pre-wrap; max-width: 62ch; }
.yt-pd-read-text.empty { color: var(--fg-mute); font-style: italic; }
.yt-pd-read-input {
  width: 100%; max-width: 44rem; min-height: 6.5rem; font: inherit; font-size: 13.5px;
  padding: .6rem .75rem; border-radius: 10px; border: 1px solid var(--hairline);
  background: var(--bg); color: var(--fg); resize: vertical;
}
.yt-pd-read-input:focus { outline: none; border-color: var(--yt); }
.yt-pd-read-actions { display: flex; gap: .5rem; }
.yt-pd-videos { margin-top: .3rem; }
.yt-pd-eng { color: var(--yt); font-weight: 700; }
.yt-pd-close {
  margin-left: auto; border: 0; background: transparent; color: var(--fg-mute);
  font-size: 20px; line-height: 1; cursor: pointer; padding: 0 .2rem;
}
.yt-pd-close:hover { color: var(--fg); }
.yt-pd-block { margin-top: 1.1rem; }
.yt-pd-block h4 {
  margin: 0 0 .5rem; font-size: 11px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; color: var(--fg-mute);
}
.yt-pd-row {
  display: flex; align-items: center; gap: .6rem; flex-wrap: wrap;
  padding: .35rem 0; border-bottom: 1px dashed var(--hairline); font-size: 13px;
}
.yt-pd-thumb {
  width: 64px; aspect-ratio: 16 / 9; object-fit: cover; border-radius: 6px;
  flex: none; background: var(--bg); display: block;
}
.yt-pd-row:last-child { border-bottom: 0; }
.yt-pd-row a { color: var(--fg); text-decoration: none; }
.yt-pd-row a:hover { text-decoration: underline; }
.yt-pd-row span { color: var(--fg-mute); font-size: 12px; }
.yt-pd-role, .yt-pd-ck { font-family: var(--mono); font-size: 10px !important; text-transform: uppercase; letter-spacing: .06em; }
.yt-pd-comment { padding: .45rem 0; border-bottom: 1px dashed var(--hairline); }
.yt-pd-comment:last-child { border-bottom: 0; }
.yt-pd-comment .t { font-size: 13px; }
.yt-pd-comment .m { font-size: 11.5px; color: var(--fg-mute); margin-top: .2rem; }
.yt-pd-comment .m a { color: var(--portal-2); text-decoration: none; }
.yt-pd-comment .m a:hover { text-decoration: underline; }

/* =============================================================================
   Weed Buddy module (portal-weed.*)
   -----------------------------------------------------------------------------
   Taste-corpus geometry throughout: r2 corners, generous shell (12–13px) over
   tight interiors, control clusters pad 9 / gap 7, small-caps quiet labels,
   accent carries STATE (selected row spine/ground), numeric emphasis second.
   Chart color is computed, not eyeballed: terpene profile = single-hue
   magnitude (the portal accent); affinity = validated diverging pair
   (light #2171cc/#d97706, dark #4f92ea/#bd8a18 — dark gets its own steps),
   every bar direct-labeled so polarity is never color-alone.
============================================================================= */
#portal-weed { --wb-pos: #2171cc; --wb-neg: #d97706; }
:root[data-theme="dark"] #portal-weed { --wb-pos: #4f92ea; --wb-neg: #bd8a18; }

/* --- shells ---------------------------------------------------------------- */
.wb-work { display: grid; grid-template-columns: 330px 1fr; gap: 14px; align-items: start; margin-top: 14px; }
.wb-side { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.wb-main { min-width: 0; }
.wb-box { border: 1px solid var(--hairline); border-radius: 2px; background: var(--bg-soft); padding: 12px 13px; }
.wb-box-head, .wb-tbox-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 4px; }
.wb-box-head h3, .wb-tbox-head h3 {
  margin: 0; font-family: var(--mono); font-size: 11px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--fg-dim);
}
.wb-box-head .hint, .wb-tbox-head .hint { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); }
.wb-blk-lbl {
  display: block; font-family: var(--mono); font-size: 10px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--fg-mute); margin: 12px 0 4px;
}
.wb-ghost-line { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); opacity: .7; padding: 6px 0; }

/* --- tendencies band -------------------------------------------------------- */
.wb-tend { margin-top: 4px; }
.wb-stats { display: flex; border: 1px solid var(--hairline); border-radius: 2px; background: var(--bg-soft); overflow: hidden; }
.wb-stat { flex: 1; min-width: 0; padding: 9px 13px 8px; border-left: 1px solid var(--hairline); display: flex; flex-direction: column; gap: 2px; }
.wb-stat:first-child { border-left: 0; }
.wb-stat-v { font-family: var(--mono); font-size: 17px; font-weight: 700; color: var(--fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wb-stat-name .wb-stat-v { font-family: inherit; font-size: 14.5px; letter-spacing: -.01em; }
.wb-stat-k { font-family: var(--mono); font-size: 9.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--fg-mute); }
.wb-tend-grid { display: grid; grid-template-columns: 1.4fr 1fr; gap: 14px; margin-top: 14px; }
.wb-tbox { border: 1px solid var(--hairline); border-radius: 2px; background: var(--bg-soft); padding: 12px 13px; }

/* affinity — diverging around a center origin; ghost rows show the shape */
.wb-aff { margin-top: 4px; }
.wb-aff-row { display: grid; grid-template-columns: 108px 1fr 62px; gap: 8px; align-items: center; padding: 3px 0; }
.wb-aff-row.ghost { opacity: .42; }
.wb-aff-lbl { font-size: 11px; color: var(--fg-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wb-aff-track { position: relative; height: 10px; }
.wb-aff-mid { position: absolute; left: 50%; top: 0; bottom: 0; width: 1px; background: color-mix(in srgb, var(--fg) 18%, transparent); }
.wb-aff-bar { position: absolute; top: 2px; height: 6px; border-radius: 2px; }
.wb-aff-bar.pos { background: var(--wb-pos); }
.wb-aff-bar.neg { background: var(--wb-neg); }
.wb-aff-val { font-family: var(--mono); font-size: 10.5px; color: var(--fg-dim); text-align: right; }

/* type + method */
.wb-typerows { margin-top: 2px; }
.wb-typerow { display: flex; align-items: center; gap: 8px; padding: 5px 0; border-top: 1px solid var(--hairline); }
.wb-typerow:first-child { border-top: 0; }
.wb-typerow.ghost { opacity: .42; }
.wb-type-avg { font-family: var(--mono); font-size: 13px; font-weight: 700; margin-left: auto; }
.wb-type-lift { font-family: var(--mono); font-size: 10.5px; width: 44px; text-align: right; }
.wb-type-lift.pos { color: var(--wb-pos); }
.wb-type-lift.neg { color: var(--wb-neg); }
.wb-type-n { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); width: 78px; text-align: right; }
.wb-methods { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 10px; }
.wb-mchip { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--hairline); border-radius: 2px; padding: 2px 7px; font-size: 11px; }
.wb-mchip b { font-weight: 600; }
.wb-mcount { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); }

/* --- tags (square r2, role-tiered: type carries a tone, always with text) --- */
.wb-tag {
  font-family: var(--mono); font-size: 9.5px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; padding: 1px 6px; border-radius: 2px; flex: none;
  color: var(--fg-mute); border: 1px solid var(--hairline);
}
.wb-tag.tone-violet { color: var(--tone-violet); border-color: color-mix(in srgb, var(--tone-violet) 40%, transparent); background: color-mix(in srgb, var(--tone-violet) 8%, transparent); }
.wb-tag.tone-amber  { color: var(--tone-amber);  border-color: color-mix(in srgb, var(--tone-amber) 40%, transparent);  background: color-mix(in srgb, var(--tone-amber) 8%, transparent); }
.wb-tag.tone-cyan   { color: var(--tone-cyan);   border-color: color-mix(in srgb, var(--tone-cyan) 40%, transparent);   background: color-mix(in srgb, var(--tone-cyan) 8%, transparent); }

/* --- controls (cluster pad 9 / gap 7; filled-well inputs; ground-tint focus) - */
.wb-controls { display: flex; gap: 7px; margin: 9px 0; }
.wb-search {
  flex: 1; min-width: 0; border: 1px solid var(--hairline); border-radius: 2px;
  background: color-mix(in srgb, var(--fg) 5%, transparent); color: var(--fg);
  padding: 4px 8px; font-size: 12px; outline: none;
}
.wb-search:focus { background: color-mix(in srgb, var(--portal) 10%, transparent); }
.wb-seg { display: flex; border: 1px solid var(--hairline); border-radius: 2px; overflow: hidden; flex: none; }
.wb-seg-btn {
  background: none; border: 0; border-left: 1px solid var(--hairline); cursor: pointer;
  font-family: var(--mono); font-size: 10px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--fg-mute); padding: 4px 8px;
}
.wb-seg-btn:first-child { border-left: 0; }
.wb-seg-btn:hover { color: var(--fg); background: color-mix(in srgb, var(--fg) 5%, transparent); }
.wb-seg-btn.on { color: var(--portal); background: color-mix(in srgb, var(--portal) 12%, transparent); }

.wb-add, .wb-mini {
  margin-left: auto; border: 0; border-radius: 2px; cursor: pointer;
  background: color-mix(in srgb, var(--portal) 12%, transparent); color: var(--portal);
  font-family: var(--mono); font-size: 10.5px; font-weight: 700; padding: 3px 8px; flex: none;
}
.wb-mini { margin-left: 0; }
.wb-add:hover, .wb-mini:hover { background: color-mix(in srgb, var(--portal) 20%, transparent); }
.wb-mini.danger { background: color-mix(in srgb, var(--fg) 6%, transparent); color: var(--fg-mute); }
.wb-mini.danger:hover { color: var(--fg-dim); background: color-mix(in srgb, var(--fg) 10%, transparent); }
.wb-mini.armed { color: var(--tone-amber); background: color-mix(in srgb, var(--tone-amber) 12%, transparent); }

/* --- list rows (dense; selected = accent spine + ground: accent carries state) */
.wb-list { display: flex; flex-direction: column; }
.wb-row {
  position: relative; display: flex; align-items: center; gap: 8px;
  padding: 5px 6px 5px 9px; border-top: 1px solid var(--hairline); cursor: pointer;
}
.wb-row:first-child { border-top: 0; }
.wb-row:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.wb-row.on { background: color-mix(in srgb, var(--portal) 8%, transparent); }
.wb-row.on::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--portal); }
.wb-row-txt { display: flex; flex-direction: column; min-width: 0; flex: 1; gap: 0; }
.wb-row-name { font-size: 12.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wb-row-sub { font-size: 10.5px; color: var(--fg-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wb-row-nums { display: flex; flex-direction: column; align-items: flex-end; flex: none; gap: 0; }
.wb-row-thc { font-family: var(--mono); font-size: 10.5px; color: var(--fg-dim); }
.wb-row-rate { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); }
.wb-row-rate.rated { color: var(--portal); font-weight: 700; }
.wb-row-count { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); flex: none; }

/* --- detail ------------------------------------------------------------------ */
.wb-det-head { display: flex; align-items: center; gap: 10px; }
.wb-det-title { display: flex; align-items: center; gap: 8px; min-width: 0; }
.wb-det-title h3 { margin: 0; font-size: 17px; font-weight: 800; letter-spacing: -.02em; }
.wb-det-head .wb-mini { margin-left: auto; }
.wb-det-sub { font-size: 11.5px; color: var(--fg-mute); margin-top: 2px; }
.wb-det-nums { display: flex; border: 1px solid var(--hairline); border-radius: 2px; margin-top: 10px; overflow: hidden; }
.wb-num { flex: 1; padding: 7px 11px 6px; border-left: 1px solid var(--hairline); display: flex; flex-direction: column; gap: 1px; }
.wb-num:first-child { border-left: 0; }
.wb-num-v { font-family: var(--mono); font-size: 15px; font-weight: 700; }
.wb-num-k { font-family: var(--mono); font-size: 9.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--fg-mute); }

/* terpene profile — thin single-hue magnitude bars, fixed 1.0% scale */
.wb-terps { margin-top: 12px; }
.wb-terp-row { display: grid; grid-template-columns: 108px 1fr 52px; gap: 8px; align-items: center; padding: 3px 0; }
.wb-terp-lbl { font-size: 11px; color: var(--fg-dim); }
.wb-terp-track { height: 8px; border-radius: 2px; background: color-mix(in srgb, var(--fg) 7%, transparent); overflow: hidden; }
.wb-terp-bar { display: block; height: 100%; border-radius: 2px; background: var(--portal); }
.wb-terp-val { font-family: var(--mono); font-size: 10.5px; color: var(--fg-dim); text-align: right; }

.wb-det-effects { font-size: 12.5px; color: var(--fg-dim); line-height: 1.55; margin: 12px 0 0; }
.wb-market { font-size: 11.5px; color: var(--fg-mute); line-height: 1.5; margin: 8px 0 0; }

/* notes — inline click-to-edit; the ✎ affordance reveals on hover */
.wb-notes {
  position: relative; margin-top: 12px; padding: 7px 26px 7px 10px; border-radius: 2px;
  background: color-mix(in srgb, var(--fg) 4%, transparent); cursor: text; font-size: 12px;
}
.wb-notes-lbl { font-family: var(--mono); font-size: 9.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--fg-mute); display: block; margin-bottom: 2px; }
.wb-notes-body { white-space: pre-wrap; color: var(--fg-dim); }
.wb-notes.empty .wb-notes-body { color: var(--fg-mute); }
.wb-notes-pen { position: absolute; right: 8px; top: 7px; font-size: 11px; color: var(--fg-mute); opacity: 0; transition: opacity .15s; }
.wb-notes:hover .wb-notes-pen { opacity: 1; }
.wb-notes-edit {
  width: 100%; border: 1px solid var(--hairline); border-radius: 2px; outline: none;
  background: color-mix(in srgb, var(--portal) 8%, transparent); color: var(--fg);
  font: inherit; font-size: 12px; padding: 4px 6px; resize: vertical;
}

/* stores — chips; researched (potential) wears the provisional dashed boundary */
.wb-stores { margin-top: 2px; }
.wb-store-chips { display: flex; flex-wrap: wrap; gap: 7px; align-items: center; }
.wb-store-chip {
  display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--hairline);
  border-radius: 2px; padding: 3px 8px; font-size: 11.5px; background: var(--bg-soft);
}
.wb-store-chip b { font-weight: 600; }
.wb-store-chip.potential { border-style: dashed; }
.wb-store-chip i { font-family: var(--mono); font-style: normal; font-size: 9px; letter-spacing: .05em; text-transform: uppercase; color: var(--fg-mute); }
.wb-strain-chip { cursor: pointer; }
.wb-strain-chip:hover { background: color-mix(in srgb, var(--portal) 8%, transparent); }
.wb-chip-num { font-family: var(--mono); font-size: 10px; color: var(--portal); font-weight: 700; }
.wb-chip-x { border: 0; background: none; cursor: pointer; color: var(--fg-mute); font-size: 12px; padding: 0 1px; line-height: 1; }
.wb-chip-x:hover, .wb-chip-x.armed { color: var(--tone-amber); }
.wb-store-add { position: relative; display: inline-flex; align-items: center; gap: 7px; }
.wb-store-input {
  border: 1px solid var(--hairline); border-radius: 2px; outline: none; width: 150px;
  background: color-mix(in srgb, var(--fg) 5%, transparent); color: var(--fg);
  padding: 3px 7px; font-size: 11.5px;
}
.wb-store-input:focus { background: color-mix(in srgb, var(--portal) 10%, transparent); }
.wb-store-menu {
  position: absolute; left: 0; top: calc(100% + 4px); z-index: 30; min-width: 220px;
  background: var(--bg-elev, var(--bg-soft)); border: 1px solid var(--hairline); border-radius: 2px;
  box-shadow: 0 8px 12px -4px rgba(0,0,0,.2); display: flex; flex-direction: column;
}
.wb-store-menu:empty { display: none; }
.wb-store-item {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  border: 0; background: none; cursor: pointer; text-align: left;
  padding: 5px 9px; font-size: 12px; color: var(--fg);
}
.wb-store-item:hover { background: color-mix(in srgb, var(--portal) 10%, transparent); }
.wb-store-item b { font-weight: 600; }
.wb-store-item span { font-family: var(--mono); font-size: 9px; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-mute); }

/* session log — dense rows; actions reveal on hover */
.wb-blk-head { display: flex; align-items: center; gap: 8px; }
.wb-blk-head .wb-blk-lbl { flex: 1; }
.wb-blk-head .wb-mini { margin-top: 10px; }
.wb-review-list { display: flex; flex-direction: column; }
.wb-review-row { display: grid; grid-template-columns: 78px 36px 1fr auto; gap: 10px; align-items: start; padding: 7px 2px; border-top: 1px solid var(--hairline); }
.wb-review-row:first-child { border-top: 0; }
.wb-review-row.ghost { opacity: .42; }
.wb-rev-date { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); padding-top: 2px; }
.wb-rev-rating { font-family: var(--mono); font-size: 15px; font-weight: 700; color: var(--portal); }
.wb-rev-rating.unrated { color: var(--fg-mute); }
.wb-rev-body { min-width: 0; font-size: 12px; }
.wb-rev-meta { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; color: var(--fg-dim); font-size: 11.5px; }
.wb-rev-place { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }
.wb-rev-effects { margin-top: 2px; color: var(--fg-dim); }
.wb-rev-notes { margin-top: 2px; color: var(--fg-mute); font-size: 11.5px; white-space: pre-wrap; }
.wb-rev-acts { display: flex; gap: 6px; opacity: 0; transition: opacity .15s; }
.wb-review-row:hover .wb-rev-acts { opacity: 1; }

/* forms — cluster pad 9 / gap 7; filled wells; ground-tint focus */
.wb-form { margin-top: 9px; padding: 9px; border: 1px solid var(--hairline); border-radius: 2px; background: color-mix(in srgb, var(--fg) 3%, transparent); }
.wb-form-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 7px; }
.wb-terp-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; }
.wb-field { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.wb-field.full { grid-column: 1 / -1; }
.wb-field-lbl { font-family: var(--mono); font-size: 9.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--fg-mute); }
.wb-field input, .wb-field select, .wb-field textarea {
  border: 1px solid var(--hairline); border-radius: 2px; outline: none;
  background: color-mix(in srgb, var(--fg) 5%, transparent); color: var(--fg);
  padding: 4px 7px; font-size: 12px; font-family: inherit; min-width: 0;
}
.wb-field input:focus, .wb-field select:focus, .wb-field textarea:focus { background: color-mix(in srgb, var(--portal) 10%, transparent); }
.wb-field textarea { resize: vertical; }
.wb-form-acts { display: flex; align-items: center; gap: 7px; margin-top: 9px; }
.wb-form-acts .btn { padding: .32rem .8rem; font-size: 12px; }
.wb-form-spacer { flex: 1; }
.wb-review-form { margin-bottom: 4px; }

@media (max-width: 980px) {
  .wb-work { grid-template-columns: 1fr; }
  .wb-tend-grid { grid-template-columns: 1fr; }
  .wb-stats { flex-wrap: wrap; }
  .wb-stat { min-width: 130px; }
}

/* --- Weed Buddy: genetics (family tree) ------------------------------------ */
.wb-gen { margin-top: 14px; }
.wb-gen-comp { position: relative; padding: 10px 2px 6px; overflow-x: auto; }
.wb-gen-comp + .wb-gen-comp { border-top: 1px solid var(--hairline); }
.wb-gen-comp.ghost { opacity: .42; }
.wb-gen-svg { position: absolute; inset: 0; pointer-events: none; }
.wb-gen-edge { fill: none; stroke: color-mix(in srgb, var(--fg) 26%, transparent); stroke-width: 1.25; }
.wb-gen-cols { position: relative; display: flex; gap: 46px; align-items: center; width: max-content; }
.wb-gen-col { display: flex; flex-direction: column; gap: 9px; }
.wb-gen-node {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  border: 1px solid color-mix(in srgb, var(--fg) 22%, transparent); border-radius: 2px;
  background: var(--bg-soft); color: var(--fg); text-align: left;
  padding: 3px 9px; font-size: 11.5px; white-space: nowrap;
}
.wb-gen-node b { font-weight: 600; }
.wb-gen-node:hover { background: color-mix(in srgb, var(--portal) 10%, transparent); border-color: color-mix(in srgb, var(--portal) 45%, transparent); }
.wb-gen-node.ghostnode { border-style: dashed; color: var(--fg-dim); }
.wb-gen-loose { margin-top: 10px; }
.wb-gen-loose .wb-blk-lbl { margin-top: 0; }

/* kin line on the strain detail (parents ↑ / offspring ↓) */
.wb-kin { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
.wb-kin-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.wb-kin-lbl { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); width: 12px; }
.wb-kin-chip {
  border: 1px solid var(--hairline); border-radius: 2px; background: var(--bg-soft);
  color: var(--fg-dim); cursor: pointer; padding: 1px 7px; font-size: 11px;
}
.wb-kin-chip:hover { background: color-mix(in srgb, var(--portal) 10%, transparent); color: var(--fg); }
.wb-kin-chip.ghostnode { border-style: dashed; color: var(--fg-mute); }

/* =============================================================================
   Film module (portal-film.*)
   -----------------------------------------------------------------------------
   Same taste-corpus geometry as Weed Buddy: r2 corners, generous shell
   (12–13px) over tight interiors, control clusters pad 9 / gap 7, small-caps
   quiet labels, accent carries STATE (selected row spine/ground, rated
   numerals), structure stays neutral graphite. The connector chips are
   control surfaces — the categorization grammar the whole page walks on.
============================================================================= */

/* --- shells ---------------------------------------------------------------- */
.fm-work { display: grid; grid-template-columns: 330px 1fr; gap: 14px; align-items: start; margin-top: 14px; }
.fm-side { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.fm-main { min-width: 0; }
.fm-box { border: 1px solid var(--hairline); border-radius: 2px; background: var(--bg-soft); padding: 12px 13px; }
.fm-box-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 4px; }
.fm-box-head h3 {
  margin: 0; font-family: var(--mono); font-size: 11px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--fg-dim);
}
.fm-box-head .hint { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); }
.fm-blk-lbl {
  display: block; font-family: var(--mono); font-size: 10px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--fg-mute); margin: 12px 0 4px;
}
.fm-ghost-line { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); opacity: .7; padding: 6px 0; }

/* --- stat strip -------------------------------------------------------------- */
.fm-stats { display: flex; border: 1px solid var(--hairline); border-radius: 2px; background: var(--bg-soft); overflow: hidden; margin-top: 4px; }
.fm-stat { flex: 1; min-width: 0; padding: 9px 13px 8px; border-left: 1px solid var(--hairline); display: flex; flex-direction: column; gap: 2px; }
.fm-stat:first-child { border-left: 0; }
.fm-stat-v { font-family: var(--mono); font-size: 17px; font-weight: 700; color: var(--fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fm-stat-name .fm-stat-v { font-family: inherit; font-size: 14.5px; letter-spacing: -.01em; }
.fm-stat-k { font-family: var(--mono); font-size: 9.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--fg-mute); }

/* --- tags (square r2, role-tiered: format carries a tone, always with text) - */
.fm-tag {
  font-family: var(--mono); font-size: 9.5px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; padding: 1px 6px; border-radius: 2px; flex: none;
  color: var(--fg-mute); border: 1px solid var(--hairline);
}
.fm-tag.tone-violet { color: var(--tone-violet); border-color: color-mix(in srgb, var(--tone-violet) 40%, transparent); background: color-mix(in srgb, var(--tone-violet) 8%, transparent); }
.fm-tag.tone-amber  { color: var(--tone-amber);  border-color: color-mix(in srgb, var(--tone-amber) 40%, transparent);  background: color-mix(in srgb, var(--tone-amber) 8%, transparent); }
.fm-tag.tone-cyan   { color: var(--tone-cyan);   border-color: color-mix(in srgb, var(--tone-cyan) 40%, transparent);   background: color-mix(in srgb, var(--tone-cyan) 8%, transparent); }

/* --- controls (cluster pad 9 / gap 7; filled-well inputs; ground-tint focus) - */
.fm-controls { display: flex; gap: 7px; margin: 9px 0; flex-wrap: wrap; }
.fm-search {
  flex: 1; min-width: 0; border: 1px solid var(--hairline); border-radius: 2px;
  background: color-mix(in srgb, var(--fg) 5%, transparent); color: var(--fg);
  padding: 4px 8px; font-size: 12px; outline: none;
}
.fm-search:focus { background: color-mix(in srgb, var(--portal) 10%, transparent); }
.fm-seg { display: flex; border: 1px solid var(--hairline); border-radius: 2px; overflow: hidden; flex: none; }
.fm-seg-btn {
  background: none; border: 0; border-left: 1px solid var(--hairline); cursor: pointer;
  font-family: var(--mono); font-size: 10px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--fg-mute); padding: 4px 8px;
}
.fm-seg-btn:first-child { border-left: 0; }
.fm-seg-btn:hover { color: var(--fg); background: color-mix(in srgb, var(--fg) 5%, transparent); }
.fm-seg-btn.on { color: var(--portal); background: color-mix(in srgb, var(--portal) 12%, transparent); }

.fm-add, .fm-mini {
  margin-left: auto; border: 0; border-radius: 2px; cursor: pointer;
  background: color-mix(in srgb, var(--portal) 12%, transparent); color: var(--portal);
  font-family: var(--mono); font-size: 10.5px; font-weight: 700; padding: 3px 8px; flex: none;
}
.fm-mini { margin-left: 0; }
.fm-add:hover, .fm-mini:hover { background: color-mix(in srgb, var(--portal) 20%, transparent); }
.fm-mini.danger { background: color-mix(in srgb, var(--fg) 6%, transparent); color: var(--fg-mute); }
.fm-mini.danger:hover { color: var(--fg-dim); background: color-mix(in srgb, var(--fg) 10%, transparent); }
.fm-mini.armed { color: var(--tone-amber); background: color-mix(in srgb, var(--tone-amber) 12%, transparent); }

/* --- list rows (dense; selected = accent spine + ground: accent carries state) */
.fm-list { display: flex; flex-direction: column; }
.fm-row {
  position: relative; display: flex; align-items: center; gap: 8px;
  padding: 5px 6px 5px 9px; border-top: 1px solid var(--hairline); cursor: pointer;
}
.fm-row:first-child { border-top: 0; }
.fm-row:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.fm-row.on { background: color-mix(in srgb, var(--portal) 8%, transparent); }
.fm-row.on::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--portal); }
.fm-row-txt { display: flex; flex-direction: column; min-width: 0; flex: 1; gap: 0; }
.fm-row-name { font-size: 12.5px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fm-row-sub { font-size: 10.5px; color: var(--fg-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fm-row-rate { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); flex: none; }
.fm-row-rate.rated { color: var(--portal); font-weight: 700; }
.fm-row-count { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); flex: none; }

/* --- detail ------------------------------------------------------------------ */
.fm-det-head { display: flex; align-items: center; gap: 10px; }
.fm-det-title { display: flex; align-items: center; gap: 8px; min-width: 0; }
.fm-det-title h3 { margin: 0; font-size: 17px; font-weight: 800; letter-spacing: -.02em; }
.fm-det-head .fm-mini { margin-left: auto; }
.fm-det-sub { font-size: 11.5px; color: var(--fg-mute); margin-top: 2px; }
.fm-det-nums { display: flex; border: 1px solid var(--hairline); border-radius: 2px; margin-top: 10px; overflow: hidden; }
.fm-num { flex: 1; padding: 7px 11px 6px; border-left: 1px solid var(--hairline); display: flex; flex-direction: column; gap: 1px; }
.fm-num:first-child { border-left: 0; }
.fm-num-v { font-family: var(--mono); font-size: 15px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fm-num-k { font-family: var(--mono); font-size: 9.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--fg-mute); }
.fm-det-synopsis { font-size: 12.5px; color: var(--fg-dim); line-height: 1.55; margin: 12px 0 0; }

/* --- connector chips (the walkable graph) ------------------------------------ */
.fm-chips { display: flex; flex-wrap: wrap; gap: 7px; align-items: center; min-width: 0; }
.fm-chip {
  display: inline-flex; align-items: baseline; gap: 6px; cursor: pointer;
  border: 1px solid var(--hairline); border-radius: 2px; background: var(--bg-soft);
  color: var(--fg); text-align: left; padding: 2px 8px; font-size: 11.5px;
}
.fm-chip b { font-weight: 600; }
.fm-chip:hover { background: color-mix(in srgb, var(--portal) 10%, transparent); border-color: color-mix(in srgb, var(--portal) 45%, transparent); }
.fm-chip-sub { font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); }
.fm-chip.ghostnode { border-style: dashed; color: var(--fg-dim); cursor: default; }
.fm-credit { display: inline-flex; align-items: center; gap: 5px; }
.fm-as { font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); }
.fm-chip-x { border: 0; background: none; cursor: pointer; color: var(--fg-mute); font-size: 12px; padding: 0 1px; line-height: 1; }
.fm-chip-x:hover, .fm-chip-x.armed { color: var(--tone-amber); }

/* credits grouped by role; the role is the quiet gutter label */
.fm-credits { margin-top: 2px; }
.fm-credit-row { display: grid; grid-template-columns: 92px 1fr; gap: 8px; align-items: start; padding: 4px 0; border-top: 1px solid var(--hairline); }
.fm-credit-row:first-of-type { border-top: 0; }
.fm-credit-role { font-family: var(--mono); font-size: 10px; letter-spacing: .05em; text-transform: uppercase; color: var(--fg-mute); padding-top: 3px; }
.fm-credit-add { display: flex; gap: 7px; align-items: center; margin-top: 7px; flex-wrap: wrap; }
.fm-credit-add select, .fm-credit-add input {
  border: 1px solid var(--hairline); border-radius: 2px; outline: none;
  background: color-mix(in srgb, var(--fg) 5%, transparent); color: var(--fg);
  padding: 3px 7px; font-size: 11.5px; font-family: inherit;
}
.fm-credit-add input:focus { background: color-mix(in srgb, var(--portal) 10%, transparent); }
.fm-credit-add input { width: 150px; }
.fm-inline-add { margin-top: 0; }
.fm-studios { margin-top: 2px; }

/* notes — inline click-to-edit; the ✎ affordance reveals on hover */
.fm-notes {
  position: relative; margin-top: 12px; padding: 7px 26px 7px 10px; border-radius: 2px;
  background: color-mix(in srgb, var(--fg) 4%, transparent); cursor: text; font-size: 12px;
}
.fm-notes-lbl { font-family: var(--mono); font-size: 9.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--fg-mute); display: block; margin-bottom: 2px; }
.fm-notes-body { white-space: pre-wrap; color: var(--fg-dim); }
.fm-notes.empty .fm-notes-body { color: var(--fg-mute); }
.fm-notes-pen { position: absolute; right: 8px; top: 7px; font-size: 11px; color: var(--fg-mute); opacity: 0; transition: opacity .15s; }
.fm-notes:hover .fm-notes-pen { opacity: 1; }
.fm-notes-edit {
  width: 100%; border: 1px solid var(--hairline); border-radius: 2px; outline: none;
  background: color-mix(in srgb, var(--portal) 8%, transparent); color: var(--fg);
  font: inherit; font-size: 12px; padding: 4px 6px; resize: vertical;
}

/* --- watch log (dense rows; actions reveal on hover) ------------------------- */
.fm-blk-head { display: flex; align-items: center; gap: 8px; }
.fm-blk-head .fm-blk-lbl { flex: 1; }
.fm-blk-head .fm-mini { margin-top: 10px; }
.fm-view-list { display: flex; flex-direction: column; }
.fm-view-row { display: grid; grid-template-columns: 78px 36px 1fr auto; gap: 10px; align-items: start; padding: 7px 2px; border-top: 1px solid var(--hairline); }
.fm-view-row:first-child { border-top: 0; }
.fm-view-row.ghost { opacity: .42; }
.fm-view-date { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); padding-top: 2px; }
.fm-view-rating { font-family: var(--mono); font-size: 15px; font-weight: 700; color: var(--portal); }
.fm-view-rating.unrated { color: var(--fg-mute); }
.fm-view-body { min-width: 0; font-size: 12px; }
.fm-view-context { color: var(--fg-dim); }
.fm-view-notes { margin-top: 2px; color: var(--fg-mute); font-size: 11.5px; white-space: pre-wrap; }
.fm-view-acts { display: flex; gap: 6px; opacity: 0; transition: opacity .15s; }
.fm-view-row:hover .fm-view-acts { opacity: 1; }

/* --- forms (cluster pad 9 / gap 7; filled wells; ground-tint focus) ---------- */
.fm-form { margin-top: 9px; padding: 9px; border: 1px solid var(--hairline); border-radius: 2px; background: color-mix(in srgb, var(--fg) 3%, transparent); }
.fm-form-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 7px; }
.fm-field { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.fm-field.full { grid-column: 1 / -1; }
.fm-field-lbl { font-family: var(--mono); font-size: 9.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--fg-mute); }
.fm-field input, .fm-field select, .fm-field textarea {
  border: 1px solid var(--hairline); border-radius: 2px; outline: none;
  background: color-mix(in srgb, var(--fg) 5%, transparent); color: var(--fg);
  padding: 4px 7px; font-size: 12px; font-family: inherit; min-width: 0;
}
.fm-field input:focus, .fm-field select:focus, .fm-field textarea:focus { background: color-mix(in srgb, var(--portal) 10%, transparent); }
.fm-field textarea { resize: vertical; }
.fm-form-acts { display: flex; align-items: center; gap: 7px; margin-top: 9px; }
.fm-form-acts .btn { padding: .32rem .8rem; font-size: 12px; }
.fm-form-spacer { flex: 1; }
.fm-view-form { margin-bottom: 4px; }

/* --- connections (the web) ---------------------------------------------------- */
.fm-web { margin-top: 14px; }
.fm-web-row { display: grid; grid-template-columns: 200px 1fr; gap: 10px; align-items: start; padding: 6px 0; border-top: 1px solid var(--hairline); }
.fm-web-row:first-of-type { border-top: 0; }
.fm-web-row.ghost { opacity: .42; }
.fm-web-node {
  display: inline-flex; align-items: baseline; gap: 6px; cursor: pointer;
  border: 0; background: none; color: var(--fg); text-align: left;
  padding: 2px 0; font-size: 12px; min-width: 0;
}
.fm-web-node b { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fm-web-node:hover b { color: var(--portal); }
.fm-web-kind { font-family: var(--mono); font-size: 9px; letter-spacing: .05em; text-transform: uppercase; color: var(--fg-mute); flex: none; }
.fm-web-row.ghost .fm-web-node { cursor: default; font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }

@media (max-width: 980px) {
  .fm-work { grid-template-columns: 1fr; }
  .fm-stats { flex-wrap: wrap; }
  .fm-stat { min-width: 130px; }
  .fm-form-grid { grid-template-columns: repeat(2, 1fr); }
  .fm-web-row { grid-template-columns: 1fr; }
}
/* --- Weed Buddy: subnav + genetics subpage --------------------------------- */
.wb-subnav { margin-left: auto; display: flex; border: 1px solid var(--hairline); border-radius: 2px; overflow: hidden; }
.wb-subnav a {
  padding: 4px 11px; font-family: var(--mono); font-size: 10.5px; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase; text-decoration: none;
  color: var(--fg-mute); border-left: 1px solid var(--hairline);
}
.wb-subnav a:first-child { border-left: 0; }
.wb-subnav a:hover { color: var(--fg); background: color-mix(in srgb, var(--fg) 5%, transparent); }
.wb-subnav a.active { color: var(--portal); background: color-mix(in srgb, var(--portal) 12%, transparent); }

#wbg-stats { margin-top: 4px; }
.wb-gen-layout { display: grid; grid-template-columns: 1fr 296px; gap: 14px; align-items: start; margin-top: 14px; }
.wb-gen-canvas { min-width: 0; display: flex; flex-direction: column; gap: 14px; }
.wb-gen-canvas .wb-gen { margin-top: 0; }
.wb-gen-inspector { position: sticky; top: calc(var(--portal-chrome-h, 120px) + 14px); min-width: 0; }
.wb-gen-loosebox .wb-blk-lbl { margin-top: 0; }

/* ancestry trace: hover dims the rest of the family */
.wb-gen-node { transition: opacity .15s, border-color .15s; }
.wb-gen-node.dim { opacity: .28; }
.wb-gen-node.hi { border-color: color-mix(in srgb, var(--portal) 55%, transparent); }
.wb-gen-node.sel { background: color-mix(in srgb, var(--portal) 12%, transparent); border-color: var(--portal); }
.wb-gen-edge { transition: opacity .15s; }
.wb-gen-edge.dim { opacity: .15; }
.wb-gen-edge.hi { stroke: color-mix(in srgb, var(--portal) 60%, transparent); stroke-width: 1.5; }

/* inspector */
.wb-insp-head { display: flex; align-items: center; gap: 8px; }
.wb-insp-head h3 { margin: 0; font-size: 15px; font-weight: 800; letter-spacing: -.02em; }
.wb-tag.ghost-tag { border-style: dashed; }
.wb-insp-sub { font-size: 11px; color: var(--fg-mute); margin-top: 3px; }
.wb-insp-act { margin-top: 9px; }
.wb-insp-act .wb-mini { text-decoration: none; display: inline-block; }
.wb-insp-edges { display: flex; flex-direction: column; gap: 4px; }
.wb-insp-edge { display: flex; align-items: center; gap: 6px; min-width: 0; }
.wb-insp-edge .wb-kin-chip { flex: none; max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-insp-note { font-size: 9.5px; color: var(--fg-mute); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-insp-edge .wb-chip-x { flex: none; }
.wb-insp-add {
  margin-top: 6px; width: 100%; border: 1px solid var(--hairline); border-radius: 2px;
  outline: none; background: color-mix(in srgb, var(--fg) 5%, transparent);
  color: var(--fg); padding: 4px 7px; font-size: 11.5px;
}
.wb-insp-add:focus { background: color-mix(in srgb, var(--portal) 10%, transparent); }

@media (max-width: 980px) {
  .wb-gen-layout { grid-template-columns: 1fr; }
  .wb-gen-inspector { position: static; }
}


/* --- cover art (key art on rows and the title card) --------------------------- */
.fm-thumb {
  width: 27px; height: 40px; flex: none; border-radius: 2px;
  border: 1px solid var(--hairline); object-fit: cover;
  background: color-mix(in srgb, var(--fg) 5%, transparent);
}
.fm-thumb-ph { display: inline-flex; align-items: center; justify-content: center; font-size: 11px; color: var(--fg-mute); opacity: .55; }
.fm-det-top { display: grid; grid-template-columns: 1fr auto; gap: 14px; align-items: start; }
.fm-det-left { min-width: 0; }
.fm-det-poster {
  width: 136px; aspect-ratio: 2 / 3; object-fit: cover; border-radius: 2px;
  border: 1px solid var(--hairline);
  background: color-mix(in srgb, var(--fg) 5%, transparent);
}

/* --- bounded layout (fixed heights, inner scroll — the page stays short) ----- */
#fm-titles .fm-list { max-height: min(52vh, 560px); overflow-y: auto; overscroll-behavior: contain; }
/* node rails — one band across the FULL width, three fixed-height columns
   (never a stacked left-column tower with a dead right side) */
.fm-nodes { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; align-items: start; margin-top: 14px; }
.fm-rail .fm-list { max-height: 240px; overflow-y: auto; overscroll-behavior: contain; }
/* connections — head stays put, the rows scroll inside a capped well */
.fm-web-rows { max-height: 340px; overflow-y: auto; overscroll-behavior: contain; }

@media (max-width: 980px) {
  .fm-det-poster { width: 104px; }
  #fm-titles .fm-list { max-height: 44vh; }
  .fm-nodes { grid-template-columns: 1fr; }
}

/* =============================================================================
   SongDB module (portal-songdb.*)
   -----------------------------------------------------------------------------
   Same taste-corpus geometry as Film / Weed Buddy: r2 corners, generous shell
   over tight interiors, mono small-caps quiet labels, accent carries STATE
   (selected row spine), structure stays neutral graphite. Cover art is a
   first-class element: round artist portraits, square album/single covers.
============================================================================= */

.sdb-work { display: grid; grid-template-columns: 360px 1fr; gap: 14px; align-items: start; margin-top: 14px; }
.sdb-side { min-width: 0; }
.sdb-main { min-width: 0; }

/* --- rail segmented control --------------------------------------------------- */
.sdb-seg { display: flex; gap: 0; border: 1px solid var(--hairline); border-radius: 2px; overflow: hidden; margin-bottom: 2px; flex-wrap: wrap; }
.sdb-seg-btn {
  flex: 1; min-width: 0; padding: 5px 8px; border: 0; cursor: pointer;
  background: transparent; color: var(--fg-dim);
  font-family: var(--mono); font-size: 10.5px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  border-left: 1px solid var(--hairline); white-space: nowrap;
}
.sdb-seg-btn:first-child { border-left: 0; }
.sdb-seg-btn.on { background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--fg); }

/* --- controls (search + filter chip) ------------------------------------------ */
.sdb-controls { display: flex; gap: 7px; margin: 8px 0 6px; align-items: stretch; }
.sdb-controls .fm-search { flex: 1; min-width: 0; }
.sdb-filter {
  flex: none; border: 1px solid var(--hairline); border-radius: 2px; cursor: pointer;
  background: transparent; color: var(--fg-mute);
  font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; padding: 0 9px; white-space: nowrap;
}
.sdb-filter.on {
  color: var(--fg); border-color: color-mix(in srgb, var(--accent) 55%, var(--hairline));
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}

/* --- rail rows + A–Z index ----------------------------------------------------- */
.sdb-listwrap { position: relative; }
.sdb-list {
  position: relative;
  display: flex; flex-direction: column; gap: 2px; max-height: min(58vh, 640px);
  overflow-y: auto; overscroll-behavior: contain; padding-left: 18px;
}
/* A–Z index docked on the LEFT; letters magnify toward the list as the cursor
   passes (transform set in JS, motion carried by this transition). */
.sdb-alpha {
  position: absolute; top: 0; left: 0; bottom: 0; width: 15px; z-index: 2;
  display: flex; flex-direction: column; justify-content: center; gap: 0;
  padding: 2px 0; user-select: none; pointer-events: auto;
}
.sdb-alpha-k {
  border: 0; background: transparent; cursor: pointer; padding: 0; line-height: 1;
  font-family: var(--mono); font-size: 8.5px; font-weight: 700; color: var(--fg-dim);
  flex: 1; min-height: 0; display: flex; align-items: center; justify-content: flex-start;
  transform-origin: left center; opacity: .8;
  transition: transform .18s cubic-bezier(.22,1,.36,1), opacity .18s ease, color .15s ease;
  will-change: transform;
}
.sdb-alpha-k:hover { color: var(--accent); }
.sdb-alpha-k.off { color: color-mix(in srgb, var(--fg) 16%, transparent); cursor: default; }
.sdb-stat-sub {
  font-family: var(--mono); font-size: 10px; color: var(--fg-mute);
  letter-spacing: .03em; margin-top: 1px;
}
.sdb-row {
  display: flex; align-items: center; gap: 9px; padding: 5px 7px;
  border-radius: 2px; cursor: pointer; border-left: 2px solid transparent;
}
.sdb-row:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.sdb-row.sel {
  border-left-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 9%, transparent);
}
.sdb-row-txt { min-width: 0; flex: 1; }
.sdb-row-name { font-size: 12.5px; font-weight: 600; color: var(--fg); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sdb-row-meta { font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sdb-pin-dot { color: var(--accent); font-size: 8px; vertical-align: middle; }
.sdb-star-dot { color: var(--c-amber-1, #f5a623); font-size: 10px; }
.sdb-ref-dot { font-family: var(--mono); font-size: 8.5px; color: var(--fg-mute); opacity: .7; }

/* --- art (hotlinked; ghosts when a URL is absent — accumulator) --------------- */
.sdb-thumb, .sdb-hero, .sdb-cover {
  flex: none; border-radius: 2px; border: 1px solid var(--hairline);
  background: color-mix(in srgb, var(--fg) 5%, transparent);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
}
.sdb-thumb { width: 34px; height: 34px; }
.sdb-hero { width: 118px; height: 118px; }
.sdb-cover { width: 100%; aspect-ratio: 1; }
.sdb-thumb img, .sdb-hero img, .sdb-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sdb-thumb.round, .sdb-hero.round { border-radius: 50%; }
.sdb-thumb.round img, .sdb-hero.round img { border-radius: 50%; }
.sdb-art-ghost { font-size: 15px; color: var(--fg-mute); opacity: .5; }
.sdb-hero .sdb-art-ghost { font-size: 34px; }

/* --- main card ---------------------------------------------------------------- */
.sdb-card-head { display: flex; gap: 14px; align-items: flex-start; }
.sdb-card-title { min-width: 0; flex: 1; }
.sdb-card-title h3 { margin: 2px 0 6px; font-size: 20px; letter-spacing: -.015em; }
.sdb-inv-on { color: var(--accent); font-family: var(--mono); font-size: 10px; letter-spacing: .05em; text-transform: uppercase; }

/* card-head action toggles: pin (artist), star (album), catalog (song) */
.sdb-toggle-btn {
  flex: none; align-self: flex-start; border: 1px solid var(--hairline); border-radius: 2px;
  background: transparent; color: var(--fg-mute); cursor: pointer; white-space: nowrap;
  font-family: var(--mono); font-size: 10px; font-weight: 700; letter-spacing: .04em;
  padding: 4px 9px;
}
.sdb-toggle-btn:hover { color: var(--fg); border-color: color-mix(in srgb, var(--fg) 30%, var(--hairline)); }
.sdb-toggle-btn.on {
  color: var(--fg); border-color: color-mix(in srgb, var(--accent) 55%, var(--hairline));
  background: color-mix(in srgb, var(--accent) 14%, transparent);
}
.sdb-toggle-btn.star.on { color: var(--c-amber-1, #f5a623); border-color: color-mix(in srgb, var(--c-amber-1, #f5a623) 55%, var(--hairline)); background: color-mix(in srgb, var(--c-amber-1, #f5a623) 14%, transparent); }
/* per-track catalog dot */
.sdb-cat-dot {
  flex: none; border: 0; background: transparent; cursor: pointer; padding: 0 3px;
  font-size: 11px; line-height: 1; color: color-mix(in srgb, var(--fg) 28%, transparent);
}
.sdb-cat-dot.on { color: var(--accent); }
.sdb-cat-dot:hover { color: var(--fg); }
.sdb-card-sub { font-size: 12px; color: var(--fg-dim); margin-bottom: 4px; }
.sdb-idplate {
  font-family: var(--mono); font-size: 10.5px; font-weight: 700; letter-spacing: .06em;
  padding: 1px 6px; border: 1px solid var(--hairline); border-radius: 2px;
  color: var(--fg); background: color-mix(in srgb, var(--fg) 5%, transparent);
}
.sdb-dim { color: var(--fg-mute); font-size: 11px; }
.sdb-blurb { font-size: 12.5px; color: var(--fg-dim); margin: 10px 0 0; }
.sdb-inline-link {
  border: 0; background: transparent; padding: 0; cursor: pointer;
  color: var(--fg); font-size: inherit; text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--fg) 30%, transparent);
  text-underline-offset: 2px;
}
.sdb-inline-link:hover { text-decoration-color: var(--accent); }

/* --- album cover grid ---------------------------------------------------------- */
.sdb-cover-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(118px, 1fr)); gap: 10px; margin-top: 6px; }
.sdb-cover-cell { cursor: pointer; min-width: 0; }
.sdb-cover-cell:hover .sdb-cover { border-color: color-mix(in srgb, var(--accent) 50%, var(--hairline)); }
.sdb-cover-name { font-size: 11.5px; font-weight: 600; color: var(--fg); margin-top: 5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sdb-cover-meta { font-family: var(--mono); font-size: 9px; color: var(--fg-mute); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* --- tracklist ------------------------------------------------------------------ */
.sdb-tracklist { display: flex; flex-direction: column; margin-top: 4px; max-height: 420px; overflow-y: auto; overscroll-behavior: contain; }
.sdb-track {
  display: flex; align-items: baseline; gap: 10px; padding: 4px 6px;
  border-radius: 2px; cursor: pointer;
}
.sdb-track:hover { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.sdb-track-no { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); width: 18px; flex: none; text-align: right; }
.sdb-track-name { font-size: 12.5px; color: var(--fg); flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sdb-track-dur { font-family: var(--mono); font-size: 10.5px; color: var(--fg-dim); flex: none; }
.sdb-track-artist { font-size: 11.5px; color: var(--fg-mute); flex: 0 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sdb-isrc-mini { font-family: var(--mono); font-size: 9px; letter-spacing: .04em; color: var(--fg-mute); flex: none; }

/* --- appears-on chips ------------------------------------------------------------ */
.sdb-appears { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.sdb-chip {
  border: 1px solid var(--hairline); border-radius: 2px; background: transparent;
  color: var(--fg-dim); cursor: pointer; padding: 2px 8px;
  font-family: var(--mono); font-size: 10px;
}
.sdb-chip:hover { border-color: color-mix(in srgb, var(--accent) 50%, var(--hairline)); color: var(--fg); }

/* --- musical identity row --------------------------------------------------------- */
.sdb-ident { display: flex; gap: 7px; align-items: flex-end; flex-wrap: wrap; margin-top: 4px; }
.sdb-ident label {
  display: flex; flex-direction: column; gap: 3px;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .07em;
  text-transform: uppercase; color: var(--fg-mute);
}
.sdb-ident input { width: 84px; }
.sdb-btn {
  border: 1px solid var(--hairline); border-radius: 2px; cursor: pointer;
  background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--fg);
  padding: 4px 12px; font-family: var(--mono); font-size: 10.5px; font-weight: 700;
  letter-spacing: .05em; text-transform: uppercase;
}
.sdb-btn:hover { background: color-mix(in srgb, var(--accent) 20%, transparent); }
.sdb-notes {
  width: 100%; min-height: 54px; resize: vertical; margin-top: 2px;
  border: 1px solid var(--hairline); border-radius: 2px;
  background: color-mix(in srgb, var(--fg) 4%, transparent); color: var(--fg);
  padding: 7px 9px; font-size: 12px; font-family: inherit; outline: none;
}

/* --- facet stacks ------------------------------------------------------------------- */
.sdb-facet { margin-top: 2px; }
.sdb-facet-row { display: flex; align-items: baseline; gap: 8px; padding: 4px 6px; border-radius: 2px; }
.sdb-facet-row:hover { background: color-mix(in srgb, var(--fg) 3%, transparent); }
.sdb-facet-body { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; min-width: 0; flex: 1; font-size: 12px; color: var(--fg); }
.sdb-numerals { font-family: var(--mono); font-size: 11px; color: var(--fg-dim); }
.sdb-f-key { font-family: var(--mono); font-size: 9.5px; letter-spacing: .06em; text-transform: uppercase; color: var(--fg-mute); }
.sdb-x {
  border: 0; background: transparent; color: var(--fg-mute); cursor: pointer;
  font-size: 13px; line-height: 1; padding: 0 3px; flex: none;
}
.sdb-x:hover { color: var(--tone-red, #e5484d); }
.sdb-facet-add { display: flex; gap: 6px; flex-wrap: wrap; margin: 5px 0 2px; }
.sdb-facet-add .fm-search { flex: 1 1 130px; min-width: 0; font-size: 11px; }

/* --- lyrics + annotations ------------------------------------------------------------
   Two kinds of traffic write here and they must never blur together: Ryder's
   annotations are amber, a model's are violet. Neither borrows the admin green
   (that stays the signed-in signal) and neither tints a surface — the highlight
   IS the state, the panel around it stays graphite.                            */
.sdb-lyr { margin-top: 2px; }
.sdb-lyr-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.sdb-lyr-lbl { margin: 12px 0 4px; }
.sdb-lyr-spacer { flex: 1 1 auto; }
.sdb-lyr-state {
  font-family: var(--mono); font-size: 9.5px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; padding: 1px 6px; border-radius: 2px;
  border: 1px solid var(--hairline); color: var(--fg-dim); cursor: help;
}
.sdb-lyr-state.ok   { color: var(--c-admin); border-color: color-mix(in srgb, var(--c-admin) 45%, var(--hairline)); }
.sdb-lyr-state.warn { color: var(--c-amber-1, #f5a623); border-color: color-mix(in srgb, var(--c-amber-1, #f5a623) 45%, var(--hairline)); }
.sdb-lyr-state.bad  { color: var(--tone-red, #e5484d); border-color: color-mix(in srgb, var(--tone-red, #e5484d) 45%, var(--hairline)); }
.sdb-lyr-state.dim  { color: var(--fg-mute); }
.sdb-lyr-prov { font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); cursor: help; white-space: pre-line; }
/* decided by reading the sources, not by the score alone — reason on hover */
.sdb-lyr-reviewed {
  font-family: var(--mono); font-size: 9px; letter-spacing: .05em; cursor: help;
  padding: 1px 5px; border-radius: 2px; color: var(--fg-dim);
  border: 1px dashed color-mix(in srgb, var(--fg) 26%, var(--hairline));
}

/* Ryder's flag — a row of one-click markers, no dropdown chrome */
.sdb-lyr-flags { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; margin: 5px 0 2px; }
.sdb-lyr-flag-lbl { font-family: var(--mono); font-size: 9px; letter-spacing: .08em; text-transform: uppercase; color: var(--fg-mute); }
.sdb-lyr-flag {
  border: 1px solid var(--hairline); border-radius: 2px; background: transparent;
  color: var(--fg-mute); cursor: pointer; padding: 1px 7px;
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .03em;
}
.sdb-lyr-flag:hover { color: var(--fg); border-color: color-mix(in srgb, var(--fg) 30%, var(--hairline)); }
.sdb-lyr-flag.on {
  color: var(--c-amber-1, #f5a623); border-color: color-mix(in srgb, var(--c-amber-1, #f5a623) 55%, var(--hairline));
  background: color-mix(in srgb, var(--c-amber-1, #f5a623) 14%, transparent);
}

.sdb-lyr-cols { display: grid; grid-template-columns: minmax(0, 1fr) 250px; gap: 14px; margin-top: 4px; align-items: start; }
@media (max-width: 900px) { .sdb-lyr-cols { grid-template-columns: minmax(0, 1fr); } }
.sdb-lyr-body {
  white-space: pre-wrap; font-size: 13px; line-height: 1.62; color: var(--fg);
  max-height: 520px; overflow-y: auto; overscroll-behavior: contain;
  border: 1px solid var(--hairline); border-radius: 2px;
  background: color-mix(in srgb, var(--fg) 3%, transparent); padding: 10px 12px;
}
.sdb-lyr-body::selection, .sdb-lyr-body *::selection { background: color-mix(in srgb, var(--accent) 34%, transparent); }
.sdb-lyr-edit { min-height: 260px; font-family: var(--mono); font-size: 12px; line-height: 1.55; }

/* the highlight itself */
.sdb-lyr-mark { background: transparent; color: inherit; border-radius: 1px; cursor: pointer; padding: 0 1px; }
.sdb-lyr-mark.by-ryder { background: color-mix(in srgb, var(--c-amber-1, #f5a623) 26%, transparent); box-shadow: inset 0 -1px 0 color-mix(in srgb, var(--c-amber-1, #f5a623) 70%, transparent); }
.sdb-lyr-mark.by-model { background: color-mix(in srgb, var(--c-violet-1, #8b5cf6) 24%, transparent); box-shadow: inset 0 -1px 0 color-mix(in srgb, var(--c-violet-1, #8b5cf6) 70%, transparent); }
.sdb-lyr-mark.by-ryder.by-model { background: linear-gradient(color-mix(in srgb, var(--c-amber-1, #f5a623) 26%, transparent), color-mix(in srgb, var(--c-violet-1, #8b5cf6) 26%, transparent)); }
.sdb-lyr-mark:hover { filter: brightness(1.25); }

/* annotation margin */
.sdb-lyr-side { display: flex; flex-direction: column; gap: 6px; max-height: 520px; overflow-y: auto; overscroll-behavior: contain; }
.sdb-lyr-side-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.sdb-lyr-count { font-family: var(--mono); font-size: 9px; color: var(--fg-mute); white-space: nowrap; }
.sdb-anno {
  border: 1px solid var(--hairline); border-left-width: 2px; border-radius: 2px;
  padding: 6px 8px; cursor: pointer; background: color-mix(in srgb, var(--fg) 3%, transparent);
}
.sdb-anno.by-ryder { border-left-color: var(--c-amber-1, #f5a623); }
.sdb-anno.by-model { border-left-color: var(--c-violet-1, #8b5cf6); }
.sdb-anno:hover { background: color-mix(in srgb, var(--fg) 6%, transparent); }
.sdb-anno.lit { border-color: color-mix(in srgb, var(--accent) 55%, var(--hairline)); background: color-mix(in srgb, var(--accent) 10%, transparent); }
.sdb-anno.orphan { opacity: .62; }
.sdb-anno-top { display: flex; align-items: center; gap: 6px; }
.sdb-anno-who { font-family: var(--mono); font-size: 9px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; }
.sdb-anno-who.by-ryder { color: var(--c-amber-1, #f5a623); }
.sdb-anno-who.by-model { color: var(--c-violet-1, #8b5cf6); }
.sdb-anno-orphan { font-family: var(--mono); font-size: 8.5px; letter-spacing: .05em; text-transform: uppercase; color: var(--fg-mute); cursor: help; }
.sdb-anno-quote { font-size: 11px; color: var(--fg-dim); font-style: italic; margin: 3px 0 2px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.sdb-anno-body { font-size: 12px; color: var(--fg); line-height: 1.45; }

/* selection composer */
.sdb-lyr-pop { margin-top: 7px; border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--hairline)); border-radius: 2px; padding: 8px 9px; background: var(--bg-soft); }
.sdb-lyr-pop-quote { font-size: 11.5px; font-style: italic; color: var(--fg-dim); margin-bottom: 5px; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.sdb-lyr-pop-ta {
  width: 100%; min-height: 52px; resize: vertical; border: 1px solid var(--hairline);
  border-radius: 2px; background: color-mix(in srgb, var(--fg) 4%, transparent);
  color: var(--fg); padding: 6px 8px; font-size: 12px; font-family: inherit; outline: none;
}
.sdb-lyr-pop-row { display: flex; gap: 6px; align-items: center; margin-top: 6px; }

/* rail row indicators */
.sdb-lyr-dot { font-family: var(--mono); font-size: 9px; flex: none; color: var(--fg-mute); cursor: help; }
.sdb-lyr-dot.ok { color: var(--c-admin); }
.sdb-lyr-dot.weak { color: var(--c-amber-1, #f5a623); }
.sdb-lyr-dot.flagged { color: var(--tone-red, #e5484d); }
.sdb-lyr-dot.anno { color: var(--c-violet-1, #8b5cf6); }

/* --- lineage ------------------------------------------------------------------------ */
.sdb-lineage { margin-top: 4px; }
.sdb-lin-lbl { font-family: var(--mono); font-size: 9.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--fg-mute); margin: 7px 0 3px; }
.sdb-lin-branch { display: flex; flex-direction: column; gap: 3px; }
.sdb-lin-branch.nested { margin-left: 22px; border-left: 1px solid var(--hairline); padding-left: 10px; }
.sdb-lin-row { display: flex; align-items: baseline; gap: 8px; font-size: 12px; }
.sdb-lin-arrow { color: var(--fg-mute); font-size: 11px; }

/* --- rail add forms ------------------------------------------------------------------ */
.sdb-add { margin-top: 10px; border-top: 1px solid var(--hairline); padding-top: 8px; }
.sdb-add-toggle {
  border: 0; background: transparent; color: var(--fg-dim); cursor: pointer;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .05em; padding: 2px 0;
}
.sdb-add-toggle:hover { color: var(--fg); }
.sdb-add-row { display: flex; gap: 6px; margin-bottom: 5px; }
.sdb-add-row .fm-search { font-size: 11px; }

@media (max-width: 980px) {
  .sdb-work { grid-template-columns: 1fr; }
  .sdb-hero { width: 92px; height: 92px; }
}

/* === Model History module (portal-model-history.*) ===========================
   Built 2026-07-24; recomposed 2026-07-27.

   Worn from the ratified taste corpus (~/Developer/records/skills/taste),
   not from generic dashboard convention:

   * INSTRUMENT WITH A PAPER HEART (entry 2026-07-15c, A3 + B5 + C4): the
     chrome — masthead, lineage, roster, benchmark matrix — are bounded WELLS
     that sink into the page; the identity card is the reading surface, page-
     coloured and shadowless. Depth by RECESSION on fixed zones; elevation is
     kept for transients only (the tips).
   * INK LIVES AT ZONE BOUNDARIES, NOT INSIDE ZONES (same entry). The 3px
     spine survives where it marks a boundary or a selection — the card edge,
     the selected roster row — and is gone from everything it was merely
     decorating: the family filter is one fused segmented strip, status is a
     filled square tag, roster group heads are a ruled label in family colour.
   * P2 graphite structure (--fg low-percent mixes only) · r2 corners ·
     shell/dense spacing · small-caps labels · square r2 tags over filled
     pills · calm removal.

   Family colour is IDENTITY and status colour is STATE — both ride marks,
   never a workspace surface tint (CLAUDE.md portal visual law / KB #274).
============================================================================= */

#portal-model-history {
  /* sunk chrome vs. page-coloured content, resolved per theme so recession
     reads the same direction in both */
  --mh-well:  color-mix(in srgb, var(--fg) 4%, var(--bg));
  --mh-paper: var(--bg-elev);
  --mh-inset: inset 0 1px 6px color-mix(in srgb, var(--fg) 7%, transparent);
}
:root[data-theme="dark"] #portal-model-history {
  --mh-well:  color-mix(in srgb, #000 55%, var(--bg-elev));
  --mh-inset: inset 0 1px 6px rgba(0, 0, 0, .38);
}

#portal-model-history .ws-kicker { font-family: var(--mono); }

/* --- shared small-caps label --- */
.mh-label {
  font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--fg-mute); font-weight: 600;
}

/* --- zones: the sunk chrome ------------------------------------------------ */
.mh-zone {
  border: 1px solid var(--border); border-radius: 2px;
  background: var(--mh-well); box-shadow: var(--mh-inset);
  padding: 12px 13px;
}
.mh-zone-head {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  margin-bottom: 9px;
}
.mh-zone-head-col { flex-direction: column; align-items: flex-start; gap: 3px; }
.mh-zone-kicker {
  font-size: 11px; line-height: 1.5; color: var(--fg-mute); max-width: 92ch;
}

/* --- masthead: ledger + frontier keys -------------------------------------- */
.mh-masthead {
  margin: 14px 0 12px; border: 1px solid var(--border); border-radius: 2px;
  background: var(--mh-well); box-shadow: var(--mh-inset); overflow: hidden;
}
.mh-ledger {
  display: flex; flex-wrap: wrap; align-items: baseline;
  padding: 9px 13px; border-bottom: 1px solid var(--hairline);
}
.mh-led {
  display: inline-flex; align-items: baseline; gap: 7px;
  padding: 2px 15px; border-right: 1px solid var(--hairline);
}
.mh-led:first-child { padding-left: 0; }
.mh-led:last-child { border-right: 0; }
.mh-led b { font: 700 14px var(--mono); letter-spacing: -.01em; }
.mh-led i {
  font-style: normal; font-size: 9.5px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--fg-mute); white-space: nowrap;
}
.mh-led-latest { cursor: pointer; border-radius: 2px; }
.mh-led-latest:hover b { color: color-mix(in srgb, var(--accent) 70%, var(--fg)); }

.mh-frontier { display: flex; align-items: center; gap: 13px; padding: 11px 13px; }
.mh-frontier-lab { flex: 0 0 auto; }
.mh-keys { display: flex; gap: 8px; flex: 1; min-width: 0; overflow-x: auto; }
.mh-key {
  flex: 1 1 0; min-width: 152px; cursor: pointer; text-align: left;
  display: flex; flex-direction: column; gap: 2px;
  padding: 8px 10px 7px; border-radius: 2px;
  border: 1px solid var(--border); border-top: 2px solid var(--fam);
  background: var(--mh-paper); color: var(--fg-dim);
}
.mh-key:hover { border-color: var(--border-hi); }
.mh-key.sel {
  background: color-mix(in srgb, var(--fam) 9%, var(--mh-paper));
  border-color: color-mix(in srgb, var(--fam) 42%, var(--border));
  border-top-color: var(--fam);
}
.mh-key-fam {
  font: 700 8.5px var(--sans); letter-spacing: .11em; text-transform: uppercase;
  color: color-mix(in srgb, var(--fam) 78%, var(--fg));
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mh-key-name { font: 800 13.5px var(--sans); letter-spacing: -.012em; color: var(--fg); }
.mh-key-id {
  font: 400 9px var(--mono); color: var(--fg-mute);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mh-key-nums { display: flex; gap: 10px; margin-top: 3px; }
.mh-key-nums em {
  font: 500 10px var(--mono); font-style: normal; color: var(--fg-dim);
  white-space: nowrap;
}

/* --- family filter: one fused segmented strip (no per-chip spines) --------- */
.mh-seg {
  display: inline-flex; border: 1px solid var(--border); border-radius: 2px;
  background: var(--mh-paper); overflow: hidden; max-width: 100%;
  overflow-x: auto;
}
.mh-seg-b {
  display: inline-flex; align-items: center; gap: 6px;
  border: 0; border-right: 1px solid var(--hairline); background: transparent;
  color: var(--fg-dim); cursor: pointer; font: 600 11px var(--sans);
  padding: 5px 11px; white-space: nowrap;
  box-shadow: inset 0 -2px 0 transparent;
}
.mh-seg-b:last-child { border-right: 0; }
.mh-seg-b:hover { color: var(--fg); background: color-mix(in srgb, var(--fg) 4%, transparent); }
.mh-seg-b.sel {
  color: var(--fg);
  background: color-mix(in srgb, var(--fam) 10%, transparent);
  box-shadow: inset 0 -2px 0 var(--fam);
}
.mh-seg-n { font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); }

.mh-fam-blurb {
  margin: 8px 1px 2px; font-size: 12px; line-height: 1.5; color: var(--fg-dim);
  max-width: 78ch;
}

/* --- lineage legend: the lifespan encoding, described not instructed ------- */
.mh-legend { display: flex; gap: 13px; margin-left: auto; flex-wrap: wrap; }
.mh-lg {
  display: inline-flex; align-items: center; gap: 5px;
  font: 500 9px var(--mono); letter-spacing: .06em; text-transform: uppercase;
  color: var(--fg-mute);
}
.mh-lg::before { content: ""; width: 15px; height: 7px; border-radius: 1px; }
.lg-served::before { background: color-mix(in srgb, var(--fg) 34%, transparent); }
.lg-sunset::before {
  background: color-mix(in srgb, var(--fg) 10%, transparent);
  border: 1px dashed color-mix(in srgb, var(--fg) 32%, transparent);
}
.lg-sched::before {
  background: transparent;
  border: 1px dashed color-mix(in srgb, var(--fg) 34%, transparent);
}
.lg-open::before {
  content: "···"; width: auto; height: auto; letter-spacing: 1px;
  color: var(--fg-mute); line-height: 1;
}

/* --- lifespan chart -------------------------------------------------------- */
.mh-lc-wrap { position: relative; margin-top: 8px; overflow-x: auto; }
.mh-lc { display: block; }
.mh-lc-grid { stroke: var(--hairline); stroke-width: 1; }
.mh-lc-year, .mh-lc-nowlab {
  font: 500 9px var(--mono); fill: var(--fg-mute);
  letter-spacing: .08em; text-transform: uppercase;
}
.mh-lc-nowlab { text-anchor: end; fill: color-mix(in srgb, var(--accent) 80%, var(--fg)); }
.mh-lc-now {
  stroke: color-mix(in srgb, var(--accent) 55%, transparent);
  stroke-width: 1; stroke-dasharray: 2 3;
}
.mh-lc-fam {
  font: 700 9px var(--sans); letter-spacing: .1em; text-transform: uppercase;
}
.mh-lc-famrule { stroke: var(--hairline); stroke-width: 1; }
.mh-lc-lab {
  font: 500 9.5px var(--mono); fill: var(--fg-mute); text-anchor: end; cursor: pointer;
}
.mh-lc-hit { fill: var(--fg); fill-opacity: 0; cursor: pointer; }
.mh-lcrow:hover .mh-lc-hit { fill-opacity: .035; }
.mh-lcrow:hover .mh-lc-lab, .mh-lcrow.sel .mh-lc-lab { fill: var(--fg); }

/* served → sunsetting → scheduled; a span whose end was never recorded
   trails off in dots rather than pretending to a date */
.mh-lc-served { fill: var(--fam); fill-opacity: .34; cursor: pointer; }
.mh-lcrow.st-legacy  .mh-lc-served { fill-opacity: .26; }
.mh-lcrow.st-deprecated .mh-lc-served { fill-opacity: .22; }
.mh-lcrow.st-retired .mh-lc-served { fill-opacity: .17; }
.mh-lcrow:hover .mh-lc-served { fill-opacity: .48; }
.mh-lcrow.sel .mh-lc-served { fill-opacity: .6; }
.mh-lc-sunset {
  fill: var(--fam); fill-opacity: .09; cursor: pointer;
  stroke: var(--fam); stroke-opacity: .45; stroke-width: 1; stroke-dasharray: 2 2;
}
.mh-lc-sched {
  fill: none; stroke: var(--fam); stroke-opacity: .5;
  stroke-width: 1; stroke-dasharray: 3 3;
}
.mh-lc-open { fill: var(--fam); }
.mh-lc-open.o0 { fill-opacity: .42; }
.mh-lc-open.o1 { fill-opacity: .25; }
.mh-lc-open.o2 { fill-opacity: .12; }
.mh-lc-cap { fill: var(--fam); cursor: pointer; }
.mh-lcrow.st-retired .mh-lc-cap { fill-opacity: .55; }
.mh-lc-halo { fill: none; stroke: var(--fam); stroke-opacity: .55; stroke-width: 1; }

/* tooltip: surface-bordered float — elevation is the language of transients */
.mh-tip {
  position: absolute; z-index: 5; pointer-events: none;
  display: flex; flex-direction: column; gap: 1px;
  padding: 6px 9px; border: 1px solid var(--border-hi); border-radius: 2px;
  background: var(--bg-elev); font-size: 11px;
  box-shadow: 0 6px 12px color-mix(in srgb, var(--fg) 10%, transparent);
  opacity: 0; transition: opacity 120ms var(--ease, ease);
}
.mh-tip.show { opacity: 1; }
.mh-tip-meta { font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); }

/* --- work split: roster (well) + identity card (paper) --------------------- */
.mh-work {
  display: grid; grid-template-columns: 288px 1fr; gap: 12px; align-items: start;
  margin-top: 12px;
}

.mh-roster {
  border: 1px solid var(--border); border-radius: 2px;
  background: var(--mh-well); box-shadow: var(--mh-inset);
  padding: 11px; display: flex; flex-direction: column; gap: 2px;
  max-height: 660px; overflow-y: auto;
}
.mh-roster-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 4px;
}
.mh-add { font-size: 11px; padding: 3px 9px; }
.mh-addform { display: flex; flex-direction: column; gap: 6px; padding: 8px 0; }

/* group heads: a ruled label in family colour — alignment and ink at the
   boundary, no per-group spine */
.mh-group-head {
  display: flex; align-items: baseline; gap: 7px;
  margin: 11px 0 3px; padding-bottom: 3px;
  border-bottom: 1px solid var(--hairline);
}
.mh-group-name {
  font: 700 9.5px var(--sans); letter-spacing: .1em; text-transform: uppercase;
}
.mh-group-n { font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); }
.mh-group-unrec { margin-top: 16px; }
.mh-group-unrec .mh-group-name { color: var(--fg-mute); letter-spacing: .07em; }

.mh-row {
  display: grid; grid-template-columns: 1fr auto auto auto auto;
  gap: 7px; align-items: center; width: 100%;
  border: 0; border-left: 3px solid transparent; border-radius: 2px;
  background: transparent; cursor: pointer; text-align: left;
  padding: 4px 6px 4px 6px; color: var(--fg-dim); font: 500 12px var(--sans);
}
.mh-row:hover { background: color-mix(in srgb, var(--fg) 5%, transparent); color: var(--fg); }
.mh-row.sel {
  border-left-color: var(--fam); color: var(--fg);
  background: color-mix(in srgb, var(--fam) 8%, transparent);
}
.mh-row-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mh-row-id {
  font-family: var(--mono); font-size: 9px; color: var(--fg-mute);
  max-width: 88px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mh-row-use {
  font-family: var(--mono); font-size: 9px; min-width: 14px; text-align: right;
  color: color-mix(in srgb, var(--accent) 65%, var(--fg-mute));
}
.mh-row-yr { font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); }

.mh-row-unrec {
  grid-template-columns: 1fr auto auto; cursor: default;
  color: var(--fg-mute); font-style: normal;
}
.mh-row-unrec:hover { background: transparent; color: var(--fg-mute); }
.mh-mini {
  border: 1px solid var(--border); border-radius: 2px; background: transparent;
  color: var(--fg-dim); font: 600 9.5px var(--mono); padding: 2px 7px;
  cursor: pointer; letter-spacing: .04em;
}
.mh-mini:hover {
  color: var(--fg); border-color: var(--border-hi);
  background: color-mix(in srgb, var(--fg) 5%, transparent);
}

/* status: a filled square tag — state is FILLED, per the chip role tiering */
.mh-tag {
  display: inline-flex; align-items: center; border-radius: 2px;
  padding: 1.5px 6px; font: 600 8.5px var(--mono);
  letter-spacing: .08em; text-transform: uppercase;
  color: color-mix(in srgb, var(--st) 80%, var(--fg));
  background: color-mix(in srgb, var(--st) 13%, transparent);
  border: 1px solid color-mix(in srgb, var(--st) 22%, transparent);
}
.mh-tag-lg { font-size: 10px; padding: 3px 9px; }

/* --- identity card: the paper heart (page-coloured, bounded, no shadow) ---- */
.mh-card {
  border: 1px solid var(--border); border-radius: 2px;
  background: var(--mh-paper); padding: 15px 16px;
}
.mh-card-head { display: flex; align-items: center; gap: 11px; margin-bottom: 12px; }
.mh-card-spine { width: 3px; align-self: stretch; border-radius: 1px; background: var(--fam); }
.mh-card-title { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.mh-card-fam {
  font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase;
  color: color-mix(in srgb, var(--fam) 75%, var(--fg)); font-weight: 700;
}
.mh-card-name { margin: 0; font-size: 20px; font-weight: 800; letter-spacing: -.015em; }

.mh-specs {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 1px; border: 1px solid var(--hairline); border-radius: 2px;
  background: var(--hairline); overflow: hidden; margin-bottom: 11px;
}
.mh-spec {
  display: flex; flex-direction: column; gap: 3px; padding: 8px 10px;
  background: color-mix(in srgb, var(--fg) 2%, var(--mh-paper));
}
.mh-spec-v { font-family: var(--mono); font-size: 12.5px; font-weight: 500; word-break: break-word; }
.mh-spec-v.dim { color: var(--fg-mute); }
.mh-spec-hint { font-size: 9.5px; color: var(--fg-mute); line-height: 1.35; }
.mh-spec-wide { grid-column: 1 / -1; }

/* the corpus link — this record names models, transcripts record sessions */
.mh-corpus {
  display: flex; align-items: center; gap: 11px; margin-bottom: 11px;
  padding: 7px 10px; border: 1px solid var(--hairline); border-radius: 2px;
  background: color-mix(in srgb, var(--fg) 2.5%, transparent);
}
.mh-corpus-link { font-size: 11.5px; color: var(--fg-dim); text-decoration: none; }
.mh-corpus-link b {
  font-family: var(--mono); font-size: 12.5px; font-weight: 700;
  color: color-mix(in srgb, var(--accent) 75%, var(--fg));
}
.mh-corpus-link:hover { color: var(--fg); }
.mh-corpus-last { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }
.mh-corpus-none { font-size: 11.5px; color: var(--fg-mute); }

.mh-notes { display: flex; flex-direction: column; gap: 4px; margin-bottom: 11px; }
.mh-notes-body { margin: 0; font-size: 13px; line-height: 1.55; color: var(--fg-dim); max-width: 84ch; }
.mh-notes-body.dim { color: var(--fg-mute); font-style: italic; }

.mh-facets { display: flex; flex-direction: column; gap: 3px; }
.mh-facet {
  display: grid; grid-template-columns: 150px 1fr auto; gap: 8px; align-items: center;
  padding: 3px 0; border-bottom: 1px solid var(--hairline);
}
.mh-facet:last-child { border-bottom: 0; }
.mh-facet-k {
  font: 600 9.5px var(--mono); letter-spacing: .06em; text-transform: uppercase;
  color: var(--fg-mute);
}
.mh-facet-v { font-family: var(--mono); font-size: 11.5px; color: var(--fg-dim); }
.mh-facet-rm {
  border: 0; background: transparent; color: var(--fg-mute); cursor: pointer;
  font-size: 12px; padding: 0 3px; border-radius: 2px;
}
.mh-facet-rm:hover { color: var(--fg); background: color-mix(in srgb, var(--fg) 7%, transparent); }
.mh-facet-new { grid-template-columns: 150px 1fr auto; border-bottom: 0; padding-top: 6px; }
.mh-facet-new .btn { padding: 2px 9px; font-size: 11px; }

/* editing */
.mh-editable { cursor: text; border-radius: 2px; }
.mh-editable:hover { background: color-mix(in srgb, var(--fg) 6%, transparent); }
.mh-edit-input {
  width: 100%; border: 1px solid var(--border-hi); border-radius: 2px;
  background: color-mix(in srgb, var(--fg) 4%, var(--bg)); color: var(--fg);
  font: inherit; font-family: var(--mono); font-size: 11.5px; padding: 3px 6px;
}
.mh-edit-input:focus {
  outline: none; background: color-mix(in srgb, var(--accent) 7%, var(--bg));
}

/* removal is cleaning: quiet, unhurried, never alarm-styled */
.mh-card-foot { display: flex; justify-content: flex-end; margin-top: 12px; }
.mh-del {
  border: 0; background: transparent; color: var(--fg-mute); cursor: pointer;
  font: 500 10.5px var(--mono); letter-spacing: .04em; padding: 2px 4px;
  border-radius: 2px;
}
.mh-del:hover { color: var(--fg-dim); background: color-mix(in srgb, var(--fg) 5%, transparent); }

.mh-empty {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 56px 16px; border: 1px dashed var(--border); border-radius: 2px;
  color: var(--fg-mute); font-size: 12px;
}
.mh-empty-glyph { font-size: 22px; opacity: .45; }

/* --- benchmarks: the matrix ------------------------------------------------ */
.mh-benchzone { margin-top: 14px; }
.mh-mx-scroll { overflow-x: auto; margin-top: 7px; }
.mh-mx {
  display: grid;
  grid-template-columns: 170px repeat(var(--cols), minmax(62px, 1fr));
  gap: 1px; background: var(--hairline);
  border: 1px solid var(--hairline); border-radius: 2px;
  min-width: max-content;
}
.mh-mx-corner { background: var(--mh-well); }
.mh-mx-dim {
  background: var(--mh-well); padding: 5px 9px;
  font: 700 8.5px var(--sans); letter-spacing: .11em; text-transform: uppercase;
  color: color-mix(in srgb, var(--accent) 62%, var(--fg-mute));
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mh-mx-col {
  background: var(--mh-paper); padding: 6px 9px; text-align: right;
  font: 600 9.5px var(--mono); letter-spacing: .02em; color: var(--fg-dim);
  cursor: help; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mh-mx-row {
  display: flex; align-items: center; gap: 7px; width: 100%;
  background: var(--mh-paper); border: 0; padding: 5px 9px;
  cursor: pointer; text-align: left; font: 500 11.5px var(--sans);
  color: var(--fg-dim);
}
.mh-mx-row:hover { color: var(--fg); background: color-mix(in srgb, var(--fg) 4%, var(--mh-paper)); }
.mh-mx-row.sel {
  color: var(--fg); font-weight: 600;
  background: color-mix(in srgb, var(--fam) 10%, var(--mh-paper));
}
.mh-mx-sw { width: 6px; height: 6px; border-radius: 1px; background: var(--fam); flex: 0 0 auto; }
.mh-mx-nm { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mh-mx-yr { font-family: var(--mono); font-size: 9px; color: var(--fg-mute); }
.mh-mxc {
  position: relative; overflow: hidden; cursor: pointer;
  display: flex; align-items: center; justify-content: flex-end;
  background: var(--mh-paper); padding: 5px 9px 6px;
}
.mh-mxc:hover { background: color-mix(in srgb, var(--fg) 5%, var(--mh-paper)); }
.mh-mxc.sel { background: color-mix(in srgb, var(--fam) 8%, var(--mh-paper)); }
.mh-mxc-v { font: 500 11.5px var(--mono); color: var(--fg-dim); letter-spacing: -.01em; }
.mh-mxc-v i {
  font-style: normal; font-size: 8px; color: var(--fg-mute);
  vertical-align: super; margin-left: 1px;
}
.mh-mxc.lead .mh-mxc-v { color: var(--fg); font-weight: 700; }
.mh-mxc-fill {
  position: absolute; left: 0; bottom: 0; height: 2px;
  background: var(--fam); opacity: .42;
}
.mh-mxc.lead .mh-mxc-fill { opacity: .78; }
.mh-mxc.empty {
  color: var(--fg-mute); cursor: default; opacity: .4;
  font: 400 12px var(--mono);
}
.mh-mxc.empty:hover { background: var(--mh-paper); }

/* --- effort ladder --------------------------------------------------------- */
.mh-effortwrap { margin-top: 14px; }
.mh-effortviz { display: flex; flex-direction: column; gap: 3px; }
.mh-effort-row { display: inline-flex; gap: 4px; border-radius: 2px; }
.mh-effort-seg {
  display: inline-flex; align-items: center;
  border: 1px solid var(--hairline); border-radius: 2px; padding: 2px 7px;
  font: 600 9.5px var(--mono); letter-spacing: .06em; text-transform: uppercase;
  color: var(--fg-mute); white-space: nowrap;
}
.mh-effort-seg.lit {
  color: var(--fg);
  border-color: color-mix(in srgb, var(--fam, var(--accent)) 55%, var(--border));
  background: color-mix(in srgb, var(--fam, var(--accent)) 10%, transparent);
}
.mh-effort-seg.surface {
  color: var(--fg);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
  border-left: 3px solid var(--accent);
}
.mh-bench-dim {
  margin: 12px 0 4px; padding-top: 8px; border-top: 1px solid var(--hairline);
  font-size: 9.5px; letter-spacing: .11em; text-transform: uppercase;
  color: color-mix(in srgb, var(--accent) 70%, var(--fg-mute)); font-weight: 700;
}
.mh-effort-refrow {
  display: grid; grid-template-columns: 84px 1fr; gap: 10px;
  padding: 7px 0; border-bottom: 1px solid var(--hairline);
  align-items: start;
}
.mh-effort-refrow:last-child { border-bottom: 0; }
.mh-effort-refrow > .mh-effort-seg { justify-content: center; margin-top: 1px; }
.mh-effort-refbody { display: flex; flex-direction: column; gap: 2px; }
.mh-effort-reftext { margin: 0; font-size: 12px; line-height: 1.5; color: var(--fg-dim); max-width: 92ch; }
.mh-effort-since { font: 500 9.5px var(--mono); letter-spacing: .05em; color: var(--fg-mute); }

/* --- references ------------------------------------------------------------ */
.mh-refs {
  margin-top: 14px; padding: 12px 13px;
  border: 1px solid var(--hairline); border-radius: 2px;
}
.mh-refs p { margin: 5px 0 0; font-size: 11.5px; line-height: 1.55; color: var(--fg-mute); max-width: 88ch; }
.mh-refs a { color: color-mix(in srgb, var(--accent) 80%, var(--fg)); }
.mh-refs code { font-family: var(--mono); font-size: 10.5px; }

/* --- glossary float -------------------------------------------------------- */
.mh-glossed { cursor: help; }
.mh-tip-gloss {
  position: fixed; max-width: 320px; line-height: 1.45; font-size: 11px;
  color: var(--fg-dim);
}

@media (max-width: 980px) {
  .mh-work { grid-template-columns: 1fr; }
  .mh-frontier { flex-direction: column; align-items: stretch; gap: 8px; }
}
@media (max-width: 700px) {
  .mh-effort-refrow { grid-template-columns: 68px 1fr; }
  .mh-legend { display: none; }
}

/* =============================================================================
   SITE TRAFFIC (portal-traffic.html)                            added 2026-07-24
   -----------------------------------------------------------------------------
   Styled from the ratified taste corpus (~/Developer/records/skills/taste),
   not from generic dashboard convention: r2 (2px) corners — the audition
   verdict, and rounded-rect default boxes are ranked dead; shell/dense spacing;
   small-caps mono labels; uniform 3px SPINE as the accent language; square r2
   tags rather than filled pills (pill grammar ranked last); elevation only on
   floating surfaces. No lime/pale-green surface tint anywhere — admin green is
   the signed-in SIGNAL and a chart series identity, never a workspace ground
   (CLAUDE.md portal visual law / KB #274).

   SERIES COLORS ARE VALIDATED, NOT PICKED BY EYE. Both themes pass the six
   checks (lightness band, chroma floor, CVD separation across ALL pairs,
   normal-vision floor, contrast vs surface) from the dataviz method. Worst
   adjacent CVD ΔE: 25.7 dark / 26.6 light for admin↔public; 12.3 / 12.1 with
   agent included. Re-run the validator before changing any of these three.
============================================================================= */

#portal-traffic {
  --tf-admin:  #2b9f4a;   /* signed-in admin — green, the signed-in signal      */
  --tf-public: #1467c2;   /* anonymous visitors — the portal blue family        */
  --tf-agent:  #a02a83;   /* MCP connector / phone bearer                       */
  --tf-heat:   var(--portal);
  --tf-line:   var(--hairline);
  --tf-pad:    13px;      /* shell/dense: content boxes 12–13 outer             */
}
:root[data-theme="dark"] #portal-traffic {
  --tf-admin:  #30ad51;
  --tf-public: #3280dd;
  --tf-agent:  #b13b92;
}

#portal-traffic.is-loading { opacity: .6; transition: opacity 160ms var(--ease); }

/* --- console head ---------------------------------------------------------- */

.tf-head {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin: 1.5rem 0 1rem;
}
.tf-head-l { display: flex; align-items: center; gap: 12px; min-width: 0; }
.tf-head-r { display: flex; align-items: center; gap: 7px; margin-left: auto; flex-wrap: wrap; }

.tf-live {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--mono); font-size: 11px; letter-spacing: .03em;
  color: var(--fg-dim); padding: 5px 9px; border-radius: 2px;
  background: var(--mat-1); border: 1px solid var(--tf-line);
  border-left: 3px solid var(--fg-mute);   /* spine carries the state */
}
.tf-live[data-state="on"]  { border-left-color: var(--tf-admin); color: var(--fg); }
.tf-live[data-state="off"] { border-left-color: var(--fg-mute); }
.tf-live-dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--fg-mute); flex: none;
}
.tf-live[data-state="on"] .tf-live-dot { background: var(--tf-admin); }
.tf-live-txt { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 46ch; }
.tf-asof { font-family: var(--mono); font-size: 11px; color: var(--fg-mute); }

/* Dense segmented strip (e-07 C#1) — compact, r2, no pill radii. */
.tf-seg {
  display: inline-flex; gap: 0; padding: 2px; border-radius: 2px;
  background: var(--mat-1); border: 1px solid var(--tf-line);
}
.tf-seg button {
  font: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 11px; border: 0; border-radius: 2px; background: transparent;
  color: var(--fg-mute); transition: color 140ms var(--ease), background 140ms var(--ease);
}
.tf-seg button:hover { color: var(--fg); }
.tf-seg button[aria-selected="true"] {
  background: color-mix(in srgb, var(--portal) 14%, transparent);
  color: var(--fg);
}
.tf-seg-sm button { font-size: 11px; padding: 4px 9px; }
/* The lens carries series keys, so its selected state stays neutral —
   the swatch is the identity, the ground would fight it. */
.tf-seg-lens button { padding-left: 9px; }

.tf-toggle {
  font-family: var(--mono); font-size: 11px; letter-spacing: .04em;
  padding: 6px 10px; border-radius: 2px; background: var(--mat-1);
  border: 1px solid var(--tf-line); color: var(--fg-mute); cursor: pointer;
  transition: color 140ms var(--ease), border-color 140ms var(--ease);
}
.tf-toggle:hover { color: var(--fg); }
.tf-toggle[aria-pressed="true"] {
  color: var(--fg); border-color: color-mix(in srgb, var(--portal) 55%, transparent);
  background: color-mix(in srgb, var(--portal) 12%, transparent);
}

/* --- key swatches: square r2 tags, never filled pills ---------------------- */

.tf-key {
  width: 9px; height: 9px; border-radius: 2px; flex: none; display: inline-block;
  background: var(--fg-mute);
}
.tf-key-admin  { background: var(--tf-admin); }
.tf-key-public { background: var(--tf-public); }
.tf-key-agent  { background: var(--tf-agent); }

/* --- KPI rail -------------------------------------------------------------- */

.tf-kpis { margin-bottom: 1rem; }
.tf-kpis .kpi {
  border-radius: 2px; padding: 11px 13px;
  border-left: 3px solid color-mix(in srgb, var(--portal) 55%, transparent);
}
.tf-kpis .kpi-v { font-size: 1.55rem; font-variant-numeric: tabular-nums; }
.tf-kpis .kpi-k { font-size: 9.5px; letter-spacing: .09em; }
.tf-kpis .kpi-sub { font-size: 10.5px; }
.tf-kpi-admin { border-left-color: var(--tf-admin) !important; }
.tf-fail {
  font-family: var(--mono); font-size: 12px; color: var(--fg-dim);
  padding: 13px; border: 1px solid var(--tf-line); border-left: 3px solid var(--c-coral-1);
  border-radius: 2px; background: var(--mat-1);
}

/* --- chassis: hairline-divided bands, one defined console ------------------ */

.tf-chassis {
  border: 1px solid var(--tf-line); border-radius: 2px;
  background: var(--mat-1); overflow: hidden;
}
.tf-chassis > .tf-band { margin: 0; padding: 15px var(--tf-pad); border-top: 1px solid var(--tf-line); }
.tf-chassis > .tf-band:first-child { border-top: 0; }
.tf-band .portal-block-head { margin-bottom: 9px; align-items: baseline; }
.tf-band .portal-block-head h3 { font-size: 1rem; letter-spacing: -.01em; }
.tf-band .portal-block-head::before { display: none; }
.tf-band-ctl { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-left: auto; }

.tf-subhead {
  font-family: var(--mono); font-size: 9.5px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--fg-mute);
  margin: 0 0 7px;
}
.tf-legend { display: inline-flex; gap: 11px; }
.tf-legend-item {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--mono); font-size: 10.5px; color: var(--fg-dim);
}
.tf-dim { color: var(--fg-mute); }
.tf-warn { color: var(--c-coral-1, #ff6b6b); }
.tf-n { font-family: var(--mono); font-variant-numeric: tabular-nums; font-size: 12px; text-align: right; }

.tf-find {
  font: inherit; font-size: 11.5px; padding: 4px 8px; border-radius: 2px;
  background: var(--bg-soft); border: 1px solid var(--tf-line); color: var(--fg);
  width: 130px;
}
.tf-find:focus { outline: none; background: color-mix(in srgb, var(--portal) 8%, var(--bg-soft)); }

/* --- stacked share bar ----------------------------------------------------- */
/* A 2px surface gap between segments so adjacent fills never touch. */

.tf-stack {
  display: flex; height: 8px; width: 100%; gap: 2px; border-radius: 2px; overflow: hidden;
}
.tf-stack-empty { background: color-mix(in srgb, var(--fg) 6%, transparent); }
.tf-stack-seg { width: var(--w); background: var(--c); border-radius: 2px; min-width: 2px; }

/* --- BAND 1: who's here ---------------------------------------------------- */

.tf-split { display: flex; flex-direction: column; }

.tf-splitrow {
  display: grid; grid-template-columns: 92px 1fr auto; align-items: center;
  gap: 12px; padding: 6px 0;
}
.tf-splitrow + .tf-splitrow { border-top: 1px solid var(--tf-line); }
.tf-splitrow-k {
  font-family: var(--mono); font-size: 10px; letter-spacing: .07em;
  text-transform: uppercase; color: var(--fg-mute);
}
.tf-splitrow-l { display: flex; gap: 14px; }
.tf-splitlab { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; }
.tf-splitlab-v { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--fg); font-weight: 600; }
.tf-splitlab-p { font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); }

.tf-actors {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
  gap: 9px; margin-top: 12px;
}
.tf-actor {
  border: 1px solid var(--tf-line); border-radius: 2px; padding: 11px 12px;
  background: var(--bg-elev); border-left: 3px solid var(--fg-mute);
}
.tf-actor-admin  { border-left-color: var(--tf-admin); }
.tf-actor-public { border-left-color: var(--tf-public); }
.tf-actor-agent  { border-left-color: var(--tf-agent); }
.tf-actor-head { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.tf-actor-name { font-size: 12.5px; font-weight: 700; }
.tf-actor-note {
  font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute);
  flex: 1 1 100%; letter-spacing: .03em;
}
.tf-actor-v {
  font-size: 1.75rem; font-weight: 900; letter-spacing: -.03em; line-height: 1.1;
  margin-top: 6px; font-variant-numeric: tabular-nums;
}
.tf-actor-v span {
  font-size: 10px; font-weight: 700; font-family: var(--mono); color: var(--fg-mute);
  letter-spacing: .08em; text-transform: uppercase; margin-left: 6px;
}
.tf-actor-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 4px 10px; margin-top: 9px;
  border-top: 1px solid var(--tf-line); padding-top: 8px;
}
.tf-actor-grid > div { display: flex; align-items: baseline; gap: 5px; min-width: 0; }
.tf-actor-wide { grid-column: 1 / -1; }
.tf-actor-grid b {
  font-family: var(--mono); font-size: 12px; font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.tf-actor-grid span {
  font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute);
  letter-spacing: .05em; text-transform: uppercase;
}
.tf-spark { width: 100%; height: 24px; margin-top: 7px; display: block; overflow: visible; }
.tf-spark-flat {
  border-bottom: 1px solid var(--tf-line); height: 24px; margin-top: 7px;
}

/* --- BAND 2: time series --------------------------------------------------- */

.tf-chart { position: relative; padding: 4px 0 0 44px; }
.tf-plot { position: relative; height: 168px; }
.tf-tick {
  position: absolute; left: 0; right: 0; bottom: var(--y);
  border-top: 1px dashed color-mix(in srgb, var(--fg) 9%, transparent);
}
.tf-tick > span {
  position: absolute; right: calc(100% + 7px); top: -.55em;
  font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); white-space: nowrap;
}
.tf-tick-base { border-top: 1px solid var(--tf-line); border-top-style: solid; }
.tf-cols { position: absolute; inset: 0; display: flex; gap: 2px; align-items: flex-end; }
.tf-col { flex: 1; min-width: 0; height: 100%; display: flex; align-items: flex-end; cursor: default; }
.tf-col-stack { width: 100%; display: flex; flex-direction: column-reverse; gap: 2px; }
.tf-col-seg {
  display: block; width: 100%; height: var(--h); background: var(--c);
  border-radius: 2px 2px 0 0; min-height: 2px;
  transition: filter 140ms var(--ease);
}
.tf-col:hover .tf-col-seg { filter: brightness(1.18); }
.tf-xs { display: flex; gap: 2px; padding-top: 5px; }
.tf-x {
  flex: 1; min-width: 0; font-family: var(--mono); font-size: 9.5px;
  color: var(--fg-mute); text-align: center; white-space: nowrap; overflow: visible;
}

/* Tooltip: surface-bordered float, present shadow (e-13 C#1). */
.tf-tip {
  position: absolute; transform: translateX(-50%); pointer-events: none;
  background: var(--bg-elev); border: 1px solid var(--tf-line); border-radius: 2px;
  padding: 7px 9px; box-shadow: 0 12px 28px -8px rgba(0,0,0,.45);
  z-index: 5; min-width: 108px;
}
.tf-tip strong {
  display: block; font-size: 11px; font-weight: 700; margin-bottom: 4px;
  color: var(--fg);
}
.tf-tip-row {
  display: flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: 10.5px; color: var(--fg-dim); line-height: 1.7;
}
.tf-tip-row b {
  margin-left: auto; color: var(--fg); font-variant-numeric: tabular-nums;
}
.tf-tip-tot { border-top: 1px solid var(--tf-line); margin-top: 3px; padding-top: 3px; }

/* --- BAND 3: ranked attention ---------------------------------------------- */

.tf-ranked { display: flex; flex-direction: column; }

.tf-ranked-row {
  display: grid; grid-template-columns: minmax(140px, 1.5fr) 3fr 62px 42px;
  align-items: center; gap: 10px; padding: 5px 0;
}
.tf-ranked-row + .tf-ranked-row { border-top: 1px solid var(--tf-line); }
.tf-ranked-k {
  display: flex; align-items: center; gap: 6px; font-size: 12.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tf-ranked-bar { display: flex; gap: 2px; height: 9px; align-items: center; }
.tf-ranked-seg { height: 9px; width: var(--w); background: var(--c); border-radius: 2px; min-width: 2px; }
.tf-ranked-v {
  font-family: var(--mono); font-size: 12px; font-weight: 700; text-align: right;
  font-variant-numeric: tabular-nums;
}
.tf-ranked-s {
  font-family: var(--mono); font-size: 10.5px; color: var(--fg-mute); text-align: right;
}

/* Square r2 area tags, role-tiered quiet (type/count chips stay recessive). */
.tf-areatag {
  font-family: var(--mono); font-size: 8.5px; font-weight: 700; letter-spacing: .08em;
  text-transform: uppercase; padding: 2px 5px; border-radius: 2px; flex: none;
  color: var(--fg-mute); background: color-mix(in srgb, var(--fg) 7%, transparent);
}
.tf-areatag-portal   { color: var(--portal-2); background: color-mix(in srgb, var(--portal) 14%, transparent); }
.tf-areatag-app      { color: var(--c-violet-1); background: color-mix(in srgb, var(--c-violet-1) 13%, transparent); }
.tf-areatag-research { color: var(--c-cyan-1); background: color-mix(in srgb, var(--c-cyan-1) 13%, transparent); }

/* --- BAND 4: pages table --------------------------------------------------- */

.tf-table { font-size: 12px; }
.tf-row {
  display: grid; align-items: center; gap: 10px; padding: 6px 0;
  border-top: 1px solid var(--tf-line);
}
.tf-table-pages .tf-row {
  grid-template-columns: minmax(180px, 2.4fr) 54px 84px 62px 66px 56px 52px 66px;
}
.tf-row-head {
  border-top: 0; font-family: var(--mono); font-size: 9px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--fg-mute); padding-bottom: 3px;
}
.tf-row-head > span:not(:first-child) { text-align: right; }
.tf-row:not(.tf-row-head):hover { background: color-mix(in srgb, var(--fg) 3%, transparent); }
.tf-cell-page { display: flex; align-items: center; gap: 6px; min-width: 0; }
.tf-cell-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tf-cell-slug {
  font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: none; max-width: 40%;
}
.tf-cell-split { min-width: 0; }

/* --- BAND 5: acquisition --------------------------------------------------- */

.tf-two { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.tf-half { min-width: 0; }
.tf-kinds { display: flex; gap: 7px; flex-wrap: wrap; margin-bottom: 10px; }
.tf-kind {
  position: relative; flex: 1 1 88px; border: 1px solid var(--tf-line); border-radius: 2px;
  padding: 7px 9px 9px; background: var(--bg-elev); overflow: hidden;
}
.tf-kind b { display: block; font-size: 15px; font-weight: 800; font-variant-numeric: tabular-nums; }
.tf-kind span {
  font-family: var(--mono); font-size: 9px; letter-spacing: .08em;
  text-transform: uppercase; color: var(--fg-mute);
}
.tf-kind i {
  position: absolute; left: 0; bottom: 0; height: 2px; width: var(--w);
  background: var(--tf-public);
}
.tf-reflist { display: flex; flex-direction: column; }
.tf-ref {
  display: grid; grid-template-columns: minmax(90px, 1.4fr) 2fr 46px 54px;
  align-items: center; gap: 9px; padding: 4px 0;
}
.tf-ref + .tf-ref { border-top: 1px solid var(--tf-line); }
.tf-ref-host {
  font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tf-ref-bar { height: 7px; background: color-mix(in srgb, var(--fg) 5%, transparent); border-radius: 2px; }
.tf-ref-bar i {
  display: block; height: 7px; width: var(--w); border-radius: 2px;
  background: var(--c, var(--tf-public));
}
.tf-ref-v {
  font-family: var(--mono); font-size: 11.5px; text-align: right; font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.tf-ref-k {
  font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); text-align: right;
}

/* --- BAND 6: facets -------------------------------------------------------- */

.tf-facets { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 20px; }
.tf-facet { min-width: 0; }
.tf-facet-row {
  display: grid; grid-template-columns: minmax(64px, 1fr) 2fr 42px 40px;
  align-items: center; gap: 9px; padding: 4px 0;
}
.tf-facet-row + .tf-facet-row { border-top: 1px solid var(--tf-line); }
.tf-facet-bar { min-width: 0; }
.tf-facet-k { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tf-facet-v {
  font-family: var(--mono); font-size: 11.5px; font-weight: 700; text-align: right;
  font-variant-numeric: tabular-nums;
}
.tf-facet-p { font-family: var(--mono); font-size: 10px; color: var(--fg-mute); text-align: right; }

/* --- BAND 7: heatmap ------------------------------------------------------- */
/* Sequential ramp: ONE hue, monotonic by construction (--i drives a single
   color-mix), never a rainbow. Zero reads as empty, not as the lightest step. */

.tf-heat { position: relative; }
.tf-hmgrid { display: flex; flex-direction: column; gap: 2px; }
.tf-hmrow { display: flex; gap: 2px; align-items: center; }
.tf-hmlab {
  width: 30px; flex: none; font-family: var(--mono); font-size: 9.5px;
  color: var(--fg-mute); letter-spacing: .04em;
}
.tf-cell {
  flex: 1; min-width: 0; height: 15px; border-radius: 2px;
  background: color-mix(in srgb, var(--tf-heat) calc(var(--i) * 100%), transparent);
  transition: outline-color 120ms var(--ease);
  outline: 1px solid transparent; outline-offset: -1px;
}
.tf-cell-0 { background: color-mix(in srgb, var(--fg) 4%, transparent); }
.tf-cell:hover { outline-color: var(--fg-dim); }
.tf-hmaxis { margin-top: 1px; }
.tf-hmx {
  flex: 1; min-width: 0; font-family: var(--mono); font-size: 8.5px;
  color: var(--fg-mute); text-align: left;
}
.tf-hmkey {
  display: flex; align-items: center; gap: 3px; margin-top: 9px;
  font-family: var(--mono); font-size: 9px; color: var(--fg-mute);
}
.tf-hmkey .tf-cell { flex: none; width: 15px; }
.tf-hmkey > span:first-child { margin-right: 3px; }
.tf-hmkey > span:last-child { margin-left: 3px; }

/* --- BAND 8: sessions ------------------------------------------------------ */

.tf-sessions { display: flex; flex-direction: column; gap: 7px; }
.tf-session {
  border: 1px solid var(--tf-line); border-left: 3px solid var(--fg-mute);
  border-radius: 2px; padding: 9px 11px; background: var(--bg-elev);
}
.tf-session-admin  { border-left-color: var(--tf-admin); }
.tf-session-public { border-left-color: var(--tf-public); }
.tf-session-head { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.tf-session-actor { font-size: 12px; font-weight: 700; }
.tf-session-when, .tf-session-meta, .tf-session-src {
  font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); letter-spacing: .03em;
}
.tf-session-src {
  padding: 2px 5px; border-radius: 2px;
  background: color-mix(in srgb, var(--fg) 6%, transparent);
}
.tf-session-body { display: flex; gap: 14px; margin-top: 6px; flex-wrap: wrap; }
.tf-session-stat { font-size: 11px; color: var(--fg-dim); }
.tf-session-stat b {
  font-family: var(--mono); font-size: 12px; color: var(--fg); font-weight: 700;
  font-variant-numeric: tabular-nums; margin-right: 3px;
}
.tf-trail {
  display: flex; align-items: center; gap: 4px; flex-wrap: wrap; margin-top: 7px;
  padding-top: 7px; border-top: 1px solid var(--tf-line);
}
.tf-step {
  font-family: var(--mono); font-size: 9.5px; padding: 2px 6px; border-radius: 2px;
  background: color-mix(in srgb, var(--fg) 6%, transparent); color: var(--fg-dim);
  white-space: nowrap; max-width: 190px; overflow: hidden; text-overflow: ellipsis;
}
.tf-step-more { color: var(--fg-mute); }
.tf-arrow { font-size: 9px; color: var(--fg-mute); }

/* --- BAND 9: API ----------------------------------------------------------- */

.tf-apicards {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 9px; margin-bottom: 14px;
}
.tf-apicard {
  border: 1px solid var(--tf-line); border-radius: 2px; padding: 9px 11px;
  background: var(--bg-elev);
}
.tf-apicard-head {
  display: flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 700;
}
.tf-apicard-v {
  font-size: 1.35rem; font-weight: 900; letter-spacing: -.02em; margin-top: 4px;
  font-variant-numeric: tabular-nums;
}
.tf-apicard-v span {
  font-family: var(--mono); font-size: 9px; font-weight: 700; color: var(--fg-mute);
  letter-spacing: .08em; text-transform: uppercase; margin-left: 5px;
}
.tf-apicard-sub { font-family: var(--mono); font-size: 9.5px; color: var(--fg-mute); margin-top: 3px; }

.tf-eplist { display: flex; flex-direction: column; }
.tf-ep {
  display: grid; grid-template-columns: 44px minmax(140px, 2.2fr) 10px 2fr 48px 50px 30px;
  align-items: center; gap: 9px; padding: 4px 0;
}
.tf-ep + .tf-ep { border-top: 1px solid var(--tf-line); }
.tf-ep-m {
  font-family: var(--mono); font-size: 8.5px; font-weight: 700; letter-spacing: .06em;
  padding: 2px 4px; border-radius: 2px; text-align: center;
  color: var(--fg-mute); background: color-mix(in srgb, var(--fg) 7%, transparent);
}
.tf-ep-m-post, .tf-ep-m-put, .tf-ep-m-patch {
  color: var(--c-amber-1); background: color-mix(in srgb, var(--c-amber-1) 13%, transparent);
}
.tf-ep-m-delete { color: var(--c-coral-1); background: color-mix(in srgb, var(--c-coral-1) 13%, transparent); }
.tf-ep-p {
  font-family: var(--mono); font-size: 11px; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.tf-ep-bar { height: 6px; background: color-mix(in srgb, var(--fg) 5%, transparent); border-radius: 2px; }
.tf-ep-bar i { display: block; height: 6px; width: var(--w); background: var(--c); border-radius: 2px; }
.tf-ep-v {
  font-family: var(--mono); font-size: 11.5px; font-weight: 700; text-align: right;
  font-variant-numeric: tabular-nums;
}
.tf-ep-ms, .tf-ep-e { font-family: var(--mono); font-size: 10px; text-align: right; }

/* --- empty states: show the SHAPE, never a lesson (anti-didactic law) ------ */

.tf-empty { padding: 6px 0; }
.tf-empty p {
  font-family: var(--mono); font-size: 11px; color: var(--fg-mute); margin: 9px 0 0;
}
.tf-empty-rows { display: flex; flex-direction: column; gap: 6px; }
.tf-empty-rows > span {
  height: 9px; border-radius: 2px;
  background: color-mix(in srgb, var(--fg) 5%, transparent);
}
.tf-empty-rows > span:nth-child(2) { width: 82%; }
.tf-empty-rows > span:nth-child(3) { width: 64%; }
.tf-empty-rows > span:nth-child(4) { width: 47%; }
.tf-empty-rows > span:nth-child(5) { width: 31%; }
.tf-empty-ghost { display: flex; gap: 2px; align-items: flex-end; height: 84px; }
.tf-empty-ghost > span {
  flex: 1; border-radius: 2px 2px 0 0;
  background: color-mix(in srgb, var(--fg) 5%, transparent);
}
.tf-empty-ghost > span:nth-child(3n)   { height: 42%; }
.tf-empty-ghost > span:nth-child(3n+1) { height: 66%; }
.tf-empty-ghost > span:nth-child(3n+2) { height: 26%; }

/* --- responsive ------------------------------------------------------------ */

@media (max-width: 900px) {
  .tf-two { grid-template-columns: 1fr; }
  .tf-splitrow { grid-template-columns: 76px 1fr; }
  .tf-splitrow-l { grid-column: 1 / -1; }
  .tf-table-pages .tf-row { grid-template-columns: minmax(140px, 2fr) 50px 70px 60px; }
  .tf-table-pages .tf-row > span:nth-child(n+5) { display: none; }
  .tf-ep { grid-template-columns: 40px minmax(110px, 2fr) 10px 44px 44px; }
  .tf-ep > .tf-ep-bar, .tf-ep > .tf-ep-e { display: none; }
  .tf-head-r { margin-left: 0; }
}
@media (max-width: 620px) {
  .tf-ranked-row { grid-template-columns: 1fr 56px 38px; }
  .tf-ranked-bar { grid-column: 1 / -1; }
  .tf-cell { height: 12px; }
  .tf-hmlab { width: 24px; }
}


/* =============================================================================
   THE DECK — portal material system + section identity (2026-07-27)
   =============================================================================
   Ryder's ask: the portal should feel like a world you ENTER, and the Dashboard
   should CONNECT it rather than sit unchanged while everything grew around it.
   Three moves, in order of how much they carry:

   1. SECTION IDENTITY. Every top-level section owns a tone + glyph (the model
      lives in layout.js SECTION_TONE). That pair is the visual cue that
      travels: tab spine → deck cell → hub masthead → the widgets that report
      from it. You can read where you are, and where a number came from,
      without reading a label.

   2. MATERIAL, NOT ATMOSPHERE. Depth is built into the control surfaces: a
      top-lit bevel, a specular sweep that tracks the pointer, and a real
      perspective lean toward the hand. The banned website canvas (radial glow,
      grain, generative field — KB #274) sat BEHIND content; this lives ON it
      and only moves when you do. Structure stays neutral graphite — tone rides
      spines and state, never a surface wash (the lime-green law, KB #274).

   3. THE DECK. A masthead band above the KPI rail whose cells ARE the sections,
      each carrying its own live number. Not a hero title (location still lives
      in the nav highlight) — an instrument that shows the whole portal at once.

   Taste-corpus bindings: r2 corners · shell/dense spacing · elevation PRESENT
   (blur-12) · SPINE as the accent language · small-caps labels · numbers
   TRAVEL · motion smooth and unhurried, never pushy, never a mid-action pulse.
============================================================================= */

/* --- Section tones ---------------------------------------------------------
   Six identities + graphite for home. Indigo is new: Workspaces needed a hue
   distinct from both violet and cyan, and admin GREEN stays reserved for the
   signed-in signal — it is never spent on a section. */
:root { --tone-indigo: #4f46e5; }
:root[data-theme="dark"] { --tone-indigo: #a5b4fc; }

[data-tone="cyan"]   { --sec: var(--tone-cyan); }
[data-tone="violet"] { --sec: var(--tone-violet); }
[data-tone="coral"]  { --sec: var(--tone-coral); }
[data-tone="mint"]   { --sec: var(--tone-mint); }
[data-tone="amber"]  { --sec: var(--tone-amber); }
[data-tone="indigo"] { --sec: var(--tone-indigo); }
[data-tone="green"]  { --sec: var(--tone-green); }
[data-tone="portal"] { --sec: var(--portal-2); }

/* --- Deck material ---------------------------------------------------------
   One light source, above and slightly left. --lit is the bevel it catches,
   --shade the edge it leaves. Dark mode runs a faint highlight against a deep
   shade (glass on graphite); light mode inverts the weighting so panels read as
   milled surfaces rather than paper. */
body[data-portal] {
  --lit:    rgba(255, 255, 255, .72);
  --shade:  rgba(10, 15, 26, .07);
  --sheen:  10%;
  --cast:   0 18px 38px -20px rgba(10, 15, 26, .34);
  --cast-hi:0 30px 64px -22px rgba(10, 15, 26, .42);
}
:root[data-theme="dark"] body[data-portal] {
  --lit:    rgba(255, 255, 255, .062);
  --shade:  rgba(0, 0, 0, .34);
  --sheen:  16%;
  --cast:   0 20px 44px -22px rgba(0, 0, 0, .78);
  --cast-hi:0 34px 76px -24px rgba(0, 0, 0, .9);
}

/* The lit panel. A half-percent gradient is enough to read as a surface facing
   a light; anything stronger becomes a "card" and the grid stops being one
   fascia. Rings are box-shadow so shared 1px cell edges still merge. */
.deck-cell, .hub-surface, .hub-stat, .hub-live-panel,
body[data-portal] .dash-board .panel {
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--fg) 1.6%, var(--cell-bg)) 0,
      var(--cell-bg) 46%,
      color-mix(in srgb, var(--shade) 42%, var(--cell-bg)) 100%);
  box-shadow: inset 0 1px 0 var(--lit), inset 0 -1px 0 var(--shade),
              0 0 0 1px var(--grid-line);
}

/* --- The lift: sheen + lean ------------------------------------------------
   [data-lift] opts a surface in; layout.js wirePortalMaterial() feeds --mx/--my
   (where the light is) and --rx/--ry (how far it leans). The tilt transition is
   short enough to TRACK the hand and long enough to carry weight; the settle
   back to flat is slow, so a panel released mid-lean glides down rather than
   snapping. Neighbours never move — motion is never pushy (entry-08 law). */
/* Perspective lives in the transform FUNCTION, not on the container: each panel
   then hinges around its own centre, so a cell at the far right of the deck
   leans exactly like the one in the middle instead of skewing toward a shared
   vanishing point. (A container `perspective` on top of this would compose with
   it and double the distortion — deliberately absent.) */
[data-lift] {
  position: relative;
  transform-style: preserve-3d;
  transform: perspective(1200px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform .5s var(--ease-out), box-shadow .4s var(--ease),
              z-index 0s linear .4s;
}
[data-lift]:hover {
  z-index: 5;
  transition: transform .22s var(--ease), box-shadow .28s var(--ease), z-index 0s;
  transform: perspective(1200px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) translateZ(18px);
  box-shadow: inset 0 1px 0 var(--lit),
              0 0 0 1px color-mix(in srgb, var(--sec, var(--portal)) 46%, var(--grid-line)),
              var(--cast-hi);
}
/* The specular sweep — a soft ellipse of the section's own tone under the
   pointer. It fades IN on approach, never blinks, and dies with the hover. */
[data-lift]::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  opacity: 0; transition: opacity .34s var(--ease);
  background: radial-gradient(46% 120% at var(--mx, 50%) var(--my, 50%),
    color-mix(in srgb, var(--sec, var(--portal)) var(--sheen), transparent) 0,
    transparent 68%);
}
[data-lift]:hover::after { opacity: 1; }
/* Content rides above the sweep and a hair forward in Z, so the lean produces
   real parallax between the panel face and its type. Scoped to the surfaces
   that actually tilt — a translateZ on a board widget's children would build a
   stacking context around Leaflet's panes and the embedded console. */
.deck-cell > *, .hub-surface > *, .hub-stat > * {
  position: relative; z-index: 1; transform: translateZ(6px);
}

/* FLAT lift — sheen, ring and elevation without the lean. Board widgets host
   live instruments (the map, the console, a month grid); a 3D transform on
   their ancestor would flatten Leaflet's own layering and blur text mid-tilt.
   They get the light and the depth, not the rotation. */
[data-lift="flat"], [data-lift="flat"]:hover { transform: none; }
[data-lift="flat"] { transform-style: flat; will-change: auto; }
[data-lift="flat"]:hover {
  box-shadow: inset 0 1px 0 var(--lit),
              0 0 0 1px color-mix(in srgb, var(--sec, var(--portal)) 42%, var(--grid-line)),
              var(--cast);
}
/* Edit mode owns the pointer: drags do the geometry, so nothing lifts under it. */
#portal-hub.editing [data-lift],
#portal-hub.editing [data-lift]:hover { transform: none; box-shadow: 0 0 0 1px var(--grid-line); }
#portal-hub.editing [data-lift]::after { opacity: 0; }

/* --- Entrance: the portal assembles ---------------------------------------
   Cells rise into place on load, staggered by their index. This is the "enter
   a world" beat and it happens exactly once — never a loop, never a pulse. */
@keyframes deck-rise {
  from { opacity: 0; transform: perspective(1200px) translateY(11px) translateZ(-26px); }
  to   { opacity: 1; transform: perspective(1200px) translateY(0) translateZ(0); }
}
.deck-cell, .hub-surface, .hub-stat {
  animation: deck-rise .52s var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * 42ms);
}

/* --- Numbers travel -------------------------------------------------------- */
.travelling { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  [data-lift], [data-lift]:hover { transform: none; transition: box-shadow .2s var(--ease); }
  [data-lift] > * { transform: none; }
  .deck-cell, .hub-surface, .hub-stat { animation: none; }
}

/* =============================================================================
   The Deck band — the Dashboard's section constellation
============================================================================= */
.deck {
  margin-inline: calc(-1 * var(--pad-x));
  border-bottom: 1px solid var(--grid-line);
  background: var(--cell-bg);
}
/* Masthead line: identity left, instrument readouts right. Mono throughout —
   this row is a status strip, not a headline. */
.deck-bar {
  display: flex; align-items: center; gap: .8rem;
  padding: .5rem .85rem;
  border-bottom: 1px solid var(--grid-line);
}
.deck-mark { display: inline-flex; align-items: center; gap: .55rem; min-width: 0; }
.deck-mark-glyph {
  width: 25px; height: 25px; flex-shrink: 0;
  display: grid; place-items: center; border-radius: 7px;
  font-size: 12px; color: var(--portal-2);
  background: color-mix(in srgb, var(--portal) 13%, transparent);
  box-shadow: inset 0 1px 0 var(--lit),
              0 0 0 1px color-mix(in srgb, var(--portal) 26%, transparent);
}
.deck-mark-txt { display: flex; align-items: baseline; gap: .5rem; min-width: 0; }
.deck-mark-txt b {
  font: 700 11px/1 var(--mono); letter-spacing: .18em;
  text-transform: uppercase; color: var(--fg);
}
.deck-mark-txt i {
  font: 400 10.5px/1 var(--mono); font-style: normal; color: var(--fg-mute);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.deck-readouts {
  margin-left: auto; display: flex; align-items: center; gap: 0;
  flex-shrink: 0; font-family: var(--mono);
}
.deck-read {
  display: flex; flex-direction: column; gap: .1rem; align-items: flex-end;
  padding: 0 .85rem; border-left: 1px solid var(--grid-line);
}
.deck-read:first-child { border-left: none; }
.deck-read b { font-size: 13px; font-weight: 700; color: var(--fg); line-height: 1; font-variant-numeric: tabular-nums; }
.deck-read span {
  font-size: 8.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--fg-mute); line-height: 1;
}
/* The live dot: a slow breath, not an alarm blink. */
.deck-live { display: inline-flex; align-items: center; gap: .4rem; }
.deck-live-dot {
  width: 6px; height: 6px; border-radius: 999px; background: var(--c-admin);
  box-shadow: 0 0 7px color-mix(in srgb, var(--c-admin) 70%, transparent);
}

/* The constellation. Auto-fit so it re-flows to any width; cells share the 1px
   grid lines the rest of the surface uses, so the deck reads as the top band of
   one continuous fascia rather than a separate widget. */
.deck-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(11.5rem, 1fr));
  gap: 1px; background: var(--grid-line);
}
.deck-cell {
  display: flex; flex-direction: column; gap: .34rem;
  padding: .62rem .8rem .66rem;
  color: inherit; text-decoration: none; overflow: hidden;
  border-radius: 0;
}
/* THE SPINE — the accent language, at section scale. 3px uniform (entry-07:
   simplicity over scaled), tone-coded because tone here IS the meaning. */
.deck-cell::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--sec, var(--portal));
  opacity: .5; transition: opacity .3s var(--ease);
  z-index: 2;
}
.deck-cell:hover::before, .deck-cell.here::before { opacity: 1; }
.deck-cell-top { display: flex; align-items: center; gap: .45rem; }
.deck-cell-glyph {
  width: 19px; height: 19px; flex-shrink: 0;
  display: grid; place-items: center; border-radius: 5px;
  font-size: 10px; color: var(--sec, var(--portal));
  background: color-mix(in srgb, var(--sec, var(--portal)) 14%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--sec, var(--portal)) 24%, transparent);
}
.deck-cell-name {
  flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font: 700 10px/1 var(--mono); letter-spacing: .15em; text-transform: uppercase;
  color: var(--fg-dim);
}
.deck-cell:hover .deck-cell-name { color: var(--fg); }
.deck-cell-go {
  font: 400 12px/1 var(--mono); color: var(--fg-mute); flex-shrink: 0;
  opacity: 0; transform: translateX(-4px);
  transition: opacity .26s var(--ease), transform .26s var(--ease), color .26s var(--ease);
}
.deck-cell:hover .deck-cell-go { opacity: 1; transform: none; color: var(--sec, var(--portal)); }
/* The number is the point of the cell: large, tabular, second-accent coloring
   per the taste corpus (numeric emphasis carries the accent). */
.deck-cell-v {
  display: flex; align-items: baseline; gap: .38rem; min-width: 0;
}
.deck-cell-v b {
  font: 800 1.42rem/1 var(--sans); letter-spacing: -.03em;
  color: var(--sec, var(--portal)); font-variant-numeric: tabular-nums;
}
.deck-cell-v i {
  font: 400 10px/1.3 var(--mono); font-style: normal; color: var(--fg-mute);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.deck-cell-foot {
  display: flex; align-items: center; gap: .5rem; margin-top: auto; padding-top: .1rem;
}
/* Surface ticks: one mark per page in the section. Density IS the information —
   Money reads as two, Workspaces as eight, before you read either label. */
.deck-ticks { display: flex; gap: 2.5px; flex: 1; min-width: 0; }
.deck-tick {
  height: 3px; flex: 1 1 0; max-width: 14px; border-radius: 1px;
  background: color-mix(in srgb, var(--sec, var(--portal)) 34%, transparent);
  transition: background .3s var(--ease), transform .3s var(--ease-out);
  transform-origin: bottom;
}
.deck-cell:hover .deck-tick {
  background: color-mix(in srgb, var(--sec, var(--portal)) 88%, transparent);
  transform: scaleY(1.9);
}
/* Stagger the ticks so the row fills left-to-right instead of flashing. */
.deck-cell:hover .deck-tick:nth-child(2) { transition-delay: .03s; }
.deck-cell:hover .deck-tick:nth-child(3) { transition-delay: .06s; }
.deck-cell:hover .deck-tick:nth-child(4) { transition-delay: .09s; }
.deck-cell:hover .deck-tick:nth-child(5) { transition-delay: .12s; }
.deck-cell:hover .deck-tick:nth-child(6) { transition-delay: .15s; }
.deck-cell:hover .deck-tick:nth-child(7) { transition-delay: .18s; }
.deck-cell:hover .deck-tick:nth-child(8) { transition-delay: .21s; }
.deck-cell-n {
  font: 400 9.5px/1 var(--mono); color: var(--fg-mute); white-space: nowrap; flex-shrink: 0;
}
/* Home cell: you are standing on it. Tone fills the spine and the ground stays
   graphite — state is carried by the accent, structure never is. */
.deck-cell.here { background-image: none; background-color: color-mix(in srgb, var(--fg) 4%, var(--cell-bg)); }
.deck-cell.here .deck-cell-name { color: var(--fg); }

@media (max-width: 820px) {
  .deck-grid { grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); }
  .deck-cell-v b { font-size: 1.2rem; }
  .deck-read:nth-child(n+3) { display: none; }
}
@media (max-width: 560px) {
  .deck-mark-txt i { display: none; }
}

/* =============================================================================
   Section identity in the chrome — the cue that travels with you
============================================================================= */
/* Each tab wears its section's glyph and, when active, its section's tone. The
   strip stops being seven interchangeable words and becomes a legend you learn
   once: ❯_ is always Development, ◷ is always Schedule, wherever you see it. */
.psub-glyph {
  display: inline-grid; place-items: center; width: 15px; flex-shrink: 0;
  font-size: 10px; line-height: 1; color: var(--sec, var(--fg-mute));
  opacity: .72; transition: opacity var(--t-fast) var(--ease);
}
.psub-tab:hover .psub-glyph { opacity: 1; }
.psub-tab.active, .psub-group.active > .psub-tab {
  color: var(--sec, var(--accent-2));
  background: color-mix(in srgb, var(--sec, var(--accent)) 11%, transparent);
}
.psub-tab.active .psub-glyph, .psub-group.active > .psub-tab .psub-glyph { opacity: 1; }
/* The active tab grows a spine along its underside — the tab strip's own
   version of the box spine, so "which section" reads from the band edge. */
.psub-tab.active::after, .psub-group.active > .psub-tab::after {
  content: ""; position: absolute; left: .7rem; right: .7rem; bottom: -3px; height: 2px;
  background: var(--sec, var(--accent)); border-radius: 1px;
}
.psub-tab { position: relative; }
.psub-group.active > .psub-tab { position: relative; }
/* Only the caret toggles the menu on touch — give it a target and a hint. */
.psub-group .psub-caret {
  padding: .12rem .1rem; margin-right: -.12rem; border-radius: 4px;
  transition: color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
.psub-group:hover .psub-caret { transform: translateY(1px); color: var(--sec, var(--accent-2)); }
/* The section's own overview, at the head of its menu. */
.psub-item-hub {
  display: flex; align-items: center; gap: .45rem;
  color: var(--sec, var(--accent-2)); font-weight: 600;
  margin-bottom: .18rem; padding-bottom: .42rem;
  border-bottom: 1px solid var(--hairline); border-radius: 9px 9px 0 0;
}
.psub-item-glyph { font-size: 10px; opacity: .8; width: 13px; display: inline-grid; place-items: center; }
/* Row 2's section tag is the way back up to the hub, so it behaves like one. */
.psub-row2-tag {
  display: inline-flex; align-items: center; gap: .42rem;
  color: var(--sec, var(--fg-mute)); border-radius: 7px 0 0 7px;
  transition: color var(--t-fast) var(--ease), background var(--t-fast) var(--ease);
}
.psub-row2-tag:hover { background: color-mix(in srgb, var(--sec, var(--accent)) 12%, transparent); }
.psub-row2-tag.active { color: var(--fg); }
.psub-row2-tag .psub-glyph { opacity: 1; }
.psub-item.active, .psub-item2.active {
  color: var(--sec, var(--accent-2));
  background: color-mix(in srgb, var(--sec, var(--accent)) 10%, transparent);
}
.psub-item2.active { border-color: color-mix(in srgb, var(--sec, var(--accent)) 52%, transparent); }
/* The band itself carries the current section's tone on the brand dot and the
   bottom rule — location, before a single label is read. */
.portal-subnav[data-here] .psub-dot { background: var(--sec); box-shadow: 0 0 8px var(--sec); }
.portal-subnav[data-here="cyan"]   { --sec: var(--tone-cyan); }
.portal-subnav[data-here="violet"] { --sec: var(--tone-violet); }
.portal-subnav[data-here="coral"]  { --sec: var(--tone-coral); }
.portal-subnav[data-here="mint"]   { --sec: var(--tone-mint); }
.portal-subnav[data-here="amber"]  { --sec: var(--tone-amber); }
.portal-subnav[data-here="indigo"] { --sec: var(--tone-indigo); }
.portal-subnav[data-here="portal"] { --sec: var(--portal-2); }
body[data-portal] .portal-subnav[data-here] {
  border-bottom-color: color-mix(in srgb, var(--sec) 30%, var(--grid-line));
}
.psub-brand { color: var(--fg-mute); text-decoration: none; transition: color var(--t-fast) var(--ease); }
.psub-brand:hover { color: var(--fg); }

/* The main-header Portal directory gets the same legend. */
.pnav-glyph {
  display: inline-grid; place-items: center; width: 16px; flex-shrink: 0;
  font-size: 10.5px; line-height: 1; color: var(--sec, var(--fg-mute)); opacity: .8;
}
.pnav-row-parent { cursor: pointer; }   /* it is a link to the hub now */
.pnav-row.active { color: var(--sec, var(--accent)); }
.pnav-row.active .pnav-glyph { opacity: 1; }
.pnav-sub-hub {
  color: var(--sec, var(--accent-2)); font-weight: 600;
  margin-bottom: .15rem; padding-bottom: .4rem; border-bottom: 1px solid var(--hairline);
}

/* =============================================================================
   Section hub pages — Schedule · Development · User Data · Workspaces · Money
   -----------------------------------------------------------------------------
   A hub is a PLACE, not a directory. Three bands: what this section is and how
   it is doing (masthead + stat rail), its surfaces as live cards carrying their
   own real numbers, and the section's live content underneath. Every surface
   card is a working readout — you learn the state of the section without
   opening any of it.
============================================================================= */
.hub { padding-top: 0 !important; }

.hub-head {
  position: relative; overflow: hidden;
  margin-inline: calc(-1 * var(--pad-x));
  border-bottom: 1px solid var(--grid-line);
  background: var(--cell-bg);
}
/* The masthead's one graphic moment: a wide, very low-opacity wash of the
   section's tone raking in from the left, behind the glyph. It is the only
   place a tone touches a surface, it is anchored to a structural edge, and it
   is under 7% — a lit edge, never the pale-wash grammar that got overruled. */
.hub-head::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(58% 150% at 0% 0%,
    color-mix(in srgb, var(--sec, var(--portal)) 9%, transparent), transparent 70%);
}
.hub-head::after {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--sec, var(--portal));
}
.hub-head-inner {
  position: relative; display: flex; align-items: center; gap: .95rem;
  padding: 1rem 1.1rem .95rem;
}
.hub-glyph {
  width: 46px; height: 46px; flex-shrink: 0;
  display: grid; place-items: center; border-radius: 12px;
  font-size: 19px; color: var(--sec, var(--portal));
  background: color-mix(in srgb, var(--sec, var(--portal)) 13%, transparent);
  box-shadow: inset 0 1px 0 var(--lit),
              0 0 0 1px color-mix(in srgb, var(--sec, var(--portal)) 30%, transparent),
              0 10px 24px -14px color-mix(in srgb, var(--sec, var(--portal)) 60%, transparent);
}
.hub-title { min-width: 0; flex: 1; }
.hub-title h1 {
  margin: 0; font-size: 1.42rem; font-weight: 800; letter-spacing: -.03em; line-height: 1.1;
}
.hub-title p {
  margin: .2rem 0 0; font-family: var(--mono); font-size: 11px; color: var(--fg-mute);
  letter-spacing: .04em;
}
/* Section KPI rail — the same cell rhythm the dashboard strip uses, toned. */
.hub-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: 1px;
  margin-inline: calc(-1 * var(--pad-x));
  background: var(--grid-line);
  border-bottom: 1px solid var(--grid-line);
}
.hub-stat {
  display: flex; flex-direction: column; gap: .16rem;
  padding: .72rem .9rem .78rem; color: inherit; text-decoration: none; overflow: hidden;
}
.hub-stat-v {
  font: 800 1.35rem/1 var(--sans); letter-spacing: -.03em;
  color: var(--sv, var(--sec, var(--portal))); font-variant-numeric: tabular-nums;
}
.hub-stat-k {
  font: 700 9px/1 var(--mono); letter-spacing: .16em; text-transform: uppercase; color: var(--fg-dim);
}
.hub-stat-sub { font: 400 10px/1.35 var(--mono); color: var(--fg-mute); }

/* Band labels between the hub's sections — small-caps, quiet, structural. */
.hub-band {
  display: flex; align-items: center; gap: .7rem;
  margin-inline: calc(-1 * var(--pad-x));
  padding: .8rem 1.1rem .5rem;
}
.hub-band-k {
  font: 700 9.5px/1 var(--mono); letter-spacing: .2em; text-transform: uppercase; color: var(--fg-mute);
}
.hub-band-rule { flex: 1; height: 1px; background: var(--grid-line); }
.hub-band-n { font: 400 9.5px/1 var(--mono); color: var(--fg-mute); }

/* --- Surfaces: the section's pages, as live cards ------------------------- */
.hub-surfaces {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(15.5rem, 1fr)); gap: 1px;
  margin-inline: calc(-1 * var(--pad-x));
  background: var(--grid-line);
  border-block: 1px solid var(--grid-line);
}
.hub-surface {
  display: flex; flex-direction: column; gap: .5rem;
  padding: .85rem .95rem .9rem; min-height: 8.4rem;
  color: inherit; text-decoration: none; overflow: hidden;
}
.hub-surface::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--sec, var(--portal)); opacity: .42;
  transition: opacity .3s var(--ease); z-index: 2;
}
.hub-surface:hover::before { opacity: 1; }
.hub-surface-top { display: flex; align-items: center; gap: .5rem; }
.hub-surface-glyph {
  width: 22px; height: 22px; flex-shrink: 0;
  display: grid; place-items: center; border-radius: 6px;
  font-size: 11px; color: var(--sec, var(--portal));
  background: color-mix(in srgb, var(--sec, var(--portal)) 13%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--sec, var(--portal)) 22%, transparent);
}
.hub-surface-name {
  flex: 1; min-width: 0; font-size: .95rem; font-weight: 700; letter-spacing: -.02em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hub-surface-go {
  font: 400 12px/1 var(--mono); color: var(--fg-mute); flex-shrink: 0;
  opacity: 0; transform: translateX(-4px);
  transition: opacity .26s var(--ease), transform .26s var(--ease), color .26s var(--ease);
}
.hub-surface:hover .hub-surface-go { opacity: 1; transform: none; color: var(--sec, var(--portal)); }
.hub-surface-v { display: flex; align-items: baseline; gap: .4rem; flex-wrap: wrap; }
.hub-surface-v b {
  font: 800 1.28rem/1 var(--sans); letter-spacing: -.03em; color: var(--fg);
  font-variant-numeric: tabular-nums;
}
.hub-surface-v i {
  font: 400 10px/1.3 var(--mono); font-style: normal; color: var(--fg-mute);
}
.hub-surface-desc {
  margin: 0; font-family: var(--mono); font-size: 10.5px; line-height: 1.45; color: var(--fg-mute);
  margin-top: auto;
}
/* Facts, not prose: a wrapping row of "key value" pairs under the headline
   number, each one a real reading from that surface. */
.hub-facts { display: flex; flex-wrap: wrap; gap: .3rem; }
.hub-fact {
  display: inline-flex; align-items: baseline; gap: .3rem;
  padding: .16rem .42rem; border-radius: 5px;
  background: color-mix(in srgb, var(--fg) 5%, transparent);
  font-family: var(--mono); font-size: 10px; color: var(--fg-dim);
}
.hub-fact b { font-weight: 700; color: var(--fg); font-variant-numeric: tabular-nums; }
.hub-fact-none { color: var(--fg-mute); }

/* Inline bar meter — the sparkline slot on a surface card. */
.hub-spark { display: flex; align-items: flex-end; gap: 2px; height: 22px; }
.hub-spark span {
  flex: 1 1 0; min-width: 2px; border-radius: 1px 1px 0 0;
  background: color-mix(in srgb, var(--sec, var(--portal)) 42%, transparent);
  transition: background .3s var(--ease);
}
.hub-surface:hover .hub-spark span { background: color-mix(in srgb, var(--sec, var(--portal)) 78%, transparent); }

/* --- Live band: section content, rendered in place ------------------------ */
.hub-live {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr)); gap: 1px;
  margin-inline: calc(-1 * var(--pad-x));
  background: var(--grid-line);
  border-block: 1px solid var(--grid-line);
  margin-bottom: 2rem;
}
.hub-live-panel { display: flex; flex-direction: column; min-height: 11rem; overflow: hidden; }
.hub-live-head {
  display: flex; align-items: center; gap: .5rem;
  padding: .45rem .8rem;
  border-bottom: 1px solid color-mix(in srgb, var(--sec, var(--portal)) 30%, var(--hairline));
  background: color-mix(in srgb, var(--fg) 3%, transparent);
}
.hub-live-head h3 {
  margin: 0; font: 700 10px/1 var(--mono); letter-spacing: .16em; text-transform: uppercase; color: var(--fg-dim);
}
.hub-live-head .hub-live-n { margin-left: auto; font: 400 10px/1 var(--mono); color: var(--fg-mute); }
.hub-live-head a { font: 400 10px/1 var(--mono); color: var(--fg-mute); text-decoration: none; }
.hub-live-head a:hover { color: var(--sec, var(--portal)); }
.hub-live-body { padding: .5rem .55rem .6rem; display: flex; flex-direction: column; gap: .1rem; overflow: auto; }

/* Rows inside a live panel — whole-row targets, hairline separated, dense. */
.hub-row {
  display: flex; align-items: center; gap: .55rem;
  padding: .4rem .5rem; border-radius: 7px; color: inherit; text-decoration: none;
  transition: background var(--t-fast) var(--ease);
}
.hub-row:hover { background: color-mix(in srgb, var(--fg) 5%, transparent); }
.hub-row-dot {
  width: 6px; height: 6px; border-radius: 999px; flex-shrink: 0;
  background: var(--dot, var(--sec, var(--fg-mute)));
}
.hub-row-name {
  flex: 1; min-width: 0; font-size: 13px; font-weight: 550;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hub-row-meta {
  font-family: var(--mono); font-size: 10px; color: var(--fg-mute); flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}
.hub-row-v {
  font-family: var(--mono); font-size: 11.5px; font-weight: 700; color: var(--fg);
  flex-shrink: 0; font-variant-numeric: tabular-nums;
}
/* Empty states show the SHAPE of what will be — ghost rows, never a lesson
   (the anti-didactic law, entry-13). */
.hub-ghost { display: flex; flex-direction: column; gap: .35rem; padding: .5rem .5rem .3rem; }
.hub-ghost-row {
  display: flex; align-items: center; gap: .55rem; height: 21px;
  opacity: calc(.5 - var(--g, 0) * .12);
}
.hub-ghost-row::before {
  content: ""; width: 6px; height: 6px; border-radius: 999px;
  background: var(--fg-mute); opacity: .5; flex-shrink: 0;
}
.hub-ghost-row::after {
  content: ""; flex: 1; height: 7px; border-radius: 2px;
  background: color-mix(in srgb, var(--fg) 9%, transparent);
}
.hub-ghost-row:nth-child(2)::after { max-width: 74%; }
.hub-ghost-row:nth-child(3)::after { max-width: 52%; }
.hub-ghost-k {
  padding: .1rem .5rem .35rem; font: 400 10px/1.4 var(--mono); color: var(--fg-mute);
}

/* A hub that failed to load says so — never a page of confident zeros. */
.hub-err {
  grid-column: 1 / -1; display: flex; align-items: center; gap: .8rem; flex-wrap: wrap;
  padding: .85rem 1.1rem; font-size: 13px; color: var(--fg-dim);
  background: var(--cell-bg);
  border-top: 1px solid color-mix(in srgb, var(--c-coral-1) 34%, var(--grid-line));
}

@media (max-width: 700px) {
  .hub-head-inner { padding: .85rem .9rem; gap: .7rem; }
  .hub-glyph { width: 38px; height: 38px; font-size: 16px; }
  .hub-title h1 { font-size: 1.2rem; }
  .hub-surfaces { grid-template-columns: 1fr; }
  .hub-live { grid-template-columns: 1fr; }
}

/* =============================================================================
   Board widgets, wearing their section's identity
   -----------------------------------------------------------------------------
   The Dashboard's job is to CONNECT the portal, and a tile that reports from
   Money should say so without a caption. Each widget carries data-tone (set by
   portal-deck.js from the same SECTION_TONE model the nav uses), which drives
   its spine, its glyph and its head rule. Hovering a widget also lights its
   section's cell up in the deck — the two bands are one instrument.
============================================================================= */
body[data-portal] .dash-board .panel { --w-tint: var(--sec, var(--portal)); }
/* The widget spine: 3px, tone-coded, at the leading edge. Same grammar as the
   deck cell and the hub surface — one accent language across three scales. */
.dash-board .panel[data-tone]::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; z-index: 4;
  background: var(--sec); opacity: .4;
  transition: opacity .3s var(--ease);
  pointer-events: none;
}
.dash-board .panel[data-tone]:hover::before { opacity: 1; }
.dash-board .panel-head { padding-left: .95rem; }
/* A widget's section, named once in its head — quiet, mono, right-aligned, so
   the board can be read as "which parts of the portal am I looking at". */
.panel-sec {
  font: 700 8.5px/1 var(--mono); letter-spacing: .15em; text-transform: uppercase;
  color: var(--sec, var(--fg-mute)); opacity: .72; flex-shrink: 0;
  padding: .16rem .34rem; border-radius: 4px;
  background: color-mix(in srgb, var(--sec, var(--fg)) 10%, transparent);
  transition: opacity var(--t-fast) var(--ease);
}
.dash-board .panel:hover .panel-sec { opacity: 1; }
@container (max-width: 20rem) { .panel-sec { display: none; } }
/* The reciprocal cue: hovering a widget raises its section in the deck. */
.deck-cell.echo::before { opacity: 1; }
.deck-cell.echo {
  background-color: color-mix(in srgb, var(--sec) 7%, var(--cell-bg));
  transition: background-color .3s var(--ease);
}

/* The strip sits between the deck and the board — same fascia, no seam. */
.deck + .dash-strip { border-top: none; }
/* …and the reverse: hovering a deck cell raises every widget in that section. */
.dash-board .dw.echo-w { z-index: 4; }
.dash-board .dw.echo-w::before { opacity: 1; }
.dash-board .dw.echo-w {
  box-shadow: inset 0 1px 0 var(--lit),
              0 0 0 1px color-mix(in srgb, var(--sec, var(--portal)) 40%, var(--grid-line)),
              var(--cast);
}
.dash-board .dw.echo-w .panel-sec { opacity: 1; }
