/* ===========================================================================
   SARMENT — Components
   Buttons, nav, panels, tables, badges, fields, figures, card visual, drawer.
   Brutalist: thick borders + hard offset shadows + bold lift on interaction.
   =========================================================================== */

/* --- Navigation items (bottom command bar) --------------------------- */
.nav { display: flex; align-items: center; gap: var(--s-1); }
.nav-item {
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: var(--s-2) var(--s-4);
  border-radius: var(--radius);
  font-weight: 700; font-size: var(--t-sm); letter-spacing: 0.01em;
  color: var(--text-soft);
  border: var(--border-w) solid transparent;
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease),
              border-color var(--dur-fast) var(--ease);
}
.nav-item .ico { font-size: 1rem; }
.nav-item:hover { color: var(--text); background: var(--surface-tint); }
.nav-item.active {           /* inverted block — bold, monochrome */
  color: var(--on-accent);
  background: var(--accent);
  border-color: var(--accent);
}

/* --- Bottom tab bar items -------------------------------------------- */
/* MOBILE FIRST: equal-width, stacked icon over label (thumb targets) */
.tab {
  flex: 1 1 0; min-width: 0; position: relative;
  background: none; border: none; appearance: none;   /* the Alerts <button> tab matches the <a> tabs */
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  min-height: 56px; padding: var(--s-2) 2px;
  color: var(--text-soft); font-size: var(--t-xs); font-weight: 700; letter-spacing: 0.01em;
  text-align: center; white-space: nowrap;
  transition: color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.tab .ico { font-size: 1.3rem; line-height: 1; }
.tab:hover { color: var(--text); }
.tab.active { color: var(--text); background: var(--surface-tint); }
.tab.active::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 2px; background: var(--accent); }
/* the Alerts tab is set off with vertical dividers (left + right), never top/bottom */
.alerts-tab { border-left: 1.5px solid var(--hairline); border-right: 1.5px solid var(--hairline); }

@media (min-width: 721px) {
  /* desktop/tablet: tabs inline + LEFT-aligned, Setup pushed to the right */
  .botnav-inner { justify-content: flex-start; gap: var(--s-1); padding: var(--s-2) var(--s-4); }
  .tab { flex: 0 0 auto; flex-direction: row; gap: var(--s-2); min-height: auto; padding: var(--s-2) var(--s-4); font-size: var(--t-sm); }
  .tab:last-child { margin-left: auto; }   /* Setup flows right */
  .tab.active::before { top: auto; bottom: 0; left: var(--s-3); right: var(--s-3); }
}

/* business chip (right of top nav) */
.opchip {
  display: flex; align-items: center; gap: var(--s-3);
  padding: var(--s-2) var(--s-3); border: var(--border-w) solid var(--border);
  border-radius: var(--radius); background: var(--bg-sunken);
}
.opchip .ava {
  width: 2rem; height: 2rem; flex: none;
  background: var(--accent); color: var(--on-accent);
  display: grid; place-items: center; font-family: var(--font-display); font-weight: 800;
  border-radius: var(--radius);
}
/* mobile: collapse business chip to just the avatar to save the top bar */
.topnav .opchip .col { display: none; }
.topnav .opchip { padding: var(--s-1); border-color: transparent; background: transparent; }
@media (min-width: 561px) {
  .topnav .opchip .col { display: flex; }
  .topnav .opchip { padding: var(--s-2) var(--s-3); border-color: var(--border); background: var(--bg-sunken); }
}


/* --- Buttons ---------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s-2);
  padding: 0.7rem 1.2rem;
  font-weight: 700; font-size: var(--t-sm);
  letter-spacing: 0.01em;
  background: var(--surface); color: var(--text);
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius);
  transition: background var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.btn:hover  { background: var(--surface-tint); border-color: var(--text-soft); }
.btn:active { background: var(--bg-sunken); transform: translateY(1px); }

.btn-primary { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.btn-primary:hover { background: var(--accent-deep); border-color: var(--accent-deep); }
.btn-danger  { background: var(--c-coral); color: #fff; border-color: var(--c-coral); }
/* bright emerald (theme-independent) so the dark label always reads — the token
   --c-mint is tuned for tags/text and is too dark behind near-black button text */
.btn-ok      { background: #34D399; color: #06231A; border-color: #34D399; }
.btn-ok:hover { background: #2BBE85; border-color: #2BBE85; }
.btn-ghost   { background: transparent; border-color: transparent; }
.btn-ghost:hover { background: var(--surface-tint); }
.btn-lg      { padding: 0.95rem 1.6rem; font-size: var(--t-md); }
.btn-block   { width: 100%; }
.btn[disabled] { opacity: 0.4; pointer-events: none; }

/* --- Panels / cards --------------------------------------------------- */
.panel {
  background: var(--surface);
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--s-6);
}
.panel.flat { box-shadow: none; }
.panel.tint { background: var(--surface-tint); }
.panel-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); margin-bottom: var(--s-4); flex-wrap: wrap; }
.panel-title { font-size: var(--t-lg); }

/* delta arrows — used by the Money KPIs (the .figure block it came from was
   removed; StatTile renders the values now). */
.delta.up   { color: var(--c-mint); }
.delta.down { color: var(--c-coral); }

/* --- Badges / status pills ------------------------------------------- */
.tag {
  display: inline-flex; align-items: center; gap: 0.4rem;
  flex: none;                 /* never shrink in a flex row */
  white-space: nowrap;        /* never wrap — "TO DO" stays one line */
  padding: 0.2rem 0.6rem; border-radius: var(--radius-pill);
  font-family: var(--font-mono); font-size: var(--t-xs);
  text-transform: uppercase; letter-spacing: 0.06em; font-weight: 700;
  border: 1.5px solid var(--border);
  background: var(--surface);
}
.tag::before { content: ""; width: 0.5rem; height: 0.5rem; border-radius: 50%; background: var(--text-soft); }
.tag.ok      { background: var(--c-mint-wash); }  .tag.ok::before     { background: var(--c-mint); }
.tag.warn    { background: var(--c-amber-wash); } .tag.warn::before   { background: var(--c-amber); }
.tag.bad     { background: var(--c-coral-wash); } .tag.bad::before    { background: var(--c-coral); }
.tag.sarment   { background: var(--c-sarment-wash); } .tag.sarment::before  { background: var(--accent); }
.tag.plain::before { display: none; }

/* --- Data table ------------------------------------------------------- */
/* fixed layout: columns keep their width regardless of content (no jank as
   rows stream in). Long values truncate — the detail drawer shows them full. */
