/* ============================================================================
   WelfareHub console -- "Campaign Operations" component sheet on the VANTAGE
   design language (PRD 14.1, docs/06, docs/ui-styleguide.md).

   What this file is
   - The component sheet for the CONSOLE (layouts/app.php and layouts/guest.php).
     The field PWA loads field.css and never this file.
   - Built ONLY on tokens.css: no colour literal appears below this header.
     If a colour is missing, it is added to tokens.css, not invented here.
   - Every class name here is load-bearing: 155 templates use them. Names are
     added, never renamed.

   What changed with the VANTAGE restyle
   - Type: the console opts IN to var(--font-ui) (self-hosted Inter, loaded by
     fonts.css). tokens.css keeps --font on the system stack so the field
     bundle can never pull the 352 KB face by accident; --font-ui is the
     console's deliberate opt-in and appears exactly once, on body.
   - Chrome: the sidebar and the record band carry the deep green identity
     (--chrome-bg), not a neutral. The approved mark still appears only
     through the mark slot (PRD 14.5).
   - Motion: interactive states now move. The old "nothing animates" rule is
     retired for hover/press/open transitions on CONTROLS only. Nothing that
     carries meaning animates: no pill, status, meter, alert, badge or
     environment banner has a transition, because a moving status is a status
     you can miss. prefers-reduced-motion stops every transition and every
     animation at the foot of this file.
   - Shape: --radius-sm (6px) for chips and inline marks, --radius (10px) for
     controls and menu rows, --radius-lg (16px) for cards, modals and sheets.

   Accessibility rules this file may not break
   - 48px touch floor (--touch) wherever a finger is expected: controls are
     --control-h (40px) on a fine pointer and grow to --touch on coarse
     pointers and at phone width.
   - Every text/background pair is at least 4.5:1; every non-text boundary or
     state indicator is at least 3:1. Where a solid status fill needed a
     different ink per theme, the ink is overridden per theme rather than
     shipped as a failing pair.
   - Status is colour AND text: .status always renders .status__text, and a
     .pill is a word. Nothing here paints a status without its label.
   - One focus ring, from the focus tokens, plus its halo. Nothing sets
     outline: none.
   - The environment banner (FR-ADM-007) is never hidden outside @media print.
   - ASCII only, LF endings (CLAUDE.md sec. 5).
   ============================================================================ */

/* ---- Reset and base ------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; height: 100%; }
body {
  margin: 0;
  min-height: 100%;
  /* The one console opt-in to the web font (see the header). */
  font-family: var(--font-ui);
  font-size: var(--fs-console);
  line-height: var(--lh);
  color: var(--text);
  background: var(--bg);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img, svg { vertical-align: middle; max-width: 100%; }
/* Links keep their underline: --link against --text is under 3:1, so colour
   alone would carry the link (WCAG 1.4.1). Component links (nav, buttons,
   tiles, menu rows) drop it explicitly because their shape carries them. */
a { color: var(--link); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--link-hover); }
h1, h2, h3, h4 { margin: 0 0 var(--sp-3); line-height: var(--lh-tight); font-weight: var(--fw-semibold); color: var(--text); }
h1 { font-size: var(--fs-xl); font-weight: var(--fw-bold); letter-spacing: -0.01em; }
h2 { font-size: var(--fs-lg); }
h3 { font-size: var(--fs-base); }
h4 { font-size: var(--fs-md); }
p { margin: 0 0 var(--sp-3); }
code, kbd, .mono { font-family: var(--font-mono); font-size: 0.93em; }
kbd, .kbd {
  display: inline-block; padding: 1px 6px; border: 1px solid var(--border-strong);
  border-bottom-width: 2px; border-radius: var(--radius-sm); background: var(--surface-2);
  font-family: inherit; font-size: var(--fs-xs); color: var(--text-muted); line-height: 1.5;
}
hr { border: 0; border-top: 1px solid var(--border); margin: var(--sp-4) 0; }
.num, .text-num { font-family: var(--font-num); font-variant-numeric: tabular-nums; font-feature-settings: "tnum"; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
[hidden] { display: none !important; }
::selection { background: var(--accent-soft); color: var(--accent-deep); }

/* Slim themed scrollbars (VANTAGE): Firefox via scrollbar-*, WebKit via the
   pseudo-elements. The thumb is --line-strong, a visible rule, not an input
   boundary, so --border-strong is reserved for controls. */
* { scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track, ::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--line-strong); border-radius: var(--radius-pill);
  border: 2px solid transparent; background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: var(--border-strong); background-clip: padding-box; }

/* The focus ring is painted at the FOOT of this file, not here: it is two
   rings (the outline plus the --focus-halo box-shadow) and a component that
   declares its own box-shadow at the same specificity would otherwise eat
   the halo simply by being further down the sheet. See "Focus ring" below
   the utilities. */

.skip-link {
  position: absolute; left: var(--sp-3); top: -100px; z-index: var(--z-toast);
  padding: var(--sp-2) var(--sp-4); border-radius: var(--radius);
  background: var(--accent); color: var(--on-accent); font-weight: var(--fw-semibold);
}
.skip-link:focus { top: var(--sp-3); }

.visually-hidden, .sr-only {
  position: absolute !important; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ---- Environment banner (FR-ADM-007) -------------------------------------
   Rendered on every non-production screen by partials/env-banner. It is
   text, not colour: the label names the environment. It never animates and
   is never hidden outside @media print. */
.env-banner {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: 28px; padding: var(--sp-1) var(--gutter);
  background: var(--status-warn-bg); color: var(--status-warn-text);
  border-bottom: 2px solid var(--status-warn);
  font-size: var(--fs-sm); font-weight: var(--fw-semibold); letter-spacing: 0.02em;
  text-align: center;
}
.env-banner strong { text-transform: uppercase; letter-spacing: var(--tracking-wide); }
.env-banner svg { flex: none; }

/* ---- Progress bar (one of the three things that animate) ------------------ */
#progress-bar {
  position: fixed; top: 0; left: 0; height: 3px; width: 0; z-index: var(--z-toast);
  background: var(--accent); opacity: 0;
}

/* ---- App shell ----------------------------------------------------------- */
.app { display: flex; min-height: 100vh; min-height: 100dvh; }
.app__main {
  flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column;
  margin-left: var(--sidebar-w);
  transition: margin-left var(--dur) var(--ease);
}
.app.is-collapsed .app__main { margin-left: var(--sidebar-w-collapsed); }
.app__content {
  flex: 1 0 auto; width: 100%; max-width: var(--content-max); margin: 0 auto;
  padding: var(--sp-5) var(--sp-5) var(--sp-7);
}
.app__scrim {
  position: fixed; inset: 0; z-index: var(--z-scrim); border: 0; padding: 0;
  background: var(--scrim); cursor: pointer;
}

/* ---- Sidebar -------------------------------------------------------------
   The deep green chrome. The identity lives here; the mark slot lives in the
   masthead at the top of it (PRD 14.5). */
.sidebar {
  position: fixed; top: 0; bottom: 0; left: 0; z-index: var(--z-sidebar);
  width: var(--sidebar-w); display: flex; flex-direction: column; overflow: hidden;
  background: var(--chrome-bg); color: var(--chrome-text);
  border-right: 1px solid var(--chrome-line);
  transition: width var(--dur) var(--ease);
}
.app.is-collapsed .sidebar { width: var(--sidebar-w-collapsed); }
.sidebar__brand {
  display: flex; align-items: center; gap: var(--sp-3); flex: none; min-height: var(--topbar-h);
  padding: 0 var(--sp-4); border-bottom: 1px solid var(--chrome-line);
  color: var(--chrome-text); text-decoration: none;
}
.sidebar__brand:hover { color: var(--white); }
.app.is-collapsed .sidebar__brand { padding: 0 var(--sp-2); justify-content: center; }
.mark { display: inline-flex; align-items: center; gap: var(--sp-3); min-width: 0; }
/* The approved mark is not square (the shield is wider than it is tall), so
   the height is fixed and the width follows. Forcing both squashed it. */
.mark__img { height: 34px; width: auto; flex: none; border-radius: var(--radius-sm); }
.mark__name { font-weight: var(--fw-bold); font-size: var(--fs-base); letter-spacing: 0.01em; line-height: 1.15; white-space: nowrap; }
.mark__sub {
  display: block; margin-top: 2px; font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--chrome-text-dim);
}
/* Collapsed rail: the wordmark is CLIPPED, not removed -- it is the masthead
   link's accessible name (WCAG 2.4.4 / 4.1.2). The sub-line is decorative
   and may go. */
.app.is-collapsed .mark__name {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.app.is-collapsed .mark__sub { display: none; }
/* The nav scrolls under the sticky foot, so it carries the same scroll
   affordance the table wrapper uses: two "cover" gradients in the panel
   colour that scroll away with the content (attachment: local) and two
   shadow gradients pinned to the box (attachment: scroll), which therefore
   show only at an edge that still has content behind it. */
.sidebar__nav {
  flex: 1 1 auto; overflow-y: auto; padding: var(--sp-3) var(--sp-2) var(--sp-5);
  background-image:
    linear-gradient(to bottom, var(--chrome-bg) 60%, transparent),
    linear-gradient(to top, var(--chrome-bg) 60%, transparent),
    linear-gradient(to bottom, var(--chrome-bg-2), transparent),
    linear-gradient(to top, var(--chrome-bg-2), transparent);
  background-position: top center, bottom center, top center, bottom center;
  background-repeat: no-repeat;
  background-size: 100% 26px, 100% 26px, 100% 14px, 100% 14px;
  background-attachment: local, local, scroll, scroll;
}
.sidebar__nav::-webkit-scrollbar { width: 6px; }
.sidebar__nav::-webkit-scrollbar-thumb { background: var(--chrome-line); border: 0; }
.sidebar__nav::-webkit-scrollbar-thumb:hover { background: var(--chrome-text-dim); }
.nav-section { margin-bottom: var(--sp-2); }
.nav-section__label {
  padding: var(--sp-3) var(--sp-3) var(--sp-1); font-size: var(--fs-xs); font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--chrome-text-dim);
}
/* clip-path keeps the group label in the accessibility tree while the rail
   is collapsed; the box stays as the section spacer. */