.tbl { width: 100%; border-collapse: collapse; font-size: var(--t-sm); table-layout: fixed; }
.tbl th {
  text-align: left; padding: var(--s-3) var(--s-4);
  font-family: var(--font-mono); font-size: var(--t-xs); text-transform: uppercase;
  letter-spacing: var(--track-wide); color: var(--text-soft);
  border-bottom: var(--border-w) solid var(--border);
  white-space: nowrap;
}
.tbl td { padding: var(--s-3) var(--s-4); border-bottom: 1.5px solid var(--hairline); vertical-align: middle; overflow: hidden; white-space: nowrap; }
.tbl td.ell { text-overflow: ellipsis; } /* long text columns (party, detail) truncate */
.tbl tbody tr { transition: background var(--dur-fast) var(--ease); }
.tbl tbody tr:hover { background: var(--surface-tint); }
.tbl .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right; }
/* mobile: let wide tables scroll horizontally inside their panel */
@media (max-width: 640px) {
  .panel { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .tbl { min-width: 520px; }
}
/* scroll region for long tables — list scrolls inside the panel, header sticks.
   Inner scrollbar is hidden (still scrolls via wheel/touch): the pagination
   footer "Showing X of Y" is the affordance, and a hidden bar avoids the
   janky thumb-resize as rows stream in. */
/* always fits ~10 rows: floor 34rem (≈10), grows toward 64dvh on tall screens,
   capped at 48rem. Never collapses, even when a tall section sits above it. */
.tscroll { max-height: clamp(34rem, 64dvh, 48rem); overflow: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none; overscroll-behavior: contain; scroll-behavior: smooth; }
.tscroll::-webkit-scrollbar { width: 0; height: 0; }
.tscroll thead th { position: sticky; top: 0; background: var(--surface); z-index: 1; }

/* list-focus pages: just trim the trailing space (main is the scroll viewport) */
.page-fill { padding-bottom: var(--s-4); }

/* --- Flow stream (explorer) affordances ------------------------------- */
/* live-feed buffer banner — "N new · load latest" (new arrivals don't shift the
   page you're reading; tap to merge + jump to top). */
.newpill {
  display: block; width: 100%; margin-top: var(--s-3); padding: 0.55rem var(--s-4);
  background: var(--accent); color: var(--on-accent); border: var(--border-w) solid var(--accent);
  font-family: var(--font-mono); font-size: var(--t-xs); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em; cursor: pointer;
  animation: rise var(--dur) var(--ease-out) both;
}
.newpill:hover { background: var(--accent-deep); border-color: var(--accent-deep); }
/* result legend — per-status counts for the current filter */
.streamsum { display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-4); margin: var(--s-3) 0 var(--s-4); color: var(--text-soft); font-family: var(--font-mono); font-size: var(--t-xs); }
.streamsum b { color: var(--text); font-weight: 700; }

/* ===== skeleton loaders =====
   A shimmer block: a faint surface fill with a light sweep passing across it.
   `.skel-line` height is em-based so a bar inherits the size of whatever text
   context it sits in (cell text vs a big `.stat .v`). Bars never wrap. */
@keyframes skel-sweep { from { background-position: -150% 0; } to { background-position: 150% 0; } }
.skel {
  background-color: color-mix(in srgb, var(--text-soft) 14%, transparent);
  background-image: linear-gradient(90deg, transparent 0%, color-mix(in srgb, var(--text-soft) 20%, transparent) 50%, transparent 100%);
  background-size: 220% 100%;
  background-repeat: no-repeat;
  animation: skel-sweep 1.2s var(--ease) infinite;
  border-radius: 2px;
  pointer-events: none;
}
.skel-line { display: inline-block; height: 0.72em; width: 100%; vertical-align: middle; }
.skel-tag { display: inline-block; height: 1.35rem; vertical-align: middle; }
.skel-btn { display: block; height: 2.4rem; width: 100%; }
@media (prefers-reduced-motion: reduce) { .skel { animation: none; } }
/* directional amount — IN credits read mint, OUT spends stay neutral */
.flow-in { color: var(--c-mint); }
.flow-out { color: var(--text); }
/* Recall = balance clawed back to the operating pool on suspension (a
   withdrawal) — flag the amount red, distinct from green inflows. */
.flow-recall { color: var(--c-coral); }
/* status cell — uniform-width status tag so every row's Status column lines up
   (shared by Flow + Cards). Type tags size to content (compact, no empty box). */
.statuscell { display: inline-flex; align-items: center; }
/* Type + Status tags share one uniform min-width so the two columns read the
   same (same box size for the content). */
.statuscell .tag { min-width: 7rem; justify-content: flex-start; }
/* Type labels are short (SPEND/DEPOSIT). A 7rem floor was wider than the narrow
   Type column, so the tag bled into Tx hash. Smaller uniform floor + trimmed
   cell side-padding keeps Type tags uniform AND inside their column. */
.tbl td[data-label="Type"] .tag { min-width: 5.5rem; justify-content: flex-start; }
.tbl td[data-label="Type"] { padding-left: var(--s-3); padding-right: var(--s-3); }
/* table-general: no tag may exceed its cell, so a content-sized tag can never
   bleed into the next column. Columns whose tag carries a min-width floor must
   be sized to fit it — the schemas in `components::table` enforce that. */
.tbl td .tag { max-width: 100%; }
/* Reserve the status-dot slot even on dot-less (plain) tags — SPEND/Reversed
   have no dot, so without this their label starts ~0.9rem left of dotted tags
   (REDEEM/PREFUND) and the column reads ragged. Keep the box, just don't paint
   it, so every label left-aligns to the same x. */
.statuscell .tag.plain::before,
.tbl td[data-label="Type"] .tag.plain::before { display: block; visibility: hidden; }
/* keyboard-operable rows: visible focus ring */
.tbl tbody tr.rowclick { cursor: pointer; }
.tbl tbody tr.rowclick:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; background: var(--surface-tint); }
/* compact inline badges in the Detail cell (dispute state / reversal) */
.tag.mini { padding: 0.1rem 0.4rem; font-size: 0.6rem; margin-left: var(--s-2); gap: 0.3rem; }
.tag.mini::before { width: 0.4rem; height: 0.4rem; }

/* --- Form fields ------------------------------------------------------ */
.field { display: flex; flex-direction: column; gap: var(--s-2); }
.field > label { font-weight: 600; font-size: var(--t-sm); }
.field .hint { font-size: var(--t-xs); color: var(--text-soft); }
.input, .select {
  width: 100%;
  padding: 0.8rem 0.9rem;
  background: var(--bg);
  color: var(--text);
  border: var(--border-w) solid var(--border);
  border-radius: var(--radius);
  transition: box-shadow var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.input::placeholder { color: color-mix(in srgb, var(--text-soft) 80%, transparent); }
.input:focus, .select:focus { outline: none; box-shadow: var(--shadow-accent); }
.input.mono { font-family: var(--font-mono); }
/* strip the OS number-spinner (can't be themed, clashes with the flat look) —
   the pager has its own ‹/› + jump field; type directly to set a page. */
.input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
.input[type="number"]::-webkit-outer-spin-button,
.input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* custom select — replaces native <select> (OS dropdown can't be themed) */
.cselect { position: relative; }
.cselect-trigger {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: var(--s-2);
  padding: 0.8rem 0.9rem;
  background: var(--bg); color: var(--text);
  border: var(--border-w) solid var(--border); border-radius: var(--radius);
  font: inherit; text-align: left; cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease);
}
.cselect-trigger:hover { border-color: var(--text-soft); }
.cselect.open .cselect-trigger { border-color: var(--accent); }
.cselect-chev { color: var(--text-soft); transition: transform var(--dur-fast) var(--ease); }
.cselect.open .cselect-chev { transform: rotate(180deg); }
.cselect-menu {
  list-style: none; margin: 4px 0 0; padding: 0;
  background: var(--surface); border: var(--border-w) solid var(--border);
  max-height: 240px; overflow: auto;
}
.cselect-opt {
  display: flex; align-items: center; gap: var(--s-2);
  padding: 0.7rem 0.9rem; cursor: pointer;
  border-bottom: 1.5px solid var(--hairline);
}
.cselect-opt:last-child { border-bottom: none; }
.cselect-opt:hover { background: var(--surface-tint); }
.cselect-opt.sel { background: var(--surface-tint); }
.cselect-opt::before { content: ""; width: 1ch; color: var(--accent); }
.cselect-opt.sel::before { content: "✓"; }

/* segmented control (.seg, often 4-5 status options) + tabset (.tabset, 2-3
   inline tabs) — one shared button style; only the container chrome differs. */
.seg, .tabset { display: inline-flex; border: var(--border-w) solid var(--border); }
.seg { border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm); }
.seg button, .tabset > button { padding: 0.55rem 1rem; font-weight: 700; font-size: var(--t-sm); background: var(--surface); border: none; border-right: 1.5px solid var(--border); white-space: nowrap; }
.seg button:last-child, .tabset > button:last-child { border-right: none; }
.seg button.on, .tabset > button.on { background: var(--accent); color: var(--on-accent); }
/* wrapping variant — the status seg inside the Stream Filters disclosure: fills
   the row and wraps to 2 rows on narrow screens instead of overflowing */
.seg.wrap { display: flex; width: 100%; }
.seg.wrap > button { flex: 1 1 auto; }

/* two-axis filter bar (type + status), each a labelled segmented control */
.filterbar { display: flex; gap: var(--s-5); flex-wrap: wrap; align-items: flex-end; }
.filtergrp { display: flex; flex-direction: column; gap: var(--s-2); }

/* toggle switch */
.switch { position: relative; width: 3.2rem; height: 1.7rem; flex: none; }
.switch input { position: absolute; opacity: 0; }
.switch .track {
  position: absolute; inset: 0; background: var(--bg-sunken);
  border: var(--border-w) solid var(--border); border-radius: var(--radius-pill);
  transition: background var(--dur) var(--ease);
}
.switch .track::after {
  content: ""; position: absolute; top: 1px; left: 1px;
  width: calc(1.7rem - 6px); height: calc(1.7rem - 6px);
  background: var(--text); border-radius: 0;
  transition: transform var(--dur) var(--ease);
}
.switch input:checked + .track { background: var(--accent); }
.switch input:checked + .track::after { transform: translateX(1.5rem); background: var(--on-accent); }

/* --- Card visual (the issued card mockup) ----------------------------- */
.cardface {
  position: relative; aspect-ratio: 1.586 / 1; width: 100%;
  border: var(--border-w) solid var(--border);
  border-radius: 0;
  padding: var(--s-5);
  display: flex; flex-direction: column; justify-content: space-between;
  background: var(--surface-tint);
  color: var(--text);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease);
}
.cardface::after {
  content: ""; position: absolute; right: -30px; bottom: -40px;
  width: 180px; height: 180px; border-radius: 50%;
  background: rgba(255,255,255,0.03);
}
.cardface:hover { border-color: var(--text-soft); }
.cardface.frozen { opacity: 0.55; }
.cardface .pan { font-family: var(--font-mono); font-size: 1.25rem; letter-spacing: 0.12em; }
.cardface .net { font-family: var(--font-display); font-weight: 800; font-size: 1.15rem; letter-spacing: var(--track-tight); }
.cardface .chip { width: 2.4rem; height: 1.8rem; border-radius: 0; background: var(--text-soft); opacity: 0.5; }

/* --- Drawer (slide-in for create flows) ------------------------------ */
.scrim {
  position: fixed; inset: 0; background: color-mix(in srgb, var(--c-ink) 55%, transparent);
  opacity: 0; pointer-events: none; transition: opacity var(--dur) var(--ease); z-index: var(--z-scrim);
}
.scrim.open { opacity: 1; pointer-events: auto; }
.drawer {
  position: fixed; top: 0; right: 0; height: 100dvh; width: min(460px, 92vw);
  background: var(--surface); border-left: var(--border-w-thick) solid var(--border);
  box-shadow: var(--shadow-lg);
  transform: translateX(103%); transition: transform var(--dur) var(--ease);
  z-index: var(--z-drawer); display: flex; flex-direction: column;
}
.drawer.open { transform: translateX(0); }
.drawer.wide { width: min(680px, 96vw); }
.scrim.top { z-index: var(--z-scrim-2); }
.drawer.top { z-index: var(--z-drawer-2); }
/* Alerts/notifications drawer — TOP layer, above every modal/sheet/drawer, so
   the notification panel is never covered by anything. */
.drawer.alerts { z-index: var(--z-alerts); }
.alerts-scrim { position: fixed; inset: 0; z-index: calc(var(--z-alerts) - 1); background: color-mix(in srgb, var(--c-ink) 55%, transparent); opacity: 0; pointer-events: none; transition: opacity var(--dur) var(--ease); }
.alerts-scrim.open { opacity: 1; pointer-events: auto; }
/* mobile: drawers go full-screen (no sliver of page behind) */
@media (max-width: 560px) { .drawer, .drawer.wide { width: 100vw; border-left: none; } }
.drawer-head { display: flex; align-items: center; justify-content: space-between; padding: var(--s-5); border-bottom: var(--border-w) solid var(--border); }
.drawer-body { padding: var(--s-5); overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; scroll-behavior: smooth; display: flex; flex-direction: column; gap: var(--s-5); flex: 1 1 auto; min-height: 0; }
/* the BODY is the single scroll region: children keep their natural height so a
   long detail scrolls as one. Without this the flex column shrinks each card and
   (with the mobile .panel overflow rule) turns every card into its own scroller. */