.app.is-collapsed .nav-section__label { padding: var(--sp-3) 0 var(--sp-1); text-align: center; clip-path: inset(50%); }
.nav-item {
  position: relative; display: flex; align-items: center; gap: var(--sp-3); min-height: 40px;
  margin: 1px 0; padding: var(--sp-2) var(--sp-3);
  border-left: 3px solid transparent; border-radius: var(--radius);
  color: var(--chrome-text); text-decoration: none; font-weight: var(--fw-medium);
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}
.nav-item:hover { background: var(--chrome-active); color: var(--white); }
/* Active is THREE signals: the left bar, the filled row and the weight --
   never colour alone. --brand-bright clears 3:1 on both the chrome and the
   active row; in high contrast the bar becomes the chrome text colour,
   because every green collapses to one dark ink there. */
.nav-item.is-active {
  background: var(--chrome-active); border-left-color: var(--brand-bright);
  color: var(--white); font-weight: var(--fw-semibold);
}
:root[data-theme="hc"] .nav-item.is-active { border-left-color: var(--chrome-text); }
@media (prefers-contrast: more) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) .nav-item.is-active { border-left-color: var(--chrome-text); }
}
.nav-item svg { flex: none; width: 20px; height: 20px; }
.nav-item__text { flex: 1 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The count is a pair (background + ink) in every theme: white on the dark
   theme's lighter red would have been 2.2:1. */
.nav-item__badge {
  display: inline-block; min-width: 20px; padding: 0 6px; border: 1px solid var(--status-crit); border-radius: var(--radius-pill);
  text-align: center; font-size: var(--fs-xs); font-weight: var(--fw-bold);
  background: var(--status-crit-bg); color: var(--status-crit-text);
}
.app.is-collapsed .nav-item { justify-content: center; padding: var(--sp-2); }
.app.is-collapsed .nav-item__text {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.app.is-collapsed .nav-item__badge { display: none; }
.sidebar__foot {
  flex: none; padding: var(--sp-3) var(--sp-4); border-top: 1px solid var(--chrome-line);
  background: var(--chrome-bg-2); font-size: var(--fs-xs); font-weight: var(--fw-medium);
  letter-spacing: 0.02em; color: var(--chrome-text-dim);
}
.app.is-collapsed .sidebar__foot { display: none; }

/* ---- Topbar -------------------------------------------------------------- */
.topbar {
  position: sticky; top: 0; z-index: var(--z-topbar);
  display: flex; align-items: center; gap: var(--sp-2);
  min-height: var(--topbar-h); padding: 0 var(--sp-4);
  background: var(--surface); border-bottom: 1px solid var(--border);
  box-shadow: var(--shadow-xs);
}
.topbar__toggle, .topbar__icon-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-width: var(--control-h); min-height: var(--control-h); padding: 0 var(--sp-2);
  border: 1px solid transparent; border-radius: var(--radius); background: transparent; color: var(--text-muted);
  text-decoration: none; position: relative;
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}
.topbar__toggle:hover, .topbar__icon-btn:hover { background: var(--surface-2); border-color: var(--border); color: var(--text); }
.topbar__toggle { display: none; }
.topbar__icon-btn .topbar__lbl { font-size: var(--fs-sm); font-weight: var(--fw-medium); }
.topbar__search { flex: 1 1 320px; max-width: 520px; position: relative; margin: 0; }
.topbar__search input {
  width: 100%; height: var(--control-h); padding: 0 var(--sp-3) 0 38px;
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--surface-2); color: var(--text); font-size: var(--fs-sm);
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.topbar__search input:hover { border-color: var(--accent); }
.topbar__search input:focus { background: var(--surface); border-color: var(--accent); }
.topbar__search svg { position: absolute; left: 12px; top: 50%; margin-top: -9px; color: var(--text-faint); pointer-events: none; }
.topbar__search-btn {
  display: inline-flex; align-items: center; gap: var(--sp-2); width: 100%; height: var(--control-h); padding: 0 var(--sp-3);
  border: 1px solid var(--border-strong); border-radius: var(--radius); background: var(--surface-2); color: var(--text-muted);
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.topbar__search-btn:hover { background: var(--surface); border-color: var(--accent); color: var(--text); }
.topbar__search-btn kbd { margin-left: auto; }
.topbar__spacer { flex: 1 1 auto; }
.topbar__right { display: flex; align-items: center; gap: var(--sp-1); }
.topbar__user {
  display: flex; align-items: center; gap: var(--sp-2); min-height: var(--control-h); padding: 0 var(--sp-2);
  border: 1px solid transparent; border-radius: var(--radius); background: transparent; color: var(--text); cursor: pointer;
  list-style: none;
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.topbar__user::-webkit-details-marker { display: none; }
.topbar__user:hover { background: var(--surface-2); border-color: var(--border); }
.topbar__user > svg { flex: none; color: var(--text-muted); transition: transform var(--dur-fast) var(--ease); }
.dropdown[open] > .topbar__user > svg { transform: rotate(180deg); }
.avatar {
  display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; flex: none;
  border-radius: 50%; background: var(--accent-soft); color: var(--accent-deep);
  font-weight: var(--fw-bold); font-size: var(--fs-sm);
}
.topbar__user-meta { display: flex; flex-direction: column; line-height: 1.2; text-align: left; min-width: 0; }
.topbar__user-name { font-weight: var(--fw-semibold); font-size: var(--fs-sm); max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.topbar__user-role { font-size: var(--fs-xs); color: var(--text-muted); }
.notif__bell { position: relative; }
.notif__badge {
  position: absolute; top: 2px; right: 2px; min-width: 18px; height: 18px; padding: 0 4px;
  border: 1px solid var(--status-crit); border-radius: var(--radius-pill);
  background: var(--status-crit-bg); color: var(--status-crit-text);
  font-size: var(--fs-xs); font-weight: var(--fw-bold); line-height: 16px; text-align: center;
}
[data-theme-icon] .theme-ic { display: none; }
[data-theme-icon][data-current="light"] .theme-ic--light,
[data-theme-icon][data-current="dark"] .theme-ic--dark,
[data-theme-icon][data-current="hc"] .theme-ic--hc,
[data-theme-icon][data-current="auto"] .theme-ic--auto { display: inline-flex; }

/* ---- Dropdown menus ------------------------------------------------------ */
.dropdown { position: relative; }
.dropdown__menu {
  display: none; position: absolute; right: 0; top: calc(100% + 6px); z-index: var(--z-menu);
  min-width: 240px; padding: var(--sp-2); margin: 0;
  background: var(--surface-float); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.dropdown__menu.is-open, .dropdown[open] > .dropdown__menu { display: block; }
.dropdown--left .dropdown__menu { right: auto; left: 0; }
.dropdown__item {
  display: flex; align-items: center; gap: var(--sp-3); width: 100%; min-height: 40px; padding: var(--sp-2) var(--sp-3);
  border: 0; border-radius: var(--radius); background: transparent; color: var(--text); text-decoration: none; text-align: left;
  font-weight: var(--fw-medium);
  transition: background-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.dropdown__item:hover, .dropdown__item:focus-visible { background: var(--accent-soft); color: var(--accent-deep); }
.dropdown__item[aria-checked="true"] { font-weight: var(--fw-semibold); box-shadow: inset 3px 0 0 var(--accent); }
.dropdown__item svg { flex: none; color: var(--text-muted); }
.dropdown__item:hover svg, .dropdown__item:focus-visible svg { color: inherit; }
.dropdown__divider { height: 1px; margin: var(--sp-2) 0; background: var(--border); }
.dropdown__header { padding: var(--sp-2) var(--sp-3); font-size: var(--fs-xs); color: var(--text-muted); }
.dropdown__header b { display: block; font-size: var(--fs-sm); color: var(--text); }
.dropdown__form { margin: 0; }

/* ---- Page header / breadcrumb -------------------------------------------- */
.page-header {
  display: flex; align-items: flex-end; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap;
  margin-bottom: var(--sp-5);
}
.page-header--compact { margin-bottom: var(--sp-3); }
.page-title { margin: 0; font-size: var(--fs-xl); font-weight: var(--fw-bold); letter-spacing: -0.01em; display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap; }
.page-header__eyebrow { margin: 0 0 var(--sp-1); font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--text-muted); }
.page-header__sub { margin: var(--sp-1) 0 0; max-width: 78ch; color: var(--text-muted); }
.page-header__actions { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.page-header__back { display: inline-flex; align-items: center; gap: var(--sp-1); margin-bottom: var(--sp-2); font-size: var(--fs-sm); text-decoration: none; font-weight: var(--fw-medium); }
.page-header__back:hover { text-decoration: underline; }
.breadcrumb { display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-1); margin-bottom: var(--sp-1); font-size: var(--fs-sm); color: var(--text-muted); }
.breadcrumb a { color: var(--text-muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--link); text-decoration: underline; }
.breadcrumb span[aria-current] { color: var(--text); font-weight: var(--fw-medium); }
.crumb-sep { display: inline-flex; color: var(--line-strong); }

/* ---- Cards ---------------------------------------------------------------
   No overflow clipping on the base card: a dropdown or a tip inside a card
   must not be cut off. */
.card {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm); margin-bottom: var(--sp-4);
}
.card__header {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); flex-wrap: wrap;
  padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border);
}
.card__title { margin: 0; font-size: var(--fs-base); font-weight: var(--fw-semibold); }
.card__body { padding: var(--sp-4); }
.card__footer {
  display: flex; gap: var(--sp-2); flex-wrap: wrap; align-items: center;
  padding: var(--sp-3) var(--sp-4); border-top: 1px solid var(--border);
  background: var(--surface-2); border-radius: 0 0 var(--radius-lg) var(--radius-lg);
}
.card--flush .card__body { padding: 0; }
.card--plain { box-shadow: none; }

/* ---- Stat tiles (KPIs) ---------------------------------------------------
   The tone bar is a ::before rail so the tile keeps its full radius; the
   icon chip carries the same tone as an AA text/background pair. A tone is
   never the only signal: the label and the figure say what it is. */
.stats-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-3); margin-bottom: var(--sp-4); }
.stats-grid--6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.stats-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.stats-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.stats-grid > * { min-width: 0; }
.stat-tile {
  position: relative; display: flex; gap: var(--sp-3); align-items: flex-start; padding: var(--sp-4) var(--sp-4) var(--sp-4) var(--sp-5);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm); color: var(--text); text-decoration: none; min-height: 92px;
}
/* The tone rail is inset from the corners on purpose: a full-height bar at
   left:0 pokes out of a 16px corner curve, and the tile cannot clip it --
   .stat-tile__label may host a [data-tip] whose bubble has to escape. */