.drawer-body > * { flex: none; }
.drawer-body .panel { overflow: visible; }
.drawer-foot { margin-top: auto; padding: var(--s-5); padding-bottom: calc(var(--s-5) + env(safe-area-inset-bottom, 0px)); border-top: var(--border-w) solid var(--border); display: flex; gap: var(--s-3); flex-wrap: wrap; }
.iconbtn { width: 2.4rem; height: 2.4rem; display: grid; place-items: center; border: var(--border-w) solid var(--border); border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow-sm); }
.iconbtn:hover { background: var(--surface-tint); }

/* --- Misc ------------------------------------------------------------- */
.divider { height: var(--border-w); background: var(--border); border: none; margin: var(--s-5) 0; }
.kv { display: flex; justify-content: space-between; gap: var(--s-4); padding: var(--s-2) 0; border-bottom: 1.5px solid var(--hairline); }
.kv .k { color: var(--text-soft); font-size: var(--t-sm); flex: none; }
.kv.step-current { box-shadow: inset 2px 0 0 var(--accent); padding-left: var(--s-3) !important; }

/* click-to-copy id/hash */
.copyable { display: inline-flex; align-items: center; gap: 0.45rem; cursor: pointer; min-width: 0; max-width: 100%; vertical-align: bottom; }
.copyable .copyable-text { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.copyable .copyable-ico { flex: none; }
.copyable.nocopy { cursor: inherit; }
.copyable.nocopy:hover .copyable-text { color: inherit; }
.copyable-ico { color: var(--text-soft); font-size: 0.85em; transition: color var(--dur-fast) var(--ease); }
.copyable:hover .copyable-text, .copyable:hover .copyable-ico { color: var(--accent); }
.kv .v { font-family: var(--font-mono); font-size: var(--t-sm); flex: 1; min-width: 0; text-align: right; overflow-wrap: anywhere; }
.empty { text-align: center; padding: var(--s-8) var(--s-4); color: var(--text-soft); }
.empty .big { font-family: var(--font-display); font-size: var(--t-xl); color: var(--text); margin-bottom: var(--s-2); }
@media (max-width: 560px) { .empty { padding: var(--s-6) var(--s-4); } }   /* less towering on phones */
/* inside the Alerts drawer the "All clear" state shouldn't dominate — it sits
   above the Compliance section, so keep it compact (no towering whitespace). */
.alerts .empty { padding: var(--s-5) var(--s-4); }
.alerts .empty .big { font-size: var(--t-lg); margin-bottom: var(--s-1); }

/* ===========================================================================
   Reusable components (Modal, Tabset, StatTile, Toast, Approval, Chips)
   Backing classes for src/components/{modal,segmented,stat,toast}.rs.
   =========================================================================== */

/* StatTile */
.stat { display: flex; flex-direction: column; gap: var(--s-2); }
.stat .v { font-family: var(--font-mono); font-weight: 700; font-size: var(--t-xxl); letter-spacing: -0.03em; }
/* a clickable stat tile (e.g. Holders → opens the holders list) */
.statbtn { text-align: left; cursor: pointer; transition: border-color var(--dur-fast) var(--ease); }
.statbtn:hover { border-color: var(--text-soft); }

/* KPI tiles (Cards page): a flex row — 2-up on phones (the pending tile drops to
   its own full-width line), 3-up at ≥561 so the pending tile sits inline as the
   third. When the queue is empty the pending tile collapses to nothing: on
   phones its line is 0-height (row-gap 0 → no ghost gap); on wider screens its
   basis goes to 0 so Active/Holders fill the row 2-up. Basis math matches the
   column-gap exactly so 3 tiles never wrap. */
.kpis2 { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-4); }
.kpis2 > .kpi-pending { grid-column: 1 / -1; }   /* phone: pending on its own full-width row */
@media (min-width: 561px) {
  /* tablet/laptop: a stable 3-column grid. Pending is the 3rd cell; when the
     queue is empty its tile is unmounted and the 3rd cell is simply blank —
     Active + Holders keep their 1/3 width (no reflow to 2-up). */
  .kpis2 { grid-template-columns: repeat(3, 1fr); }
  .kpis2 > .kpi-pending { grid-column: auto; }
}
/* pending tile is conditionally rendered (Show) so the grid always has exactly
   the cells it needs — no reserved gap. It eases in when the queue appears. */
.kpi-pending { animation: rise var(--dur) var(--ease-out) both; }
/* KPI tiles stay compact through tablet too (not just phones) so they don't eat
   vertical space — full padding/size only returns on laptop+ */
@media (max-width: 860px) {
  .panel.stat { padding: var(--s-4); }
  .stat .v { font-size: var(--t-xl); }
}

/* Notification bell + badge */
.bell { position: relative; font-size: 1.1rem; }
.badge {
  position: absolute; top: -7px; right: -9px; min-width: 1.15rem; height: 1.15rem; padding: 0 0.25rem;
  background: var(--c-coral); color: #fff; font-family: var(--font-mono); font-size: 0.62rem;
  display: grid; place-items: center; border: 1.5px solid var(--surface);
}

/* Approval focus card (speed) */
.appfocus { border-color: var(--accent) !important; padding: var(--s-4) var(--s-5); }
.bigamt { font-family: var(--font-mono); font-weight: 700; font-size: var(--t-xl); letter-spacing: -0.03em; line-height: 1; }
.countbar { height: 6px; width: 9rem; background: var(--bg-sunken); border: 1.5px solid var(--border); overflow: hidden; }
.countbar > i { display: block; height: 100%; width: 100%; transform-origin: left; background: var(--accent); transition: transform 0.95s linear, background 0.95s linear; }
.decide { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-3); margin-top: var(--s-4); }
.decide .btn { padding: 0.8rem; font-size: var(--t-md); }
/* phones: keep both buttons on one line + shorter (rectangle, not chunky) */
@media (max-width: 560px) {
  .decide { margin-top: var(--s-4); }
  .decide .btn { padding: 0.7rem; font-size: var(--t-sm); }
  .decide .key { display: none; }
}
.key { font-family: var(--font-mono); font-size: var(--t-xs); opacity: 0.7; margin-left: 0.45rem; }
.nextrow { display: flex; align-items: center; gap: var(--s-4); padding: var(--s-3) 0; border-bottom: 1.5px solid var(--hairline); }
.nextrow:last-child { border-bottom: none; }
.nextrow .who { font-weight: 700; min-width: 8ch; }
.nextrow .amt { font-family: var(--font-mono); margin-left: auto; white-space: nowrap; }
/* up-next rows as aligned columns: party · merchant · tag · amount.
   container grid + subgrid so EVERY row shares the same 4 track widths
   (names line up, merchants line up, amounts line up); the tag column is one
   shared track and each pill stretches to fill it → all tags render the same
   width (no ragged HIGH-RISK-MCC vs NEW-MERCHANT edges). */
.qlist { display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto; gap: var(--s-4); }
.qrow { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; align-items: center; }
.qrow > * { min-width: 0; }
.qrow .who { font-weight: 700; white-space: nowrap; }
.qrow .ell { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qrow .tag { justify-self: stretch; justify-content: center; min-width: 10rem; }
.qrow .amt { font-family: var(--font-mono); text-align: right; white-space: nowrap; }
@media (max-width: 560px) {
  .qlist { gap: var(--s-3); }
  .qrow .tag { min-width: 0; padding: 0.2rem 0.5rem; font-size: 0.6rem; }
}
.nextrow.click { cursor: pointer; }
.nextrow.click:hover { background: var(--surface-tint); }

/* Toast host (transient notifications) — slides in AND out (mounted always,
   .show toggles): translateY off-screen + fade when hidden, eases to rest when
   shown. Also glides on `bottom` to clear an open sheet. */
.toasthost {
  position: fixed; left: 0; right: 0; bottom: calc(var(--botnav-h) + var(--s-3));
  display: flex; justify-content: center; padding: 0 var(--s-4); z-index: var(--z-toast); pointer-events: none;
  transform: translateY(160%); opacity: 0;
  transition: transform var(--dur) var(--ease-out), opacity var(--dur) var(--ease-out), bottom var(--dur) var(--ease);
}
.toasthost.show { transform: translateY(0); opacity: 1; }
.toast {
  position: relative; overflow: hidden;
  pointer-events: auto; display: flex; align-items: center; flex-wrap: wrap; gap: var(--s-2) var(--s-3);
  width: 100%; max-width: var(--maxw); background: var(--surface);
  border: var(--border-w) solid var(--accent); box-shadow: var(--shadow-lg); padding: var(--s-3) var(--s-4);
}
.toast > *:not(.toast-cd) { position: relative; z-index: 1; }
.toast .amt { font-family: var(--font-mono); white-space: nowrap; }
.toast .grow { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* actions stay together (right-aligned on one line when they fit). On phones
   they wrap to a full-width second row and split it, so "Approve" is never
   clipped by the toast's overflow:hidden. */
.toast-actions { display: flex; align-items: center; gap: var(--s-2); margin-left: auto; }
@media (max-width: 560px) {
  .toast-actions { flex: 1 1 100%; margin-left: 0; }
  .toast-actions > .btn { flex: 1; }
}
/* alert countdown — a draining amber→red bar behind the toast content (the
   ~6s auth window). Re-mounts (restarts) each time the auth changes. */
/* approval countdown (~6s auth window) — width + colour driven reactively from
   store.auth_secs (so the toast + focus card always show the SAME remaining
   time, even when opened mid-window). Transition smooths each 1s step. */
.toast-cd {
  position: absolute; inset: 0; z-index: 0; pointer-events: none; transform-origin: left;
  background: color-mix(in srgb, var(--accent) 24%, transparent);
  transition: transform 0.95s linear, background 0.95s linear;
}

/* Pager (replaces "Load more") — compact bar + a bottom sheet for size/jump */
.pager { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); margin-top: var(--s-4); flex-wrap: wrap; }
.pager .count { color: var(--text-soft); font-family: var(--font-mono); font-size: var(--t-sm); }
.pager-ctl { display: flex; align-items: center; gap: var(--s-2); }
.pager-page { padding: 0.5rem 0.9rem; border: var(--border-w) solid var(--border); background: var(--surface); font-family: var(--font-mono); font-size: var(--t-sm); font-weight: 700; }
.pager-page:hover { background: var(--surface-tint); }
.pager .iconbtn { width: 2.2rem; height: 2.2rem; font-size: 1.1rem; }
/* bottom sheet (slides up) — rows-per-page + page jump */
/* page/rows sheet is the TOP layer — it can be opened from inside a drawer
   (e.g. the Holders directory), so it must stack above drawers (45/65) and
   modals, and its scrim must dim them. */
.sheet-scrim {
  position: fixed; inset: 0; z-index: calc(var(--z-sheet) - 1);
  background: color-mix(in srgb, var(--c-ink) 55%, transparent);
  opacity: 0; pointer-events: none; transition: opacity var(--dur) var(--ease);
}
.sheet-scrim.open { opacity: 1; pointer-events: auto; }
.sheet {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-sheet);
  background: var(--surface); border-top: var(--border-w) solid var(--border);
  transform: translateY(101%); transition: transform var(--dur) var(--ease);
  max-width: var(--maxw); margin: 0 auto;
}
.sheet.open { transform: translateY(0); }
.sheet-head { display: flex; align-items: center; justify-content: space-between; padding: var(--s-3) var(--s-4); border-bottom: var(--border-w) solid var(--border); }
/* compact: rows-per-page + jump-to-page sit side by side on one line, wrap when narrow */
.sheet-body { padding: var(--s-3) var(--s-4); display: flex; flex-flow: row wrap; align-items: flex-end; gap: var(--s-3) var(--s-5); padding-bottom: calc(var(--s-3) + env(safe-area-inset-bottom, 0px)); }
.sheet-grp { flex: 1 1 300px; min-width: 0; display: flex; flex-direction: column; gap: var(--s-1); }
/* phones: keep them stacked + full-width, content-height (basis is read as
   height in a column, so reset it — otherwise the groups grow tall) */
@media (max-width: 560px) {
  .sheet-body { flex-direction: column; align-items: stretch; }
  .sheet-grp { flex: 0 0 auto; }
}
.sheet-body .seg { width: 100%; }
/* smaller + equal heights so the seg + jump input align on the row */
.sheet-body .seg button { flex: 1; padding: 0.55rem 0.8rem; }
.sheet-body .input { padding: 0.55rem 0.8rem; }
/* jump-to-page: a fixed-width input (fits 1 … 100000 — 6 digits — so the layout
   is static regardless of page count) + the "of N" label, which keeps its own
   room and never gets cramped. Left-aligned group, not stretched full-width. */