.stat-tile::before {
  content: ""; position: absolute; left: 0; top: var(--sp-2); bottom: var(--sp-2); width: 4px;
  background: var(--border-strong); border-radius: 0 var(--radius-pill) var(--radius-pill) 0;
}
.stat-tile--primary::before, .stat-tile--info::before { background: var(--accent); }
.stat-tile--success::before, .stat-tile--ok::before { background: var(--status-ok); }
.stat-tile--warning::before, .stat-tile--warn::before { background: var(--status-warn); }
.stat-tile--danger::before, .stat-tile--crit::before { background: var(--status-crit); }
.stat-tile--neutral::before, .stat-tile--closed::before { background: var(--status-closed); }
.stat-tile--link {
  transition: transform var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease);
}
.stat-tile--link:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: var(--accent); color: var(--text); }
.stat-tile__icon {
  display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; flex: none;
  border-radius: var(--radius); background: var(--surface-2); color: var(--text-muted);
}
.stat-tile--primary .stat-tile__icon, .stat-tile--info .stat-tile__icon { background: var(--accent-soft); color: var(--accent-deep); }
.stat-tile--success .stat-tile__icon, .stat-tile--ok .stat-tile__icon { background: var(--status-ok-bg); color: var(--status-ok-text); }
.stat-tile--warning .stat-tile__icon, .stat-tile--warn .stat-tile__icon { background: var(--status-warn-bg); color: var(--status-warn-text); }
.stat-tile--danger .stat-tile__icon, .stat-tile--crit .stat-tile__icon { background: var(--status-crit-bg); color: var(--status-crit-text); }
.stat-tile--neutral .stat-tile__icon, .stat-tile--closed .stat-tile__icon { background: var(--status-closed-bg); color: var(--status-closed-text); }
.stat-tile__visual { flex: none; }
.stat-tile__body { min-width: 0; flex: 1 1 auto; }
.stat-tile__label { font-size: var(--fs-sm); color: var(--text-muted); font-weight: var(--fw-medium); }
.stat-tile__value {
  margin-top: 2px; font-size: var(--fs-2xl); font-weight: var(--fw-bold); line-height: 1.05; letter-spacing: -0.02em;
  display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap;
}
.stat-tile__sub { font-size: var(--fs-xs); color: var(--text-muted); margin-top: 2px; }
.stat-tile__foot { margin-top: var(--sp-2); font-size: var(--fs-xs); color: var(--text-muted); }
.stat-tile__trend { display: inline-flex; align-items: center; gap: 2px; font-size: var(--fs-sm); font-weight: var(--fw-semibold); }
.stat-tile__trend--up { color: var(--status-ok-text); }
.stat-tile__trend--down { color: var(--status-crit-text); }

/* ---- Buttons -------------------------------------------------------------
   One primary action per screen. The press is a 1px drop, the hover a tone
   step; both are transitions on a control, not on a status. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: var(--control-h); padding: 0 var(--sp-4);
  border: 1px solid var(--border-strong); border-radius: var(--radius);
  background: var(--surface); color: var(--text); font-family: inherit; font-weight: var(--fw-semibold);
  text-decoration: none; white-space: nowrap; cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease), transform var(--dur-fast) var(--ease);
}
.btn:hover { background: var(--surface-2); border-color: var(--accent); color: var(--text); }
.btn:active { transform: translateY(1px); }
.btn:disabled, .btn.is-disabled, .btn[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; transform: none; }
.btn svg { flex: none; }
.btn--primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); box-shadow: var(--shadow-xs); }
.btn--primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--on-accent); box-shadow: var(--shadow-sm); }
.btn--danger { background: var(--surface); border-color: var(--status-crit); color: var(--status-crit-text); }
.btn--danger:hover { background: var(--status-crit-bg); border-color: var(--status-crit); color: var(--status-crit-text); }
.btn--danger-solid { background: var(--status-crit); border-color: var(--status-crit); color: var(--white); box-shadow: var(--shadow-xs); }
.btn--danger-solid:hover { background: var(--status-crit-text); border-color: var(--status-crit-text); color: var(--white); }
/* The dark theme's crit is a LIGHT red: white on it is 2.2:1, so the solid
   danger button takes the page ink instead -- 7.15:1 at rest and 16.61:1 on
   the paler hover fill. These selectors outrank the :hover rule above, so
   the ink stays dark through the hover; the hc theme keeps white on its deep
   red (9.05:1) and needs no override. */
:root[data-theme="dark"] .btn--danger-solid { color: var(--bg); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="hc"]) .btn--danger-solid { color: var(--bg); }
}
.btn--ghost { background: transparent; border-color: transparent; color: var(--text-muted); }
.btn--ghost:hover { background: var(--surface-2); border-color: var(--border); color: var(--text); }
.btn--link { background: transparent; border-color: transparent; color: var(--link); text-decoration: underline; }
.btn--link:hover { background: transparent; color: var(--link-hover); }
.btn--sm { min-height: 32px; padding: 0 var(--sp-3); font-size: var(--fs-sm); }
.btn--lg { min-height: var(--touch); padding: 0 var(--sp-5); font-size: var(--fs-base); }
.btn--block { display: flex; width: 100%; }
.btn--icon { padding: 0; min-width: var(--control-h); }
.btn-group { display: inline-flex; gap: var(--sp-2); flex-wrap: wrap; }

/* ---- Pills and status labels --------------------------------------------
   A pill is a WORD with a tone behind it. The border keeps the chip visible
   at 3:1 in the high-contrast theme, where every status background is white
   and the border plus the ink carry the meaning. */
.pill {
  display: inline-flex; align-items: center; gap: 6px; min-height: 22px; padding: 1px 10px;
  border: 1px solid transparent; border-radius: var(--radius-pill);
  font-size: var(--fs-xs); font-weight: var(--fw-semibold); letter-spacing: 0.01em; line-height: 1.5; white-space: nowrap;
  background: var(--status-closed-bg); color: var(--status-closed-text); border-color: var(--status-closed);
}
.pill--success, .pill--ok, .pill--active, .pill--verified, .pill--resolved, .pill--paid, .pill--approved, .pill--fulfilled { background: var(--status-ok-bg); color: var(--status-ok-text); border-color: var(--status-ok); }
.pill--warning, .pill--warn, .pill--pending, .pill--processing, .pill--awaiting, .pill--escalated { background: var(--status-warn-bg); color: var(--status-warn-text); border-color: var(--status-warn); }
.pill--danger, .pill--crit, .pill--failed, .pill--overdue, .pill--breached, .pill--emergency, .pill--rejected { background: var(--status-crit-bg); color: var(--status-crit-text); border-color: var(--status-crit); }
.pill--info, .pill--new, .pill--draft { background: var(--info-bg); color: var(--info-text); border-color: var(--info); }
.pill--neutral, .pill--closed, .pill--cancelled, .pill--inactive, .pill--archived { background: var(--status-closed-bg); color: var(--status-closed-text); border-color: var(--status-closed); }

/* status_label(): colour AND text, always together (PRD 14.1). */
.status { display: inline-flex; align-items: center; gap: 6px; font-weight: var(--fw-semibold); font-size: var(--fs-sm); white-space: nowrap; color: var(--status-closed-text); }
.status__dot { width: 10px; height: 10px; flex: none; border-radius: 50%; background: var(--status-closed); border: 1px solid var(--status-closed); }
.status__text { white-space: nowrap; }
.status--ok { color: var(--status-ok-text); }
.status--ok .status__dot { background: var(--status-ok); border-color: var(--status-ok); }
.status--warn { color: var(--status-warn-text); }
.status--warn .status__dot { background: var(--status-warn); border-color: var(--status-warn); }
.status--crit { color: var(--status-crit-text); }
.status--crit .status__dot { background: var(--status-crit); border-color: var(--status-crit); }
.status--closed { color: var(--status-closed-text); }
.status--pill { padding: 1px 10px 1px 8px; border-radius: var(--radius-pill); border: 1px solid; }
.status--pill.status--ok { background: var(--status-ok-bg); border-color: var(--status-ok); }
.status--pill.status--warn { background: var(--status-warn-bg); border-color: var(--status-warn); }
.status--pill.status--crit { background: var(--status-crit-bg); border-color: var(--status-crit); }
.status--pill.status--closed { background: var(--status-closed-bg); border-color: var(--status-closed); }

/* ---- Tables toolkit ------------------------------------------------------ */
.grid-2, .grid-3 { display: grid; gap: var(--sp-4); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* A grid child defaults to min-width:auto, so a wide table would push its
   card past the column instead of scrolling inside it. */
.grid-2 > *, .grid-3 > * { min-width: 0; }
/* The layered gradients are the scroll affordance: the "cover" pair is
   painted in the surface colour and scrolls away with the content, so the
   edge shadows (pinned to the box) show only where there is more to see. */
.table-wrap, .table-scroll {
  position: relative; overflow-x: auto; max-width: 100%; min-width: 0; -webkit-overflow-scrolling: touch;
  background-image:
    linear-gradient(to right, var(--surface) 40%, transparent),
    linear-gradient(to left, var(--surface) 40%, transparent),
    linear-gradient(to right, var(--edge-shadow), transparent),
    linear-gradient(to left, var(--edge-shadow), transparent);
  background-position: left center, right center, left center, right center;
  background-repeat: no-repeat;
  background-size: 40px 100%, 40px 100%, 14px 100%, 14px 100%;
  background-attachment: local, local, scroll, scroll;
}
.table-wrap--tall { max-height: min(70vh, 720px); overflow-y: auto; }
.card__body > .table-wrap:only-child { margin: calc(var(--sp-4) * -1); width: calc(100% + var(--sp-4) * 2); max-width: none; }
.data-table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); background: transparent; }
.data-table--fixed { table-layout: fixed; }
.data-table caption { caption-side: top; text-align: left; padding: var(--sp-3) var(--sp-4); font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--text-muted); }
.data-table thead th {
  position: sticky; top: 0; z-index: 1; padding: var(--sp-3) var(--sp-4); text-align: left;
  font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: var(--tracking-wide); text-transform: uppercase;
  color: var(--text-muted); background: var(--surface-2); border-bottom: 1px solid var(--border); white-space: nowrap; vertical-align: middle;
}
.data-table thead th a { color: inherit; text-decoration: none; display: inline-flex; align-items: center; gap: 4px; }
/* The whole head cell is the sort target (WCAG 2.5.8): the link fills it,
   cancelling the cell padding and re-applying it, so the focus ring outlines
   what the pointer can hit rather than a 12px run of text. */
.data-table thead th.is-sortable { cursor: pointer; user-select: none; }
.data-table thead th.is-sortable > a { display: flex; margin: calc(var(--sp-3) * -1) calc(var(--sp-4) * -1); padding: var(--sp-3) var(--sp-4); }
.data-table thead th.is-sortable.col-num > a { justify-content: flex-end; }
.data-table thead th.is-sortable:hover, .data-table thead th a:hover { color: var(--link); }
.data-table thead th[aria-sort="ascending"], .data-table thead th[aria-sort="descending"] { color: var(--text); }
.data-table tbody td { padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--line-2); vertical-align: middle; }
.data-table tbody tr:last-child td { border-bottom: 0; }
.data-table tbody tr:hover td { background: var(--surface-2); }
.data-table tfoot td { padding: var(--sp-3) var(--sp-4); font-weight: var(--fw-semibold); background: var(--surface-2); }
.data-table .col-num, .data-table td.num, .data-table th.col-num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table .col-trunc { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.data-table .col-wrap { white-space: normal; }
.data-table .col-status { white-space: nowrap; }
.data-table .col-actions { text-align: right; white-space: nowrap; width: 1%; }
.data-table .col-check { width: 1%; }
.data-table .cell-actions { display: inline-flex; gap: var(--sp-1); justify-content: flex-end; }
.data-table tr.is-selected td { background: var(--accent-soft); }
.data-table tr.is-breached td:first-child { box-shadow: inset 4px 0 0 var(--status-crit); }
.data-table tr.is-at-risk td:first-child { box-shadow: inset 4px 0 0 var(--status-warn); }
.sort-ico { flex: none; opacity: 0.75; }
.idchip { display: inline-flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.idchip__name { font-weight: var(--fw-semibold); }
.idchip__sub { display: block; font-size: var(--fs-xs); color: var(--text-muted); }

.grid-toolbar { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border); }
.grid-toolbar__filters { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; }
.grid-toolbar__spacer { flex: 1 1 auto; }
.grid-search { position: relative; }
.grid-search input {
  height: var(--control-h); min-width: 220px; padding: 0 var(--sp-3) 0 34px;
  border: 1px solid var(--border-strong); border-radius: var(--radius); background: var(--surface-2); color: var(--text);
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
.grid-search input:hover { border-color: var(--accent); }
.grid-search input:focus { background: var(--surface); border-color: var(--accent); }
.grid-search svg { position: absolute; left: 10px; top: 50%; margin-top: -8px; color: var(--text-faint); pointer-events: none; }
.pagination { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); flex-wrap: wrap; padding: var(--sp-3) var(--sp-4); border-top: 1px solid var(--border); }
.pagination__info { font-size: var(--fs-sm); color: var(--text-muted); }
.pagination__pages { display: flex; gap: var(--sp-1); flex-wrap: wrap; }
.page-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-1);
  min-width: 36px; min-height: 36px; padding: 0 var(--sp-2);
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); color: var(--text);
  text-decoration: none; font-size: var(--fs-sm); font-weight: var(--fw-medium);
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.page-btn:hover { background: var(--surface-2); border-color: var(--accent); color: var(--text); }
.page-btn.is-active { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.page-btn:disabled, .page-btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }
.table-more { padding: var(--sp-3) var(--sp-4); text-align: center; }
.table-more__note { display: block; margin-top: var(--sp-1); font-size: var(--fs-xs); color: var(--text-muted); }

/* ---- Tab strips ---------------------------------------------------------- */
.tab-strip { display: flex; gap: var(--sp-1); border-bottom: 1px solid var(--border); margin-bottom: var(--sp-4); overflow-x: auto; }
.tab-strip [role="tab"], .tab-strip .tab {
  display: inline-flex; align-items: center; gap: var(--sp-2); min-height: var(--control-h); padding: 0 var(--sp-3);
  border: 0; border-bottom: 3px solid transparent; background: transparent; color: var(--text-muted); font-weight: var(--fw-medium);
  text-decoration: none; white-space: nowrap; margin-bottom: -1px;
  transition: color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease);
}
/* The selected tab is the weight AND the rule, not the rule alone. */
.tab-strip [role="tab"][aria-selected="true"], .tab-strip .tab.is-active { color: var(--text); font-weight: var(--fw-semibold); border-bottom-color: var(--sky-deep); }
/* Hover is excluded on the selected tab, or it would repaint the gold rule
   that says which tab you are on. */
.tab-strip [role="tab"]:not([aria-selected="true"]):hover,
.tab-strip .tab:not(.is-active):hover { color: var(--text); border-bottom-color: var(--line-strong); }
[data-tab-panel][hidden] { display: none; }

/* ---- Forms --------------------------------------------------------------- */
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-3) var(--sp-4); }
.form-grid > .field--wide { grid-column: 1 / -1; }
.field { margin-bottom: var(--sp-4); }
.field-label, .field > label { display: block; margin-bottom: var(--sp-1); font-weight: var(--fw-semibold); font-size: var(--fs-sm); color: var(--text); }
.field-label .req { color: var(--status-crit-text); font-weight: var(--fw-bold); }
.field-input { position: relative; }
.field-icon { position: absolute; left: 12px; top: 50%; margin-top: -8px; color: var(--text-faint); pointer-events: none; display: inline-flex; }
.field-control,
.field > :where(input:not([type="checkbox"]):not([type="radio"]):not([type="file"]):not([type="range"])),
.field > :where(select, textarea),
.input {
  display: block; width: 100%; min-height: var(--control-h); padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--border-strong); border-radius: var(--radius); background: var(--surface); color: var(--text);
  font-family: inherit; font-size: var(--fs-md); line-height: 1.4;
  transition: border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.field-control:hover, .field > :where(input, select, textarea):hover, .input:hover { border-color: var(--accent); }
.field-control:focus, .field > :where(input, select, textarea):focus, .input:focus { border-color: var(--accent); }
.field-control--with-icon .field-control { padding-left: 38px; }
textarea.field-control, .field > textarea { min-height: 96px; resize: vertical; }
select.field-control, .field > select { padding-right: var(--sp-6); }
.field-control::placeholder, .input::placeholder { color: var(--text-faint); }
.field.has-error .field-control, .field.has-error > :where(input, select, textarea) { border-color: var(--status-crit); border-width: 2px; }
.field-error { display: flex; align-items: center; gap: var(--sp-1); margin-top: var(--sp-1); font-size: var(--fs-sm); font-weight: var(--fw-semibold); color: var(--status-crit-text); }
.field-error::before {
  content: "!"; display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px; flex: none;
  border: 1px solid var(--status-crit); border-radius: 50%;
  background: var(--status-crit-bg); color: var(--status-crit-text); font-size: var(--fs-xs); font-weight: var(--fw-bold);
}
.field-hint, .hint { margin-top: var(--sp-1); font-size: var(--fs-sm); color: var(--text-muted); }
.field-row { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.field-row .field { flex: 1 1 200px; min-width: 0; }
.fieldset { border: 1px solid var(--border); border-radius: var(--radius-lg); padding: var(--sp-4); margin: 0 0 var(--sp-4); }
.fieldset > legend { padding: 0 var(--sp-2); font-weight: var(--fw-semibold); }
.fieldset-title {
  margin: var(--sp-5) 0 var(--sp-3); padding-bottom: var(--sp-2); border-bottom: 1px solid var(--border);
  font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--text-muted);
}
.fieldset-title:first-child { margin-top: 0; }
.check { display: flex; align-items: flex-start; gap: var(--sp-2); min-height: var(--control-h); padding: var(--sp-1) 0; cursor: pointer; }
.check input[type="checkbox"], .check input[type="radio"], .field input[type="checkbox"], .field input[type="radio"] { width: 20px; height: 20px; margin: 2px 0 0; accent-color: var(--accent); flex: none; }
.form-actions { display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap; margin-top: var(--sp-4); }
.form-actions--end { justify-content: flex-end; }

/* ---- Alerts, flash and toasts -------------------------------------------
   An alert carries meaning, so it does not move and does not fade. */
.flash-stack { position: relative; z-index: 1; margin-bottom: var(--sp-4); }
.flash-stack:empty { margin: 0; }
body > .flash-stack { position: fixed; right: var(--sp-4); bottom: var(--sp-4); z-index: var(--z-toast); width: min(420px, calc(100vw - var(--sp-6))); margin: 0; }
body > .flash-stack .alert { box-shadow: var(--shadow-lg); }
.alert {
  display: flex; align-items: flex-start; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); margin-bottom: var(--sp-2);
  border: 1px solid var(--border); border-left-width: 4px; border-radius: var(--radius); background: var(--surface); color: var(--text);
}
.alert__icon { flex: none; display: inline-flex; margin-top: 1px; }
.alert__msg { flex: 1 1 auto; min-width: 0; }
.alert__close { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; margin: -6px -8px -6px 0; border: 0; border-radius: var(--radius); background: transparent; color: inherit; }
.alert__close:hover { background: var(--surface-3); }
.alert--success, .alert--ok { background: var(--status-ok-bg); color: var(--status-ok-text); border-color: var(--status-ok); }
.alert--danger, .alert--error, .alert--crit { background: var(--status-crit-bg); color: var(--status-crit-text); border-color: var(--status-crit); }
.alert--warning, .alert--warn { background: var(--status-warn-bg); color: var(--status-warn-text); border-color: var(--status-warn); }
.alert--info { background: var(--info-bg); color: var(--info-text); border-color: var(--info); }
.alert a { color: inherit; font-weight: var(--fw-semibold); }