.pager-jump { display: flex; align-items: center; gap: var(--s-3); }
.sheet-body .pager-jump .input { width: 7.5rem; flex: 0 0 7.5rem; text-align: center; }
.pager-cur { font-family: var(--font-mono); font-weight: 700; white-space: nowrap; color: var(--text-soft); }

/* link-styled button (action that looks like an inline link, e.g. "Review now →") */
.linkbtn { background: none; border: none; padding: 0; cursor: pointer; color: inherit; text-align: left; align-self: flex-start; font-size: var(--t-sm); font-weight: 700; }
.linkbtn:hover { color: var(--accent); }

/* inline-filter syntax hint under the search bar (replaces the filter buttons) */
.searchhint { color: var(--text-soft); font-family: var(--font-mono); font-size: var(--t-xs); margin: 0 0 var(--s-4); line-height: var(--lh-snug); }

/* floating filter panel — drops in-place below the search bar on focus (anchored
   to the .searchwrap, not a fullscreen takeover), over a modal-style dimmed
   backdrop. When open the wrapper is raised above the scrim so the bar + panel
   stay lit while the rest of the page is dimmed. */
.searchwrap { position: relative; }
.searchwrap.popopen { z-index: var(--z-popover); }
.searchwrap.popopen .input { position: relative; z-index: 2; }
.searchscrim { position: fixed; inset: 0; z-index: 1; background: color-mix(in srgb, var(--c-ink) 55%, transparent); }
.searchpop {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 2;
  background: var(--surface); border: var(--border-w) solid var(--border);
  box-shadow: 0 12px 32px color-mix(in srgb, var(--c-ink) 50%, transparent);
  padding: var(--s-4); display: flex; flex-direction: column; gap: var(--s-3);
  max-height: 70vh; overflow-y: auto;
}

/* uniform-width status tags in a KYC column so the column reads clean */
.kyc-cell .tag { min-width: 7.5rem; justify-content: flex-start; }

/* Filter chips + advanced */
.chips { display: flex; gap: var(--s-2); flex-wrap: wrap; align-items: center; }
.chip {
  display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.25rem 0.6rem;
  background: var(--surface-tint); border: 1.5px solid var(--border);
  font-family: var(--font-mono); font-size: var(--t-xs);
}
.chip b { cursor: pointer; color: var(--text-soft); }
.advanced { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--s-3); }

/* Centered modal (stackable) */
.mscrim {
  position: fixed; inset: 0; background: color-mix(in srgb, var(--c-ink) 58%, transparent);
  display: grid; place-items: center; padding: var(--s-5); z-index: var(--z-modal);
  animation: fadein var(--dur) var(--ease) both;   /* scrim fades in */
}
.mscrim.l2 { background: color-mix(in srgb, var(--c-ink) 38%, transparent); z-index: var(--z-modal-2); }
.modal {
  background: var(--surface); border: var(--border-w-thick) solid var(--border); box-shadow: var(--shadow-lg);
  width: min(760px, 96vw); max-height: 90vh; display: flex; flex-direction: column;
  animation: slideup var(--dur) var(--ease-out) both;   /* slides up into place */
}
.modal.sm { width: min(460px, 96vw); }
.modal.lg { width: min(920px, 96vw); }
.modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s-4); padding: var(--s-5); border-bottom: var(--border-w) solid var(--border); }
.modal-body { padding: var(--s-5); display: flex; flex-direction: column; gap: var(--s-5); overflow: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; scroll-behavior: smooth; }
.modal-foot { padding: var(--s-5); border-top: var(--border-w) solid var(--border); display: flex; gap: var(--s-3); flex-wrap: wrap; }
/* mobile: big modals go full-screen, but a small CONFIRM modal stays a compact,
   centered, screen-aware card (auto height, capped + scrollable, margin around). */
@media (max-width: 640px) {
  .modal, .modal.lg { width: 100vw; height: 100dvh; max-height: none; }
  .modal.sm { width: min(420px, 92vw); height: auto; max-height: 88dvh; }
}