/* ---- Modals and confirm dialogs -----------------------------------------
   The header band is the chrome green, so a dialog reads as part of the
   console and not as a floating web page. */
.modal-overlay { position: fixed; inset: 0; z-index: var(--z-modal); display: flex; align-items: center; justify-content: center; padding: var(--sp-4); background: var(--scrim); }
.modal { width: 100%; max-width: 520px; max-height: calc(100vh - var(--sp-6)); overflow: auto; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); }
.modal--danger { border-top: 4px solid var(--status-crit); }
.modal__header {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4); background: var(--chrome-bg); color: var(--chrome-text);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.modal--danger .modal__header { border-radius: 0; }
.modal__title { margin: 0; font-size: var(--fs-lg); color: var(--chrome-text); }
.modal__close { display: inline-flex; align-items: center; justify-content: center; width: var(--control-h); height: var(--control-h); border: 0; border-radius: var(--radius); background: transparent; color: var(--chrome-text-dim); }
.modal__close:hover { background: var(--chrome-active); color: var(--chrome-text); }
.modal__body { padding: var(--sp-4); }
.modal__footer { display: flex; justify-content: flex-end; gap: var(--sp-2); padding: var(--sp-3) var(--sp-4); border-top: 1px solid var(--border); background: var(--surface-2); border-radius: 0 0 var(--radius-lg) var(--radius-lg); }
.confirm { display: inline; }

/* ---- Empty, loading and error states (PRD 14.3) ------------------------- */
.empty-state { display: flex; flex-direction: column; align-items: center; gap: var(--sp-2); padding: var(--sp-7) var(--sp-4); text-align: center; color: var(--text-muted); }
.empty-state__icon { display: inline-flex; align-items: center; justify-content: center; width: 56px; height: 56px; border-radius: 50%; background: var(--tint); color: var(--text-muted); border: 1px solid var(--border); }
.empty-state__title { margin: var(--sp-2) 0 0; font-size: var(--fs-base); color: var(--text); }
.empty-state__body { margin: 0; max-width: 46ch; }
.empty-state__action { margin-top: var(--sp-3); }
.empty-state--tight { padding: var(--sp-4); }

.skeleton { position: relative; overflow: hidden; border-radius: var(--radius); background: var(--surface-3); pointer-events: none; }
.skeleton::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, transparent, var(--surface), transparent); animation: skeleton-shimmer 1.4s linear infinite; }
.skeleton--text { height: 14px; margin: 8px 0; }
.skeleton--title { height: 22px; width: 40%; margin: 8px 0 12px; }
.skeleton--row { height: 44px; margin-bottom: 6px; }
.skeleton--tile { height: 92px; margin-bottom: var(--sp-3); border-radius: var(--radius-lg); }
.skeleton-set { display: block; }
.skeleton-set--tiles { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--sp-3); }
@keyframes skeleton-shimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

.spinner { display: inline-block; width: 18px; height: 18px; border: 2px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; vertical-align: -4px; }
@keyframes spin { to { transform: rotate(360deg); } }
.htmx-indicator { display: none; }
.htmx-request .htmx-indicator, .htmx-request.htmx-indicator { display: inline-block; }
.meter { height: 8px; border-radius: var(--radius-pill); background: var(--surface-3); overflow: hidden; }
.meter > span { display: block; height: 100%; background: var(--status-ok); }
.meter--warn > span { background: var(--status-warn); }
.meter--crit > span { background: var(--status-crit); }
.progress-inline { display: inline-flex; align-items: center; gap: var(--sp-2); color: var(--text-muted); font-size: var(--fs-sm); }

/* ---- Error pages (401/403/404/422/429/500/503) --------------------------- */
.error-page { text-align: center; }
.error-page__icon { display: inline-flex; align-items: center; justify-content: center; width: 64px; height: 64px; margin-bottom: var(--sp-2); border-radius: 50%; background: var(--tint); color: var(--text-muted); border: 1px solid var(--border); }
.error-page__icon--warn { background: var(--status-warn-bg); color: var(--status-warn-text); border-color: var(--status-warn); }
.error-page__icon--crit { background: var(--status-crit-bg); color: var(--status-crit-text); border-color: var(--status-crit); }
.error-page__eyebrow { margin: 0; font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--text-muted); }
.error-page__code { margin: var(--sp-1) 0; font-size: var(--fs-3xl); font-weight: var(--fw-bold); letter-spacing: -0.02em; }
.error-page__msg { font-size: var(--fs-base); }
.error-page__next { text-align: left; display: inline-block; margin: var(--sp-2) 0 var(--sp-3); padding-left: var(--sp-5); color: var(--text-muted); }
.error-page__next li { margin-bottom: var(--sp-1); }
.error-page__ref { margin: var(--sp-3) 0; font-size: var(--fs-sm); color: var(--text-muted); }
.error-page__ref code { padding: 2px 6px; border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--surface-2); color: var(--text); user-select: all; }
.error-page__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--sp-3); margin-top: var(--sp-3); }

/* ---- Record detail pages -------------------------------------------------
   The identity band is the chrome green with the record's reference in it;
   status pills inside keep their OWN tone, because a status may not be
   repainted to match a band. */
.record-band {
  position: relative; display: flex; align-items: center; gap: var(--sp-4); flex-wrap: wrap;
  padding: var(--sp-4) var(--sp-5); margin-bottom: var(--sp-4);
  background: linear-gradient(120deg, var(--chrome-bg) 0%, var(--chrome-bg-2) 100%);
  color: var(--chrome-text); border: 1px solid var(--chrome-line); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.record-band__main { flex: 1 1 260px; min-width: 0; }
.record-band__title { margin: 0; font-size: var(--fs-xl); font-weight: var(--fw-bold); line-height: var(--lh-tight); color: var(--white); }
.record-band__title code { font-size: 0.85em; }
.record-band__meta { display: flex; gap: var(--sp-3); flex-wrap: wrap; align-items: center; margin-top: var(--sp-1); font-size: var(--fs-sm); color: var(--chrome-text); }
.record-band__meta svg { opacity: 0.8; }
.record-band__id { font-family: var(--font-num); font-variant-numeric: tabular-nums; font-weight: var(--fw-semibold); color: var(--white); }
.record-band__badges { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.def-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--sp-3) var(--sp-4); }
.def-grid__label { font-size: var(--fs-xs); font-weight: var(--fw-semibold); letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted); }
.def-grid__value { font-weight: var(--fw-semibold); color: var(--text); word-break: break-word; }
.def-grid__item--wide { grid-column: 1 / -1; }
.timeline { list-style: none; margin: 0; padding: 0; border-left: 2px solid var(--border); }
.timeline__item { position: relative; padding: 0 0 var(--sp-4) var(--sp-4); }
.timeline__item::before { content: ""; position: absolute; left: -7px; top: 5px; width: 12px; height: 12px; border-radius: 50%; background: var(--surface); border: 2px solid var(--border-strong); }
.timeline__item--ok::before { border-color: var(--status-ok); background: var(--status-ok); }
.timeline__item--warn::before { border-color: var(--status-warn); background: var(--status-warn); }
.timeline__item--crit::before { border-color: var(--status-crit); background: var(--status-crit); }
.timeline__time { font-size: var(--fs-xs); color: var(--text-muted); }

/* ---- Inline tips ([data-tip]) -------------------------------------------- */
[data-tip] { position: relative; text-decoration: underline dotted; text-underline-offset: 3px; cursor: help; }
.tip-bubble {
  position: absolute; left: 0; top: calc(100% + 6px); z-index: var(--z-menu); max-width: 280px; padding: var(--sp-2) var(--sp-3);
  border-radius: var(--radius); background: var(--chrome-bg); color: var(--chrome-text); box-shadow: var(--shadow-lg);
  font-size: var(--fs-sm); font-weight: var(--fw-normal); text-decoration: none; white-space: normal;
}

/* ---- Autocomplete ([data-lookup]) ---------------------------------------- */
.lta-menu { position: absolute; left: 0; right: 0; top: 100%; z-index: var(--z-menu); max-height: 260px; overflow-y: auto; margin-top: 4px; padding: var(--sp-1); background: var(--surface-float); border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-lg); }
.lta-item { display: flex; flex-direction: column; align-items: flex-start; width: 100%; min-height: 40px; padding: var(--sp-2) var(--sp-3); border: 0; border-radius: var(--radius-sm); background: transparent; color: var(--text); text-align: left; }
.lta-item:hover, .lta-item.is-active { background: var(--accent-soft); color: var(--accent-deep); }
.lta-item__label { font-weight: var(--fw-semibold); }
.lta-item__detail { font-size: var(--fs-xs); color: var(--text-muted); }

/* ---- Notification menu --------------------------------------------------- */
.notif { position: relative; }
.notif__menu { display: none; position: absolute; right: 0; top: calc(100% + 6px); z-index: var(--z-menu); width: min(380px, calc(100vw - var(--sp-6))); background: var(--surface-float); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); }
.notif.is-open .notif__menu { display: block; }
.notif__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border); }
.notif__title { margin: 0; font-size: var(--fs-md); }
.notif__markall { border: 0; background: transparent; color: var(--link); font-size: var(--fs-sm); font-weight: var(--fw-semibold); min-height: 32px; }
.notif__markall:hover { text-decoration: underline; }
.notif__list { list-style: none; margin: 0; padding: 0; max-height: 360px; overflow-y: auto; }
.notif__item { display: flex; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--line-2); color: var(--text); text-decoration: none; }
.notif__item:last-child { border-bottom: 0; }
.notif__item:hover { background: var(--surface-2); }
.notif__item.is-unread { background: var(--accent-soft); }
.notif__ic { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 32px; height: 32px; border-radius: 50%; background: var(--surface-2); color: var(--text-muted); }
.notif__txt { min-width: 0; flex: 1 1 auto; }
.notif__t { font-weight: var(--fw-semibold); }
.notif__b { font-size: var(--fs-sm); color: var(--text-muted); }
.notif__time { font-size: var(--fs-xs); color: var(--text-faint); }
.notif__dot { width: 8px; height: 8px; flex: none; border-radius: 50%; background: var(--accent); margin-top: 8px; }
.notif__empty { padding: var(--sp-4); text-align: center; color: var(--text-muted); }
.notif__foot { display: block; padding: var(--sp-3) var(--sp-4); border-top: 1px solid var(--border); background: var(--surface-2); text-align: center; font-weight: var(--fw-semibold); text-decoration: none; border-radius: 0 0 var(--radius-lg) var(--radius-lg); }

/* ---- Contextual help drawer ---------------------------------------------- */
.help-drawer { position: fixed; inset: 0; z-index: var(--z-modal); }
.help-drawer__scrim { position: absolute; inset: 0; border: 0; padding: 0; background: var(--scrim); cursor: pointer; }
.help-drawer__panel { position: absolute; top: 0; right: 0; bottom: 0; width: min(440px, 100vw); display: flex; flex-direction: column; background: var(--surface); border-left: 1px solid var(--border); box-shadow: var(--shadow-lg); }
.help-drawer__head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-3);
  padding: var(--sp-4); border-bottom: 1px solid var(--chrome-line);
  background: linear-gradient(135deg, var(--chrome-bg) 0%, var(--chrome-bg-2) 100%); color: var(--chrome-text);
}
.help-drawer__eyebrow { margin: 0 0 2px; font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--chrome-text-dim); }
.help-drawer__title { margin: 0; font-size: var(--fs-lg); color: var(--white); }
.help-drawer__x { display: inline-flex; align-items: center; justify-content: center; width: var(--control-h); height: var(--control-h); flex: none; border: 0; border-radius: var(--radius); background: var(--chrome-active); color: var(--chrome-text); }
.help-drawer__x:hover { background: var(--chrome-line); color: var(--white); }
.help-drawer__body { flex: 1 1 auto; overflow-y: auto; padding: var(--sp-4); }
.help-block { margin-bottom: var(--sp-5); }
.help-block__title { display: flex; align-items: center; gap: var(--sp-2); margin: 0 0 var(--sp-2); font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--text-muted); }
.help-block__title svg { color: var(--accent); }
.help-steps, .help-tips { margin: 0; padding-left: var(--sp-5); }
.help-steps li, .help-tips li { margin-bottom: var(--sp-2); }
.help-steps li::marker { color: var(--accent); font-weight: var(--fw-bold); }
.help-terms dt { font-weight: var(--fw-semibold); margin-top: var(--sp-2); }
.help-terms dd { margin: 0 0 var(--sp-2); color: var(--text-muted); }
.help-drawer__foot { padding: var(--sp-3) var(--sp-4); border-top: 1px solid var(--border); background: var(--surface-2); font-size: var(--fs-sm); color: var(--text-muted); display: flex; justify-content: space-between; gap: var(--sp-2); flex-wrap: wrap; }

/* ---- Command palette ----------------------------------------------------- */
.palette { position: fixed; inset: 0; z-index: var(--z-palette); }
.palette__scrim { position: absolute; inset: 0; border: 0; padding: 0; background: var(--scrim); cursor: pointer; }
.palette__dialog { position: relative; width: min(640px, calc(100vw - var(--sp-6))); margin: 10vh auto 0; background: var(--surface-float); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); overflow: hidden; }
.palette__row { display: flex; align-items: center; gap: var(--sp-2); padding: var(--sp-2) var(--sp-3); border-bottom: 1px solid var(--border); }
.palette__row-ico { color: var(--text-faint); display: inline-flex; }
.palette__input { flex: 1 1 auto; min-width: 0; min-height: var(--touch); border: 0; background: transparent; font-size: var(--fs-base); color: var(--text); }
.palette__input::placeholder { color: var(--text-faint); }
.palette__list { list-style: none; margin: 0; padding: var(--sp-2); max-height: 50vh; overflow-y: auto; }
.palette__grp + .palette__grp { margin-top: var(--sp-2); }
.palette__group { padding: var(--sp-2) var(--sp-3) var(--sp-1); font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--text-faint); }
.palette__option { display: flex; align-items: center; gap: var(--sp-3); min-height: 44px; padding: var(--sp-2) var(--sp-3); border-radius: var(--radius); color: var(--text); cursor: pointer; }
.palette__option svg { flex: none; color: var(--text-muted); }
.palette__option[aria-selected="true"], .palette__option:hover { background: var(--accent-soft); color: var(--accent-deep); }
.palette__option[aria-selected="true"] svg { color: inherit; }
.palette__option-main { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.palette__option-title { font-weight: var(--fw-medium); }
.palette__option-sub { font-size: var(--fs-xs); color: var(--text-muted); }
.palette__option-badge { font-size: var(--fs-xs); padding: 1px 8px; border-radius: var(--radius-pill); background: var(--surface-3); color: var(--text-muted); }
.palette__empty { padding: var(--sp-5) var(--sp-4); text-align: center; color: var(--text-muted); }
.palette__empty-title { margin: 0; font-weight: var(--fw-medium); }
.palette__empty-sub { margin: var(--sp-1) 0 0; font-size: var(--fs-sm); }
.palette__foot { display: flex; justify-content: space-between; gap: var(--sp-2); flex-wrap: wrap; padding: var(--sp-2) var(--sp-3); border-top: 1px solid var(--border); background: var(--surface-2); font-size: var(--fs-xs); color: var(--text-muted); }

/* ---- Keyboard shortcuts sheet -------------------------------------------- */
.shortcuts { position: fixed; inset: 0; z-index: var(--z-modal); }
.shortcuts__scrim { position: absolute; inset: 0; border: 0; padding: 0; background: var(--scrim); cursor: pointer; }
.shortcuts__panel { position: relative; width: min(560px, calc(100vw - var(--sp-6))); margin: 10vh auto 0; padding: var(--sp-5); background: var(--surface-float); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); }
.shortcuts__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--sp-3); }
.shortcuts__title { margin: 0; }
.shortcuts__x { display: inline-flex; align-items: center; justify-content: center; width: var(--control-h); height: var(--control-h); border: 0; border-radius: var(--radius); background: var(--surface-2); color: var(--text-muted); }
.shortcuts__x:hover { background: var(--surface-3); color: var(--text); }
.shortcuts__grid { display: grid; grid-template-columns: 1fr auto; gap: var(--sp-2) var(--sp-4); align-items: center; }
.shortcuts__label { grid-column: 1 / -1; margin-top: var(--sp-2); font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--text-muted); }
.shortcuts__keys { display: inline-flex; gap: 4px; }
.shortcuts__note { margin: var(--sp-3) 0 0; font-size: var(--fs-sm); color: var(--text-muted); }

/* ---- Footer -------------------------------------------------------------- */
.app-footer { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); flex-wrap: wrap; padding: var(--sp-3) var(--sp-5); border-top: 1px solid var(--border); font-size: var(--fs-xs); color: var(--text-muted); background: var(--surface); }
.app-footer__class { font-weight: var(--fw-semibold); letter-spacing: 0.02em; }
.app-footer code { font-size: var(--fs-xs); }
.app-footer a { color: var(--text-muted); }
.app-footer a:hover { color: var(--link); }

/* ---- Bottom tab bar + sheet (phones) ------------------------------------- */
.abn, .abn-sheet { display: none; }

/* ---- Guest shell (sign-in, step-up, errors) ------------------------------
   The ground is the deep green chrome and the card floats on it: the same
   two-surface arrangement the console uses, reduced to one column. The gold
   hairline at the head of the card is decorative only -- it carries no
   state, so it takes the accent rather than the decorative --sky, which is
   rated against the dark chrome and not against a card. */
.guest-body { display: flex; flex-direction: column; min-height: 100vh; min-height: 100dvh; background: var(--chrome-bg); }
.guest-main { flex: 1 1 auto; display: flex; align-items: center; justify-content: center; padding: var(--sp-7) var(--gutter); }
.guest-card {
  position: relative; width: 100%; max-width: 440px; padding: var(--sp-6) var(--sp-5) var(--sp-5); overflow: hidden;
  background: var(--surface-float); border: 1px solid var(--border-strong); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg);
  margin-bottom: 0;
}
.guest-card::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 3px; background: var(--accent); }
.guest-card--wide { max-width: 640px; }
.guest-brand { display: flex; flex-direction: column; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-5); text-align: center; }
.guest-brand .mark { flex-direction: column; gap: var(--sp-2); }
.guest-brand .mark__img { height: 48px; width: auto; }
.guest-brand .mark__name { font-size: var(--fs-xl); letter-spacing: 0.02em; }
.guest-brand .mark__sub { color: var(--text-muted); }
.guest-brand__sub { font-size: var(--fs-sm); font-weight: var(--fw-medium); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--text-muted); }
.guest-title { margin: 0 0 var(--sp-2); font-size: var(--fs-lg); font-weight: var(--fw-bold); text-align: center; }
.guest-card .form-actions { margin-top: var(--sp-5); }
.guest-footer { padding: var(--sp-4) var(--gutter) var(--sp-5); text-align: center; font-size: var(--fs-xs); color: var(--chrome-text-dim); }
.guest-footer p { margin: 0 0 var(--sp-1); }
.guest-footer strong { color: var(--chrome-text); }
.guest-footer code { color: var(--chrome-text); }

/* ---- Print meta (screen: hidden) ----------------------------------------- */
.print-meta, .print-only { display: none; }