/* Card row (inside holder hub modal) */
.cardrow { display: grid; grid-template-columns: minmax(0, 1.4fr) auto minmax(0, 0.9fr) auto auto; align-items: center; gap: var(--s-3); padding: var(--s-3); border: 1.5px solid var(--hairline); background: var(--bg-sunken); }
.cardrow > * { white-space: nowrap; min-width: 0; overflow: hidden; text-overflow: ellipsis; }  /* network·form ("Visa · Tokenized") never wraps */
.cardrow + .cardrow { margin-top: var(--s-2); }
@media (max-width: 560px) {
  .cardrow { grid-template-columns: 1fr auto auto; }   /* token · status · Manage on one line */
  .hide-sm { display: none !important; }
  /* tables become stacked cards (label : value) — mobile first */
  .tbl, .tbl tbody, .tbl tr, .tbl td { display: block; }
  .tbl thead { display: none; }
  .tbl { min-width: 0; }
  .tbl tr { border: var(--border-w) solid var(--hairline); background: var(--surface); padding: var(--s-2) var(--s-4); margin-bottom: var(--s-3); }
  .tbl tr:hover { background: var(--surface); }
  .tbl td { border: none; padding: var(--s-1) 0; display: flex !important; align-items: center; justify-content: space-between; gap: var(--s-3); white-space: normal; width: auto !important; min-width: 0; text-align: left !important; overflow: hidden; }
  .tbl td.hide-sm { display: flex !important; } /* show every field in card mode */
  .tbl td::before { content: attr(data-label); flex: none; color: var(--text-soft); font-family: var(--font-mono); font-size: var(--t-xs); text-transform: uppercase; letter-spacing: var(--track-wide); }
  .tbl td:empty { display: none !important; }
  /* the value side must be able to shrink + truncate so a stacked row can never
     force the table wider than the screen (no horizontal page overflow) */
  .tbl td > * { min-width: 0; max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
  /* the desktop uniform-tag min-widths don't apply when stacked (they'd force
     the row wide); let Type/Status tags size to their own content here */
  .statuscell .tag, .tbl td[data-label="Type"] .tag { min-width: 0; }
}

/* shown only on phones — the dropdown that replaces a status Segmented (≤560) */
.only-sm { display: none; }

/* ===========================================================================
   MOBILE-FIRST DENSITY (≤560px)
   Desktop spacing (2rem panel padding, big stat numbers) wastes a phone's
   width + height. Mobile-first principle: content fills the screen, chrome
   doesn't. Trim panel padding, flatten nested panels, compact the stat tiles,
   and stack key/value rows (so a long value can't overlap its label).
   =========================================================================== */
@media (max-width: 560px) {
  .panel { padding: var(--s-4); }
  .panel .panel { padding: var(--s-3); }          /* nested cards: tighter still */
  .panel-head { margin-bottom: var(--s-3); }

  /* KPI tiles: tighter gap on phones (padding + value size already trimmed at ≤860) */
  .stat { gap: var(--s-1); }

  /* key/value rows stack vertically — label on top, value below: never overlap
     on a narrow column (fixes long values like "USDC · cross-chain (ISMP)").
     !important beats inline align-items:center on the Setup KYB step rows. */
  .kv { flex-direction: column; align-items: stretch !important; gap: 2px; padding: var(--s-3) 0; }
  .kv .k { flex: none; }
  .kv .v { text-align: left; }

  /* trim the vertical rhythm between stacked sections */
  .mt-5 { margin-top: var(--s-4); }
  .mt-7 { margin-top: var(--s-5); }

  /* drawers (detail / holder folder): tighter padding + gaps so the stacked
     cards aren't mostly whitespace on a phone. Footer-less drawers (alerts,
     holders, tx-detail) clear the browser chrome via the bottom safe-area inset. */
  .drawer-head { padding: var(--s-4); padding-top: max(var(--s-4), env(safe-area-inset-top, 0px)); }
  .drawer-body { padding: var(--s-4); gap: var(--s-3); padding-bottom: calc(var(--s-5) + env(safe-area-inset-bottom, 0px)); }

  /* FILTERS (mobile): a 4-5 way status Segmented can't fit a phone row, so its
     buttons hide and Segmented swaps in a compact dropdown (.cselect.only-sm),
     full-width below search. Tabsets (2-3 tabs) stay visible and fill the row. */
  .only-sm { display: block; }
  .cselect.only-sm { flex: 1 1 100%; margin-top: var(--s-2); }
  .tabset { display: flex; width: 100%; }
  .tabset > button { flex: 1; }
  .advanced { grid-template-columns: 1fr 1fr; gap: var(--s-3); }
  /* search fields fill the row on phones (desktop max-width is dropped) */
  .search { max-width: none !important; width: 100%; flex: 1 1 100%; }
}

/* Choice card (e.g. the "+ New" Wallet/Card picker) */
.choice {
  display: flex; align-items: center; gap: var(--s-4); width: 100%; text-align: left;
  padding: var(--s-4) var(--s-5); background: var(--surface); border: var(--border-w) solid var(--border);
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.choice:hover { border-color: var(--accent); background: var(--surface-tint); }
.choice .ico { flex: none; width: 2.6rem; height: 2.6rem; display: grid; place-items: center; font-size: 1.5rem; border: 1.5px solid var(--border); }
.choice .body { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.choice .body strong { font-size: var(--t-md); }
.choice .arrow { color: var(--text-soft); font-size: 1.1rem; transition: transform var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
.choice:hover .arrow { color: var(--accent); transform: translateX(3px); }

/* --- Auth / login screen --------------------------------------------- */
.auth { display: grid; grid-template-columns: 1.05fr 1fr; min-height: 100vh; }
.auth-brand {
  background: var(--surface-tint); color: var(--text);
  border-right: var(--border-w) solid var(--border);
  padding: var(--s-8) var(--s-7);
  display: flex; flex-direction: column; justify-content: space-between;
  position: relative; overflow: hidden;
}
.auth-brand::after {
  content: ""; position: absolute; right: -120px; top: -60px;
  width: 420px; height: 420px; border-radius: 50%; background: rgba(255,255,255,0.03);
}
.auth-brand .wordmark { font-family: var(--font-display); font-weight: 800; font-size: var(--t-mega); line-height: 0.9; letter-spacing: -0.045em; }
.auth-brand .tagline { font-size: var(--t-lg); max-width: 22ch; line-height: var(--lh-snug); }
.auth-brand .foot { font-family: var(--font-mono); font-size: var(--t-xs); letter-spacing: var(--track-wide); text-transform: uppercase; opacity: 0.85; }
.auth-brand .pillset { display: flex; gap: var(--s-2); flex-wrap: wrap; margin-top: var(--s-5); }
.auth-brand .pillset .tag { background: var(--surface); color: var(--text); border-color: var(--border); }
.auth-brand .pillset .tag::before { background: var(--text-soft); }
.auth-form { display: flex; align-items: center; justify-content: center; padding: var(--s-7); }
.auth-card { width: min(420px, 100%); display: flex; flex-direction: column; gap: var(--s-5); }
.auth-card h1 { font-size: var(--t-xxl); }
@media (max-width: 820px) {
  .auth { grid-template-columns: 1fr; }
  .auth-brand { min-height: 36vh; }
}

/* --- Error fallback (runtime panic hook + 404 route) ------------------- */
.errpage { min-height: 100vh; display: grid; place-items: center; padding: var(--s-6); background: var(--bg); }
.errcard { width: min(34rem, 100%); display: flex; flex-direction: column; align-items: flex-start; gap: var(--s-4); }
.errcard h1 { font-size: var(--t-xxl); }
.errcard p { color: var(--text-soft); max-width: 42ch; line-height: var(--lh-body); }
.errsign { width: 3rem; height: 3rem; display: grid; place-items: center; border: var(--border-w) solid var(--c-coral); color: var(--c-coral); font-family: var(--font-display); font-weight: 800; font-size: 1.6rem; }

/* --- Design-system showcase (/design-system) ------------------------- */
.hero { padding: var(--s-9) var(--s-6) var(--s-7); max-width: var(--maxw); margin: 0 auto; }
.hero h1 { font-size: var(--t-mega); font-weight: 900; line-height: 0.88; }
.hero .lede { font-size: var(--t-lg); max-width: 52ch; margin-top: var(--s-4); }
.wrapmax { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--s-6) var(--s-9); }
.screens { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-5); }
@media (max-width: 900px) { .screens { grid-template-columns: 1fr 1fr; } }
@media (max-width: 640px) { .screens { grid-template-columns: 1fr; } }
.screen-card { display: flex; flex-direction: column; gap: var(--s-3); text-decoration: none; }
.screen-card .thumb {
  height: 110px; border: var(--border-w) solid var(--border); border-radius: var(--radius);
  background: var(--surface-tint); display: grid; place-items: center;
  font-family: var(--font-display); font-weight: 800; font-size: var(--t-xl);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.screen-card:hover .thumb { transform: translate(-3px, -3px); box-shadow: var(--shadow); }
.swatch {
  height: 64px; border: var(--border-w) solid var(--border); border-radius: var(--radius);
  display: flex; align-items: flex-end; padding: 6px; font-family: var(--font-mono); font-size: var(--t-xs);
}
.typerow { display: flex; align-items: baseline; gap: var(--s-4); border-bottom: 1.5px solid var(--hairline); padding: var(--s-3) 0; }

/* Demo tooltip — an info marker that reveals supplementary help on hover or
   keyboard focus. Square, flat, monochrome (matches the design system). Used
   by the login screen's demo hint; gated behind the `demo` cargo feature. */
.tip { position: relative; display: inline-flex; vertical-align: middle; }
.tip-mark {
  display: inline-grid; place-items: center; width: 1.05rem; height: 1.05rem;
  border: var(--border-w) solid var(--border); border-radius: var(--radius);
  font-size: var(--t-xs); color: var(--text-soft); cursor: help; user-select: none;
}
.tip:hover .tip-mark, .tip:focus-within .tip-mark { color: var(--text); border-color: var(--text-soft); }
/* The tooltip lives inside a `.field`, and `.reveal` (animation-fill: forwards)
   makes that field a PERMANENT stacking context — so the popover's own z-index
   can't escape above a later sibling (e.g. the Continue button). Lift the whole
   field above its siblings while its tip is open so the popover wins. */
.field:has(.tip:hover), .field:has(.tip:focus-within) { position: relative; z-index: var(--z-popover); }
.tip-pop {
  position: absolute; left: 0; top: calc(100% + 6px); z-index: var(--z-popover);
}
/* transparent bridge over the 6px gap so moving from the mark down into the pop
   keeps `.tip:hover` continuous — otherwise the pop hides before a click lands
   on a copyable row inside it. */
.tip-pop::before { content: ""; position: absolute; left: 0; right: 0; top: -8px; height: 8px; }
.tip-pop {
  min-width: 252px; padding: var(--s-3);
  background: var(--surface-tint); border: var(--border-w) solid var(--border); border-radius: var(--radius);
  font-size: var(--t-xs); color: var(--text-soft); line-height: 1.55; text-align: left;
  opacity: 0; visibility: hidden; transform: translateY(-3px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease), visibility var(--dur);
}
.tip:hover .tip-pop, .tip:focus-within .tip-pop { opacity: 1; visibility: visible; transform: translateY(0); }
.tip-pop b { color: var(--text); font-weight: 700; }
.tip-pop code { font-family: var(--font-mono); color: var(--text); }
.tip-pop .tip-row { display: block; margin-top: var(--s-2); }

/* ===========================================================================
   STATUS BOARD — public status page (apps/status) + design-system showcase.
   Lives in the shared sheet (not app-local) so every app + the design system
   can reuse and document it. Consumes the same tokens as everything else.
   =========================================================================== */
.statuspage { max-width: 880px; margin: 0 auto; padding: var(--s-7) var(--s-5) var(--s-9); }
.status-head { display: flex; align-items: center; gap: var(--s-3); margin-bottom: var(--s-6); }
.status-head .brand { display: inline-flex; align-items: center; gap: var(--s-2); font-family: var(--font-display); font-weight: 800; letter-spacing: var(--track-wide); color: var(--text); text-decoration: none; }
.status-head .spacer { flex: 1; }

/* Overall banner — one-glance verdict, tinted by the worst component. */
.overall { display: flex; align-items: center; gap: var(--s-3); padding: var(--s-5); border: var(--border-w-thick) solid var(--border); background: var(--surface); }
.overall .pulse { width: 0.85rem; height: 0.85rem; border-radius: 50%; flex: none; color: var(--c-mint); background: currentColor; animation: status-pulse 2.4s var(--ease) infinite; }
.overall.is-degraded .pulse { color: var(--c-amber); }
.overall.is-down .pulse { color: var(--c-coral); }
@keyframes status-pulse { 0% { box-shadow: 0 0 0 0 currentColor; } 70% { box-shadow: 0 0 0 0.6rem transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }
.overall h1 { font-size: var(--t-xl); line-height: 1.1; }
.overall .since { color: var(--text-soft); font-size: var(--t-sm); margin-top: 0.15rem; }

/* Component row — name + description, a 90-day uptime strip, a status tag. */
.comp { padding: var(--s-4) 0; border-bottom: var(--border-w) solid var(--border); }
.comp:last-child { border-bottom: 0; }
.comp-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3); }
.comp-head .name { font-weight: 700; }
.comp-head .desc { color: var(--text-soft); font-size: var(--t-sm); }
.uptime { display: flex; gap: 2px; height: 30px; margin-top: var(--s-3); align-items: stretch; }
.uptime i { flex: 1 1 0; min-width: 0; background: var(--c-mint); border-radius: 1px; transition: opacity var(--dur-fast) var(--ease); }
.uptime i.deg { background: var(--c-amber); }
.uptime i.down { background: var(--c-coral); }
.uptime i:hover { opacity: 0.6; }
@media (max-width: 560px) { .uptime i:nth-child(-n+30) { display: none; } }
.uptime-foot { display: flex; justify-content: space-between; color: var(--text-soft); font-size: var(--t-xs); margin-top: var(--s-2); }

/* SLA / uptime summary tiles */
.sla { display: flex; flex-wrap: wrap; gap: var(--s-5); }
.sla .metric { flex: 1 1 7rem; }
.sla .metric .v { font-family: var(--font-mono); font-size: var(--t-lg); font-weight: 700; display: block; }
.sla .metric .k { color: var(--text-soft); font-size: var(--t-xs); }

/* Scheduled-maintenance + incident rows share the timeline treatment. */
.maint { padding: var(--s-4) 0; border-bottom: var(--border-w) solid var(--border); }
.maint:last-child { border-bottom: 0; }
.incident { padding: var(--s-4) 0; border-bottom: var(--border-w) solid var(--border); }
.incident:last-child { border-bottom: 0; }
.incident .title, .maint .title { font-weight: 700; }
.incident .when, .maint .when { color: var(--text-soft); font-size: var(--t-xs); font-family: var(--font-mono); }
.incident .note, .maint .note { color: var(--text-soft); font-size: var(--t-sm); margin-top: 0.15rem; }

/* Update timeline — a left rail with a node per timestamped update. */
.inc-timeline { list-style: none; margin: var(--s-3) 0 0; padding-left: var(--s-4); border-left: var(--border-w) solid var(--border); display: flex; flex-direction: column; gap: var(--s-4); }
.inc-update { position: relative; }
.inc-update::before { content: ""; position: absolute; left: calc(-1 * var(--s-4) - 5px); top: 0.4rem; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }
.inc-meta { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }

.status-foot { margin-top: var(--s-8); padding-top: var(--s-5); border-top: var(--border-w) solid var(--border); color: var(--text-soft); font-size: var(--t-sm); display: flex; justify-content: space-between; flex-wrap: wrap; gap: var(--s-3); }
.status-foot a { color: var(--text); }