/* ---- Utilities ----------------------------------------------------------- */
.muted { color: var(--text-muted); }
.faint { color: var(--text-faint); }
.text-sm { font-size: var(--fs-sm); }
.text-xs { font-size: var(--fs-xs); }
.text-right { text-align: right; }
.text-center { text-align: center; }
.mt-0 { margin-top: 0; }
.mb-0 { margin-bottom: 0; }
.mb-2 { margin-bottom: var(--sp-2); }
.mb-4 { margin-bottom: var(--sp-4); }
.flex { display: flex; gap: var(--sp-2); align-items: center; flex-wrap: wrap; }
.flex--between { justify-content: space-between; }
.stack > * + * { margin-top: var(--sp-3); }
.hidden { display: none; }
.nav-ico { display: inline-flex; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ---- Focus ring (WCAG 2.4.7 / 2.4.11) ------------------------------------
   ONE ring everywhere, and it is two rings: the outline plus the --focus-halo
   behind it. The halo is load-bearing, not decoration -- in the hc theme the
   ring and the chrome are both black and the white halo is the only visible
   edge. It sits AFTER every component so that no card, tile or button shadow
   can replace it by source order; a component that genuinely needs a
   different ring (the sidebar on the dark chrome, the palette input inside
   its own border) says so with a more specific selector, below. */
:focus-visible {
  outline: var(--focus-w) solid var(--focus-color);
  outline-offset: var(--focus-offset);
  box-shadow: 0 0 0 var(--focus-offset) var(--focus-halo);
}
.sidebar a:focus-visible, .sidebar button:focus-visible {
  outline: var(--focus-w) solid var(--chrome-text);
  outline-offset: -2px;
  box-shadow: none;
}
.app__content:focus-visible { outline-offset: -2px; }
.palette__input:focus-visible { outline-offset: -2px; box-shadow: none; }

/* ---- Coarse pointers: the 48px touch floor (PRD 14.1) -------------------- */
@media (pointer: coarse) {
  .btn, .topbar__toggle, .topbar__icon-btn, .topbar__user, .dropdown__item, .page-btn, .nav-item,
  .field-control, .field > :where(input:not([type="checkbox"]):not([type="radio"])), .field > :where(select),
  .tab-strip [role="tab"], .tab-strip .tab, .check { min-height: var(--touch); }
  .btn--sm { min-height: var(--touch); }
  .check input[type="checkbox"], .check input[type="radio"], .field input[type="checkbox"], .field input[type="radio"] { width: 24px; height: 24px; }
}

/* ---- Responsive ---------------------------------------------------------- */
@media (max-width: 1024px) {
  .app__main, .app.is-collapsed .app__main { margin-left: 0; }
  .sidebar { display: none; width: var(--sidebar-w); box-shadow: var(--shadow-lg); }
  .app.is-mobile-open .sidebar { display: flex; }
  .app.is-collapsed .sidebar { width: var(--sidebar-w); }
  /* On a drawer the rail is meaningless: every clipped label comes back. */
  .app.is-collapsed .mark__name, .app.is-collapsed .nav-item__text {
    position: static; width: auto; height: auto; margin: 0; overflow: visible; clip: auto;
  }
  .app.is-collapsed .mark__sub, .app.is-collapsed .sidebar__foot { display: block; }
  .app.is-collapsed .nav-item__badge { display: inline-block; }
  .app.is-collapsed .nav-section__label { padding: var(--sp-3) var(--sp-3) var(--sp-1); text-align: left; clip-path: none; }
  .app.is-collapsed .sidebar__brand { padding: 0 var(--sp-4); justify-content: flex-start; }
  .app.is-collapsed .nav-item { justify-content: flex-start; padding: var(--sp-2) var(--sp-3); }
  .topbar__toggle { display: inline-flex; }
  .stats-grid, .stats-grid--6 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media (max-width: 768px) {
  .grid-2, .grid-3, .form-grid { grid-template-columns: 1fr; }
  .stats-grid, .stats-grid--6, .stats-grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .skeleton-set--tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 640px) {
  .app__content { padding: var(--sp-4) var(--gutter) calc(var(--bottom-nav-h) + var(--sp-6)); }
  .topbar { padding: 0 var(--sp-2); gap: var(--sp-1); }
  .topbar__search { display: none; }
  .topbar__user-meta { display: none; }
  .topbar__icon-btn .topbar__lbl { display: none; }
  .page-header { align-items: flex-start; flex-direction: column; }
  .page-header__actions { width: 100%; }
  .page-header__actions .btn { flex: 1 1 auto; }
  .grid-toolbar { flex-direction: column; align-items: stretch; }
  .grid-toolbar__filters { flex-direction: column; align-items: stretch; }
  .grid-search input { width: 100%; min-width: 0; }
  .stats-grid > :last-child:nth-child(odd) { grid-column: 1 / -1; }
  .stat-tile { flex-direction: column; gap: var(--sp-2); min-height: 0; }
  .stat-tile__body { width: 100%; }
  .stat-tile__icon { width: 38px; height: 38px; }
  .stat-tile__value { font-size: var(--fs-xl); }
  .data-table thead th, .data-table tbody td { padding: var(--sp-2) var(--sp-3); }
  .data-table thead th.is-sortable > a { margin: calc(var(--sp-2) * -1) calc(var(--sp-3) * -1); padding: var(--sp-2) var(--sp-3); }
  .modal-overlay { padding: var(--sp-2); align-items: flex-end; }
  .modal { max-height: 92vh; }
  body > .flash-stack { left: var(--gutter); right: var(--gutter); bottom: calc(var(--bottom-nav-h) + var(--sp-3)); width: auto; }
  .breadcrumb a, .breadcrumb span[aria-current] { display: inline-flex; align-items: center; min-height: 24px; }
  .btn, .page-btn, .dropdown__item, .tab-strip [role="tab"], .tab-strip .tab { min-height: var(--touch); }
  input[type="checkbox"], input[type="radio"] { min-width: 24px; min-height: 24px; }
  .data-table summary { display: flex; align-items: center; min-height: var(--touch); }
  .app-footer { flex-direction: column; align-items: flex-start; padding: var(--sp-3) var(--gutter) calc(var(--bottom-nav-h) + var(--sp-3)); }
  .guest-main { padding: var(--sp-4) var(--gutter); }
  .guest-card { padding: var(--sp-5) var(--sp-4) var(--sp-4); }

  /* Bottom tab bar: the four most-used destinations + More. */
  .abn {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-bottom-nav);
    min-height: var(--bottom-nav-h); padding-bottom: env(safe-area-inset-bottom, 0);
    background: var(--surface); border-top: 1px solid var(--border); box-shadow: var(--shadow-md);
  }
  .abn__tab {
    flex: 1 1 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
    min-height: var(--bottom-nav-h); padding: var(--sp-1); border: 0; background: transparent;
    color: var(--text-muted); text-decoration: none; font-size: var(--fs-xs); font-weight: var(--fw-semibold);
  }
  .abn__tab.is-active { color: var(--accent); box-shadow: inset 0 3px 0 var(--accent); }
  .abn__ic { display: inline-flex; }
  .abn__lbl { white-space: nowrap; }
  .abn-sheet { display: block; position: fixed; inset: 0; z-index: var(--z-sheet); }
  .abn-sheet__scrim { position: absolute; inset: 0; border: 0; padding: 0; background: var(--scrim); cursor: pointer; }
  .abn-sheet__panel { position: absolute; left: 0; right: 0; bottom: 0; max-height: 85vh; display: flex; flex-direction: column; background: var(--surface); border-top: 1px solid var(--border); border-radius: var(--radius-lg) var(--radius-lg) 0 0; box-shadow: var(--shadow-lg); padding-bottom: env(safe-area-inset-bottom, 0); }
  .abn-sheet__head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border); }
  .abn-sheet__who { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; }
  .abn-sheet__name { font-weight: var(--fw-semibold); }
  .abn-sheet__role { font-size: var(--fs-xs); color: var(--text-muted); }
  .abn-sheet__x { display: inline-flex; align-items: center; justify-content: center; width: var(--touch); height: var(--touch); border: 0; border-radius: var(--radius); background: var(--surface-2); color: var(--text-muted); }
  .abn-sheet__body { overflow-y: auto; padding: var(--sp-2) var(--sp-3) var(--sp-3); }
  .abn-sheet__group-label { padding: var(--sp-3) var(--sp-2) var(--sp-1); font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--text-muted); }
  .abn-sheet__links { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--sp-2); }
  .abn-sheet__link { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; min-height: var(--touch); padding: var(--sp-2) var(--sp-3); border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-2); color: var(--text); text-decoration: none; font-weight: var(--fw-medium); }
  .abn-sheet__link.is-active { border-color: var(--accent); color: var(--accent-deep); background: var(--accent-soft); }
  .abn-sheet__signout { margin-top: var(--sp-3); padding-top: var(--sp-3); border-top: 1px solid var(--border); }
  body.abn-sheet-open { position: fixed; width: 100%; overflow: hidden; }
}

/* ---- Print (PRD 14.6): A4, black and white, controls hidden -------------- */
@page { size: A4; margin: 14mm; }
@media print {
  body { background: var(--white); color: var(--black); font-size: 11pt; }
  .sidebar, .topbar, .app-footer, .abn, .abn-sheet, #progress-bar, .flash-stack, .help-drawer, .palette, .shortcuts,
  .env-banner, .page-header__actions, .btn, .tip-bubble, .skip-link, .app__scrim, .modal-overlay, .table-more,
  .grid-toolbar, form[role="search"], [data-print-hide], .pagination__pages, .page-btn, .card__footer:has(> .btn):not(:has(> *:not(.btn))) { display: none !important; }
  .data-table th.col-actions, .data-table td.col-actions, .data-table th.col-check, .data-table td.col-check { display: none !important; }
  .app__main, .app.is-collapsed .app__main { margin: 0 !important; }
  .app__content { padding: 0 !important; max-width: none !important; }
  .card, .stat-tile, .record-band, .modal { box-shadow: none !important; border: 1px solid var(--black); break-inside: avoid; }
  .stat-tile::before, .guest-card::before { display: none !important; }
  .record-band { background: var(--white) !important; color: var(--black); }
  .record-band__title, .record-band__id, .record-band__meta { color: var(--black); }
  .grid-2, .grid-3 { display: block; }
  .grid-2 > *, .grid-3 > * { break-inside: avoid; margin-bottom: 8pt; }
  .stats-grid, .stats-grid--6, .stats-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .table-wrap, .table-scroll, .table-wrap--tall { overflow: visible !important; max-height: none !important; background: none !important; }
  .data-table thead th { position: static; background: var(--white); border-bottom: 1px solid var(--black); }
  .data-table tbody td { border-bottom: 1px solid var(--border); }
  .data-table tr { break-inside: avoid; }
  .pagination { border: 0; }
  .pagination__info { display: inline !important; }
  .pill, .status, .status__dot, .meter > span, .timeline__item::before { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .pill { border: 1px solid var(--black); background: var(--white) !important; color: var(--black) !important; }
  .status__dot { border: 1px solid var(--black); background: var(--white) !important; }
  .status--crit .status__dot, .status--warn .status__dot { background: var(--black) !important; }
  .guest-body { background: var(--white) !important; }
  .guest-footer, .guest-footer strong, .guest-footer code { color: var(--black); }
  a { color: var(--black); text-decoration: none; }
  .print-meta, .print-only { display: block; }
  .print-meta { margin-top: 12pt; padding-top: 6pt; border-top: 1px solid var(--black); font-size: 9pt; color: var(--black); }
}

/* ---- Reduced motion ------------------------------------------------------
   Everything stops: the three progress indicators and every interactive-state
   transition introduced with the VANTAGE restyle, including the hover lift,
   which is a movement whether or not it is tweened. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition: none !important; }
  .stat-tile--link:hover, .btn:active { transform: none; }
  .skeleton::after { animation: none; }
  .spinner { animation: none; border-top-color: var(--border); }
  #progress-bar { animation: none; }
}

/* ============================================================================
   The sign-in screen (templates/layouts/guest.php, split mode)
   ----------------------------------------------------------------------------
   A floating card centred on a tinted page, divided into the form (left) and
   a brand and assurance panel (right). Below 62rem the panel is removed from
   the flow entirely and the card becomes a single column: on a phone the
   panel is what somebody has to scroll past to reach the thing they came for.

   The FORM LEADS in the document. It is first for a screen reader and first on
   a phone; the panel is supporting material and is marked up as an aside.

   Identity comes from FILES/flyer.jpeg: the navy #002868 that carries the
   headline band and the footer bar, with the party mark in the mark slot -
   the sign-in screen is one of the two places PRD 14.5 permits it. There is no
   photograph, no candidate imagery and no slogan anywhere on this page; the
   decoration is a hairline grid and two soft washes drawn from tokens, which
   degrade to nothing if a paint is dropped.
   ============================================================================ */

.auth-body {
    min-height: 100vh;
    margin: 0;
    background: var(--bg);
}

.auth-stage {
    position: relative;
    isolation: isolate;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--sp-5);
    padding: var(--sp-6) var(--gutter);
}

/* Page decoration, painted under everything. */
.auth-stage-grid,
.auth-stage-glow {
    position: absolute;
    z-index: -1;
    pointer-events: none;
}

.auth-stage-grid {
    inset: 0;
    background-image:
        linear-gradient(to right, var(--line-2) 1px, transparent 1px),
        linear-gradient(to bottom, var(--line-2) 1px, transparent 1px);
    background-size: 56px 56px;
    /* The mask's colour channel is OPACITY, not paint - `black` here means
       "fully visible", which is why this is not a colour literal escaping
       tokens.css. It fades the grid out towards the edges so the card is not
       sitting on a hard-edged rectangle. */
    -webkit-mask-image: radial-gradient(ellipse at 50% 40%, black 0%, transparent 75%);
    mask-image: radial-gradient(ellipse at 50% 40%, black 0%, transparent 75%);
    opacity: 0.8;
}

.auth-stage-glow {
    width: 42rem;
    height: 42rem;
    border-radius: 50%;
    top: -16rem;
    right: -14rem;
    background: radial-gradient(circle, var(--brand-bright) 0%, transparent 70%);
    opacity: 0.22;
}

.auth-stage-glow--2 {
    top: auto;
    right: auto;
    bottom: -18rem;
    left: -14rem;
    background: radial-gradient(circle, var(--sky) 0%, transparent 70%);
    opacity: 0.16;
}

/* -- The card -------------------------------------------------------------- */

.auth-card {
    width: 100%;
    max-width: 62rem;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-lg);
    overflow: hidden;
}

/* -- The form column ------------------------------------------------------- */

.auth-form-col {
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: var(--sp-7) var(--sp-6);
    background: var(--surface);
}

.auth-form-card {
    width: 100%;
    max-width: 24rem;
    margin: 0 auto;
}

.auth-mark {
    margin-bottom: var(--sp-6);
}

.auth-head {
    margin-bottom: var(--sp-5);
}

.auth-head h1 {
    margin: 0 0 var(--sp-2);
    font-size: var(--fs-xl);
    line-height: var(--lh-tight);
    font-weight: var(--fw-bold);
    color: var(--text);
    letter-spacing: -0.01em;
}

.auth-head p {
    margin: 0;
    color: var(--text-muted);
    font-size: var(--fs-sm);
    line-height: var(--lh);
}

.auth-submit {
    width: 100%;
    justify-content: center;
    margin-top: var(--sp-4);
}

.auth-notice {
    margin-top: var(--sp-5);
    padding: var(--sp-3) var(--sp-4);
    border: 1px solid var(--border);
    border-left: 3px solid var(--accent);
    border-radius: var(--radius-sm);
    background: var(--surface-2);
    color: var(--text-muted);
    font-size: var(--fs-sm);
    line-height: var(--lh);
}

.auth-help {
    margin-top: var(--sp-5);
    font-size: var(--fs-sm);
    color: var(--text-muted);
}

/* -- The brand and assurance panel ----------------------------------------- */

.auth-brand {
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: var(--sp-5);
    padding: var(--sp-7) var(--sp-6);
    /* A LIGHT panel. The card sits on a tinted page and the panel is one step
       deeper, not a dark slab: at 1.25:1 against the form column the edge is
       invisible on its own, so the divider is explicit rather than implied by
       tone. */
    background: var(--soft);
    color: var(--text-muted);
    border-left: 1px solid var(--border);
    isolation: isolate;
}

.auth-brand-grid,
.auth-brand-glow {
    position: absolute;
    z-index: -1;
    pointer-events: none;
}

.auth-brand-grid {
    inset: 0;
    background-image:
        linear-gradient(to right, var(--line-strong) 1px, transparent 1px),
        linear-gradient(to bottom, var(--line-strong) 1px, transparent 1px);
    background-size: 44px 44px;
    opacity: 0.5;
}

.auth-brand-glow {
    width: 26rem;
    height: 26rem;
    border-radius: 50%;
    top: -9rem;
    right: -11rem;
    background: radial-gradient(circle, var(--sky) 0%, transparent 70%);
    opacity: 0.18;
}

.auth-brand-top {
    display: flex;
    align-items: flex-start;
    justify-content: flex-end;
}

/* The classification, in WORDS. Not a status dot: a coloured dot nobody can
   name is decoration, and this line is a handling instruction. */
.auth-status {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-1) var(--sp-3);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-pill);
    background: var(--surface);
    color: var(--text);
    font-size: var(--fs-xs);
    font-weight: var(--fw-medium);
    letter-spacing: var(--tracking);
    white-space: nowrap;
}

.auth-brand-mid h2 {
    margin: var(--sp-3) 0 var(--sp-4);
    font-size: var(--fs-2xl);
    line-height: var(--lh-tight);
    font-weight: var(--fw-bold);
    color: var(--brand);
    letter-spacing: -0.01em;
}

.auth-eyebrow {
    margin: 0;
    font-size: var(--fs-xs);
    font-weight: var(--fw-semibold);
    letter-spacing: var(--tracking-wide);
    text-transform: uppercase;
    color: var(--sky-deep);
}

/* The same eyebrow on a LIGHT surface, where the chrome tone is unreadable. */
.auth-eyebrow--dark {
    color: var(--sky-deep);
}

.auth-brand-lede {
    margin: 0;
    font-size: var(--fs-base);
    line-height: var(--lh);
    color: var(--text);
}

.auth-features {
    list-style: none;
    margin: var(--sp-6) 0 0;
    padding: 0;
    display: grid;
    gap: var(--sp-4);
}

.auth-features li {
    display: flex;
    align-items: flex-start;
    gap: var(--sp-3);
    font-size: var(--fs-sm);
    line-height: var(--lh);
    color: var(--text-muted);
}

.auth-features strong {
    display: block;
    color: var(--text);
    font-weight: var(--fw-semibold);
}

.auth-feature-ico {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--border-strong);
    background: var(--surface);
    color: var(--brand);
}

.auth-brand-foot {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin: 0;
    font-size: var(--fs-xs);
    color: var(--text-faint);
}

.auth-stage .guest-footer {
    width: 100%;
    max-width: 62rem;
    margin: 0;
    text-align: center;
}

/* -- Narrow: the card becomes one column ----------------------------------- */

@media (max-width: 62rem) {
    .auth-card {
        grid-template-columns: minmax(0, 1fr);
        max-width: 30rem;
    }

    /* The panel is supporting material. On a phone it is what somebody would
       have to scroll past to reach the form, so it is removed rather than
       stacked: the mark, the classification and the security line are already
       carried by the form column and the footer. */
    .auth-brand {
        display: none;
    }

    .auth-form-col {
        padding: var(--sp-6) var(--sp-5);
    }

    .auth-stage {
        justify-content: flex-start;
        padding-top: var(--sp-5);
    }
}

/* -- The sign-in fields ------------------------------------------------------
   The reference design groups the credentials into one bordered block with an
   accent rail down the focused field, rather than two loose inputs. Scoped to
   the auth card ON PURPOSE: `field` and `field-control` are the platform's
   shared form primitives used on every screen, and a login screen is not a
   reason to change how a case form looks. */

.auth-form-card .field + .field {
    margin-top: var(--sp-3);
}

.auth-form-card .field-input {
    position: relative;
    border-radius: var(--radius);
    transition: box-shadow var(--dur) var(--ease);
}

/* The rail. It is drawn on the wrapper rather than the input so it sits
   outside the control's own border and cannot shift the text. */
.auth-form-card .field-input::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    border-radius: var(--radius) 0 0 var(--radius);
    background: var(--accent);
    opacity: 0;
    transition: opacity var(--dur-fast) var(--ease);
}

.auth-form-card .field-input:focus-within::before {
    opacity: 1;
}

/* A field carrying an error keeps its own rail: the status colour wins over
   the focus colour, because which field is wrong outranks which field is
   being typed in. */
.auth-form-card .field.is-invalid .field-input::before {
    background: var(--status-crit);
    opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
    .auth-form-card .field-input,
    .auth-form-card .field-input::before {
        transition: none;
    }
}
