/* UI pass v2 — every rule scoped under html[data-ui="v2"]. See docs/ui-v2.md.

   Theme lane: tokens, boxes, shell (rail, header, tabs, ticker), motion, and
   the utility remap. Loaded after theme.css and before base.html's inline
   <style>, so shell rules that base.html also writes for html.dark carry a
   .dark twin here to stay ahead of it.

   Design rules (docs/ui-v2.md has the full list):
   - one neutral ramp, one accent (blue), three state colours; colour means
     state, never decoration. Amber is warning only.
   - solid surfaces: no translucency, blur, gradients, glows or idle motion
   - one edge per box: 1px border, no shadow ring in dark, background-clip
   - radius 4px chips, 6px buttons and inputs, 8px cards and modals

   Existing variable names are remapped, so every current var(--…) use picks
   the new values up without template edits. New names: --bg-inset,
   --bg-hover, --border-strong, --border-input, --border-button, --text-muted, --on-accent,
   --accent-ring, --success/--warning/--danger (+ -fill), --chart-neutral,
   --shadow-float. */

/* ── Font: Inter Variable 4.1, self-hosted ─────────────────── */
/* @font-face cannot be scoped to a selector. It only registers the family;
   nothing renders in it unless a rule under html[data-ui="v2"] names it, and
   this file is only linked under the flag. Served from /static-v2/fonts/
   (CSP font-src is 'self'). The italic file is fetched only when italic
   text is on the page. Same URLs, ?v included, as the preload links in
   base.html and launcher.html. See docs/ui-v2-typography.md. */
@font-face {
  font-family: InterVariable;
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/InterVariable-latin.woff2?v=4.1") format("woff2");
}
@font-face {
  font-family: InterVariable;
  font-style: italic;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/InterVariable-Italic-latin.woff2?v=4.1") format("woff2");
}

/* ── Tokens, dark ─────────────────────────────────────────── */
html[data-ui="v2"].dark {
  color-scheme: dark;
  --bg-primary:    #0F1115;
  --bg-secondary:  #0F1115;
  --bg-card:       #16181D;
  --bg-card-hover: #16181D;
  --bg-sidebar:    #16181D;
  --bg-inset:      #1D2026;
  --bg-tertiary:   #1D2026;
  --bg-input:      #1D2026;
  --bg-hover:      #23262D;
  --border-primary:   #2A2E36;
  --border-secondary: #2A2E36;
  --border-strong:    #3B404A;
  --border-input:     #707683;
  --border-button:    #3B404A;
  --text-heading:   #E6E8EC;
  --text-primary:   #E6E8EC;
  --text-secondary: #B0B6C1;
  --text-tertiary:  #8F96A3;
  --text-muted:     #8F96A3;
  --meta-strong:    #B0B6C1;
  --meta-subtle:    #8F96A3;
  --accent:          #74A3FF;
  --accent-hover:    #93B8FF;
  --on-accent:       #0F1115;
  --accent-soft:     #212938;
  --accent-ring:     rgba(116, 163, 255, 0.35);
  --accent-glow:     transparent;
  --accent-gradient: linear-gradient(var(--accent), var(--accent));
  --blue:      #74A3FF;
  --blue-soft: #212938;
  --cyan:      #74A3FF;
  --success:      #52C98F;
  --success-fill: #1D2D2B;
  --warning:      #E2A336;
  --warning-fill: #2E2920;
  --danger:       #F47C86;
  --danger-fill:  #31242A;
  --emerald: #52C98F;
  --amber:   #E2A336;
  --red:     #F47C86;
  --chart-neutral: #6A7080;
  --chart-data:    #7D9DDB;
  --shadow-card:    none;
  --shadow-float:   0 8px 24px rgba(0, 0, 0, 0.5);
  --shadow-sidebar: 1px 0 0 #2A2E36;
}

/* ── Tokens, light ────────────────────────────────────────── */
html[data-ui="v2"]:not(.dark) {
  color-scheme: light;
  --bg-primary:    #F6F7F9;
  --bg-secondary:  #F6F7F9;
  --bg-card:       #FFFFFF;
  --bg-card-hover: #FFFFFF;
  --bg-sidebar:    #FFFFFF;
  --bg-inset:      #F1F3F6;
  --bg-tertiary:   #F1F3F6;
  --bg-input:      #F1F3F6;
  --bg-hover:      #EBEEF2;
  --border-primary:   #E3E6EB;
  --border-secondary: #E3E6EB;
  --border-strong:    #CDD2DA;
  --border-input:     #767D8B;
  --border-button:    #D0D4DB;
  --text-heading:   #16181D;
  --text-primary:   #16181D;
  --text-secondary: #343A45;
  --text-tertiary:  #505764;
  --text-muted:     #505764;
  --meta-strong:    #343A45;
  --meta-subtle:    #505764;
  --accent:          #1D4ED8;
  --accent-hover:    #1E40AF;
  --on-accent:       #FFFFFF;
  --accent-soft:     #EAF0FD;
  --accent-ring:     rgba(29, 78, 216, 0.3);
  --accent-glow:     transparent;
  --accent-gradient: linear-gradient(var(--accent), var(--accent));
  --blue:      #1D4ED8;
  --blue-soft: #EAF0FD;
  --cyan:      #1D4ED8;
  --success:      #17784C;
  --success-fill: #E7F4ED;
  --warning:      #915C00;
  --warning-fill: #FBF1DF;
  --danger:       #C23441;
  --danger-fill:  #FCEAEC;
  --emerald: #17784C;
  --amber:   #915C00;
  --red:     #C23441;
  --chart-neutral: #8E95A2;
  --chart-data:    #7090D8;
  --shadow-card:    0 1px 2px rgba(16, 24, 40, 0.05);
  --shadow-float:   0 8px 24px rgba(16, 24, 40, 0.12);
  --shadow-sidebar: 1px 0 0 #E3E6EB;
}

/* ── Base ─────────────────────────────────────────────────── */
/* Type tokens (docs/ui-v2-typography.md). The whole scale stepped up one
   notch on 2026-09-20 ("slightly easier to read"): six sizes, 13 / 14 / 16 /
   18 / 24 / 28, nothing under 13px anywhere. Micro and meta are both 13 and
   differ only in leading — micro is the single-line badge and caps chip.
   Line-heights are on the 4px grid (the draft's 26px is the one exception);
   weights 400 / 500 / 600 only. Tracking is Inter's dynamic metric
   −0.0223 + 0.185·e^(−0.1745·size) em at each size, so it tightens as the
   size grows: change a size and the tracking beside it changes with it. */
html[data-ui="v2"] {
  background: var(--bg-primary);
  --font-sans: InterVariable, "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace;
  --font-features: "cv01", "ss03", "liga", "calt";
  --fs-micro:   13px;  --lh-micro:   16px;  --tr-micro:   -0.003em;
  --fs-meta:    13px;  --lh-meta:    20px;  --tr-meta:    -0.003em;
  --fs-ui:      14px;  --lh-ui:      20px;  --tr-ui:      -0.006em;
  --fs-body:    16px;  --lh-body:    24px;  --tr-body:    -0.011em;
  --lh-draft:   26px;
  --fs-section: 18px;  --lh-section: 24px;  --tr-section: -0.014em;
  --fs-title:   24px;  --lh-title:   32px;  --tr-title:   -0.019em;
  --fs-kpi:     28px;  --lh-kpi:     36px;  --tr-kpi:     -0.021em;
  --tr-caps: 0.04em;
  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --ctl-h: 32px;  --ctl-h-sm: 28px;  --ctl-px: 12px;  --ctl-gap: 8px;
  --chip-h: 22px;
  font-family: var(--font-sans);
}
/* Body copy is 14/20. The line-height stays a ratio (20/14) so text that sets
   a bigger size without its own line-height never overlaps; every role and
   remapped utility below sets an exact grid value. Tabular figures are not
   global: prose gets proportional digits, and tables, KPIs, counts and
   badges opt in below. The smoothing properties only affect macOS. */
html[data-ui="v2"] body {
  font-family: var(--font-sans);
  font-feature-settings: var(--font-features);
  font-optical-sizing: auto;
  font-size: var(--fs-ui);
  line-height: 1.4286;
  letter-spacing: var(--tr-ui);
  font-variant-numeric: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
html[data-ui="v2"].dark .text-white {
  color: var(--text-heading);
}
/* Light: text-white is primary text. theme.css already maps it to the
   heading colour at 0,3,0; v2 states it itself so the light theme does not
   lean on that. The coloured fills that keep light-on-fill text (accent,
   status fills, the legacy solid buttons) override this further down. */
html[data-ui="v2"]:not(.dark) .text-white {
  color: var(--text-primary);
}
/* Weights 400, 500, 600 only */
html[data-ui="v2"] .font-bold,
html[data-ui="v2"] .font-extrabold,
html[data-ui="v2"] .font-black,
html[data-ui="v2"] b,
html[data-ui="v2"] strong {
  font-weight: 600;
}
/* Default edge colour: Tailwind's preflight paints every border #e5e7eb, so a
   `border` whose colour class the purged build lacks shows a bright rim.
   :where() keeps this at zero specificity; every colour utility still wins. */
:where(html[data-ui="v2"]) *,
:where(html[data-ui="v2"]) ::before,
:where(html[data-ui="v2"]) ::after {
  border-color: var(--border-primary);
}
/* Semantic text helpers (not in the purged Tailwind build) */
html[data-ui="v2"] .text-success { color: var(--success); }
html[data-ui="v2"] .text-warning { color: var(--warning); }
html[data-ui="v2"] .text-danger  { color: var(--danger); }
html[data-ui="v2"] .text-muted   { color: var(--text-muted); }
html[data-ui="v2"] .tnum         { font-variant-numeric: tabular-nums; }
/* Keyboard focus on links and buttons (inputs keep their border focus) */
html[data-ui="v2"] a:focus-visible,
html[data-ui="v2"] button:focus-visible,
html[data-ui="v2"] summary:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ── Cards and panels: one edge ───────────────────────────── */
html[data-ui="v2"] .card,
html[data-ui="v2"] .card-solid {
  background: var(--bg-card);
  background-clip: padding-box;
  border: 1px solid var(--border-primary);
  border-radius: 8px;
  box-shadow: var(--shadow-card);
  transition: border-color 0.15s;
}
/* Plain panels do not react to hover (a tinted card keeps its tint). */
html[data-ui="v2"] .card:hover,
html[data-ui="v2"].dark .card:hover {
  border-color: var(--border-primary);
  box-shadow: var(--shadow-card);
}
/* Clickable cards: the border steps up, nothing else moves. */
html[data-ui="v2"] a.card:hover,
html[data-ui="v2"] button.card:hover,
html[data-ui="v2"] .card-link:hover,
html[data-ui="v2"] .card.cursor-pointer:hover,
html[data-ui="v2"] .card[hx-get]:hover,
html[data-ui="v2"] .card[\@click]:hover,
html[data-ui="v2"] .card[x-on\:click]:hover,
html[data-ui="v2"].dark a.card:hover,
html[data-ui="v2"].dark button.card:hover,
html[data-ui="v2"].dark .card-link:hover,
html[data-ui="v2"].dark .card.cursor-pointer:hover,
html[data-ui="v2"].dark .card[hx-get]:hover,
html[data-ui="v2"].dark .card[\@click]:hover,
html[data-ui="v2"].dark .card[x-on\:click]:hover {
  border-color: var(--border-strong);
}
html[data-ui="v2"] .glass,
html[data-ui="v2"] .glass-strong,
html[data-ui="v2"]:not(.dark) .glass,
html[data-ui="v2"]:not(.dark) .glass-strong {
  background: var(--bg-card);
  background-clip: padding-box;
  border-color: var(--border-primary);
  box-shadow: var(--shadow-card);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
html[data-ui="v2"] .divider {
  background: var(--border-primary);
}

/* ── Radius: 4 chips, 6 buttons and inputs, 8 cards and modals ── */
html[data-ui="v2"] .rounded-xl,
html[data-ui="v2"] .rounded-2xl,
html[data-ui="v2"] .rounded-3xl {
  border-radius: 8px;
}
html[data-ui="v2"] .card .rounded-lg,
html[data-ui="v2"] .card .rounded-xl,
html[data-ui="v2"] .card .rounded-2xl,
html[data-ui="v2"] button.rounded-lg,
html[data-ui="v2"] button.rounded-xl,
html[data-ui="v2"] button.rounded-2xl,
html[data-ui="v2"] button.rounded-full[class*="px-"],
html[data-ui="v2"] a.rounded-full[class*="px-"],
html[data-ui="v2"] input.rounded-lg,
html[data-ui="v2"] input.rounded-xl,
html[data-ui="v2"] select.rounded-lg,
html[data-ui="v2"] select.rounded-xl,
html[data-ui="v2"] textarea.rounded-lg,
html[data-ui="v2"] textarea.rounded-xl,
html[data-ui="v2"] .btn {
  border-radius: 6px;
}
/* Status chips: 4px. Dots, avatars and toggles (no horizontal padding)
   stay round. */
html[data-ui="v2"] span.rounded-full[class*="px-"],
html[data-ui="v2"] span.rounded-md[class*="px-"],
html[data-ui="v2"] span.rounded-lg[class*="px-"],
html[data-ui="v2"] .badge {
  border-radius: 4px;
}

/* ── Form controls ────────────────────────────────────────── */
/* Theme-prefixed and [class]-qualified so the 3:1 control edge beats the
   border remaps below; a control drawn without a border keeps none. */
html[data-ui="v2"] :is(input, select, textarea),
html[data-ui="v2"].dark :is(input, select, textarea)[class]:where(:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], .border-0, .border-transparent)),
html[data-ui="v2"]:not(.dark) :is(input, select, textarea)[class]:where(:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], .border-0, .border-transparent)) {
  border-color: var(--border-input);
}
html[data-ui="v2"] :is(input, select, textarea):focus,
html[data-ui="v2"].dark :is(input, select, textarea)[class]:focus,
html[data-ui="v2"]:not(.dark) :is(input, select, textarea)[class]:focus {
  border-color: var(--accent);
}
html[data-ui="v2"] input[type="checkbox"],
html[data-ui="v2"] input[type="radio"],
html[data-ui="v2"] input[type="range"] {
  accent-color: var(--accent);
}
/* Selects draw like a ghost button: the soft button edge (the stronger input
   edge on hover), no OS chevron, and the same 12px chevron as the More
   button, 10px in from the right. The image is a data: URI (CSP img-src
   allows data:); the colour is the muted text token, one per theme.
   background-image is !important because some legacy rules reset the
   background shorthand. Multi-line selects keep their native look. */
html[data-ui="v2"] select:not([multiple], [size]),
html[data-ui="v2"].dark select[class]:not([multiple], [size]),
html[data-ui="v2"]:not(.dark) select[class]:not([multiple], [size]) {
  -webkit-appearance: none;
  appearance: none;
  border-color: var(--border-button);
  padding-right: 32px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23646B78' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") !important;
  background-repeat: no-repeat !important;
  background-position: right 10px center !important;
  background-size: 12px 12px !important;
}
html[data-ui="v2"].dark select:not([multiple], [size]),
html[data-ui="v2"].dark select[class]:not([multiple], [size]) {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238F96A3' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E") !important;
}
html[data-ui="v2"] select:not([multiple], [size]):hover,
html[data-ui="v2"].dark select[class]:not([multiple], [size]):hover,
html[data-ui="v2"]:not(.dark) select[class]:not([multiple], [size]):hover {
  border-color: var(--border-input);
}
html[data-ui="v2"] select:not([multiple], [size]):focus,
html[data-ui="v2"].dark select[class]:not([multiple], [size]):focus,
html[data-ui="v2"]:not(.dark) select[class]:not([multiple], [size]):focus {
  border-color: var(--accent);
}
/* Checkboxes: 16px, the accent when checked, a 4px radius on the soft edge
   (not the OS grey box). */
html[data-ui="v2"] input[type="checkbox"]:not(.sr-only):is([class], :not([class])) {
  -webkit-appearance: none;
  appearance: none;
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  margin: 0;
  border: 1px solid var(--border-input);
  border-radius: 4px;
  background-color: var(--bg-card);
  display: inline-grid;
  place-content: center;
  vertical-align: middle;
  cursor: pointer;
}
html[data-ui="v2"] input[type="checkbox"]:not(.sr-only):is([class], :not([class])):checked,
html[data-ui="v2"] input[type="checkbox"]:not(.sr-only):is([class], :not([class])):indeterminate {
  background-color: var(--accent);
  border-color: var(--accent);
}
html[data-ui="v2"] input[type="checkbox"]:not(.sr-only):is([class], :not([class])):checked::before {
  content: "";
  width: 10px;
  height: 10px;
  background: var(--on-accent);
  clip-path: polygon(14% 44%, 0 62%, 40% 100%, 100% 22%, 84% 6%, 38% 66%);
}
html[data-ui="v2"] input[type="checkbox"]:not(.sr-only):is([class], :not([class])):indeterminate::before {
  content: "";
  width: 8px;
  height: 2px;
  background: var(--on-accent);
}
html[data-ui="v2"] input[type="checkbox"]:not(.sr-only):is([class], :not([class])):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
html[data-ui="v2"] input[type="checkbox"]:not(.sr-only):is([class], :not([class])):disabled {
  opacity: 0.5;
  cursor: default;
}
html[data-ui="v2"] select option,
html[data-ui="v2"].dark select option {
  background: var(--bg-inset);
  color: var(--text-primary);
}

/* ── Shared buttons and badges (theme.css component set) ──── */
html[data-ui="v2"] .btn {
  font-weight: 500;
}
html[data-ui="v2"] .btn:active {
  transform: none;
}
html[data-ui="v2"] .btn-primary,
html[data-ui="v2"] .btn-approve {
  background: var(--accent);
  color: var(--on-accent);
  border: 1px solid var(--accent);
  font-weight: 500;
}
html[data-ui="v2"] .btn-primary:hover,
html[data-ui="v2"] .btn-approve:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
  filter: none;
}
html[data-ui="v2"] .btn-secondary {
  background: transparent;
  color: var(--text-heading);
  border: 1px solid var(--border-button);
}
html[data-ui="v2"] .btn-secondary:hover,
html[data-ui="v2"] .btn-ghost:hover {
  background: var(--bg-hover);
  color: var(--text-heading);
  border-color: var(--border-input);
}
html[data-ui="v2"] .btn-danger {
  background: var(--danger-fill);
  color: var(--danger);
  border: 1px solid transparent;
}
html[data-ui="v2"] .btn-danger:hover {
  background: color-mix(in srgb, var(--danger) 18%, var(--danger-fill));
}
html[data-ui="v2"] .badge {
  font-weight: 500;
}

/* ── Floating surfaces ────────────────────────────────────── */
html[data-ui="v2"] .search-results,
html[data-ui="v2"].dark .search-results,
html[data-ui="v2"] .user-dropdown,
html[data-ui="v2"].dark .user-dropdown {
  background: var(--bg-inset);
  border: 1px solid var(--border-primary);
  border-radius: 8px;
  box-shadow: var(--shadow-float);
}
html[data-ui="v2"] .user-dropdown-item:hover,
html[data-ui="v2"] .hover-bg:hover {
  background: var(--bg-hover);
}

/* ── Tables ───────────────────────────────────────────────── */
html[data-ui="v2"] .table-striped tbody tr:nth-child(even),
html[data-ui="v2"].dark .table-striped tbody tr:nth-child(even) {
  background: var(--bg-inset);
}
html[data-ui="v2"] .row-hover-glow:hover,
html[data-ui="v2"].dark .row-hover-glow:hover {
  box-shadow: none;
  background: var(--bg-hover);
}

/* ── Shell: page, header ──────────────────────────────────── */
html[data-ui="v2"] .app-bg,
html[data-ui="v2"]:not(.dark) .app-bg {
  background: var(--bg-primary);
}
html[data-ui="v2"] .dot-grid,
html[data-ui="v2"]:not(.dark) .dot-grid {
  background-image: none;
}
html[data-ui="v2"] .inline-header,
html[data-ui="v2"].dark .inline-header {
  background: var(--bg-primary);
  border-bottom-color: var(--border-primary);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
/* Letter avatar: a quiet inset disc, not an accent blob with white text
   (white on the dark accent is 2.5:1). The headshot variant is unaffected
   under its image. !important: the colour is an inline style. */
html[data-ui="v2"] .inline-header button[aria-label="User menu"]:not([data-agent-avatar]) {
  background: var(--bg-inset) !important;
  border: 1px solid var(--border-primary);
  color: var(--text-heading);
  font-weight: 600;
}
html[data-ui="v2"] .theme-toggle {
  background: transparent;
  border-color: var(--border-button);
  border-radius: 6px;
  width: var(--ctl-h);
  height: var(--ctl-h);
}
html[data-ui="v2"] .theme-toggle svg {
  width: 16px;
  height: 16px;
}
html[data-ui="v2"] .theme-toggle:hover {
  background: var(--bg-hover);
  color: var(--text-heading);
  border-color: var(--border-input);
}

/* ── Shell: section tabs ──────────────────────────────────── */
/* Plain text tabs; the active one is primary text on a 2px accent
   underline. No fill, no pill, no border. */
html[data-ui="v2"] .sub-nav,
html[data-ui="v2"].dark .sub-nav {
  background: var(--bg-primary);
  border-bottom-color: var(--border-primary);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  align-items: stretch;
  gap: 20px;
  padding: 0 24px;
}
html[data-ui="v2"] .sub-nav-pill {
  padding: 0 2px;
  border: 0;
  border-radius: 0;
  font-size: var(--fs-ui);
  font-weight: 400;
  color: var(--text-muted);
  background: transparent;
}
html[data-ui="v2"] .sub-nav-pill:hover,
html[data-ui="v2"].dark .sub-nav-pill:hover {
  color: var(--text-heading);
  background: transparent;
}
html[data-ui="v2"] .sub-nav-pill.active,
html[data-ui="v2"].dark .sub-nav-pill.active {
  color: var(--text-heading);
  background: transparent;
  border: 0;
  box-shadow: inset 0 -2px 0 var(--accent);
  font-weight: 500;
}

/* ── Shell: rail ──────────────────────────────────────────── */
html[data-ui="v2"] .dock nav {
  scrollbar-color: var(--border-strong) transparent;
}
html[data-ui="v2"] .dock nav::-webkit-scrollbar-thumb {
  background: var(--border-strong);
}
html[data-ui="v2"] .dock-item {
  border-radius: 6px;
  border-left-color: transparent;
  color: var(--text-muted);
}
html[data-ui="v2"] .dock-item:hover,
html[data-ui="v2"].dark .dock-item:hover {
  color: var(--text-heading);
  background: var(--bg-hover);
}
/* Active item: the accent icon on the soft fill, no left bar. */
html[data-ui="v2"] .dock-item.active,
html[data-ui="v2"] .dock-item.active:hover,
html[data-ui="v2"].dark .dock-item.active,
html[data-ui="v2"].dark .dock-item.active:hover {
  color: var(--accent);
  background: var(--accent-soft);
  border-left-color: transparent;
}
html[data-ui="v2"] .dock-divider {
  background: var(--border-primary);
}
html[data-ui="v2"] .dock-badge {
  background: var(--accent);
}
html[data-ui="v2"] .dock-badge-error {
  background: var(--danger);
  color: var(--on-accent);
  font-weight: 600;
  animation: none;
}
html[data-ui="v2"] .dock-tooltip {
  font-weight: 500;
}

/* ── Shell: ticker (admins only under v2; see base.html) ──── */
html[data-ui="v2"] .ticker,
html[data-ui="v2"].dark .ticker {
  background: var(--bg-primary);
  border-bottom-color: var(--border-primary);
  font-family: inherit;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
html[data-ui="v2"] .ticker-item {
  border-right-color: var(--border-primary);
}
html[data-ui="v2"] .ticker-label {
  font-size: var(--fs-micro);
  font-weight: 500;
  text-transform: none;
  letter-spacing: var(--tr-micro);
  color: var(--text-muted);
}
html[data-ui="v2"] .ticker-value {
  font-weight: 600;
  color: var(--text-heading);
}
html[data-ui="v2"] .ticker-up    { color: var(--success); }
html[data-ui="v2"] .ticker-down  { color: var(--danger); }
html[data-ui="v2"] .ticker-alert {
  color: var(--warning);
  animation: none;
}
html[data-ui="v2"] .ticker-sep {
  background: var(--border-primary);
}

/* ── Motion: nothing moves while idle ─────────────────────── */
html[data-ui="v2"] .page-content,
html[data-ui="v2"] .card-enter,
html[data-ui="v2"] .chart-animated,
html[data-ui="v2"] .stat-animated,
html[data-ui="v2"] .animate-pulse {
  animation: none;
}
html[data-ui="v2"] .animate-ping {
  animation: none;
  opacity: 0;
}

/* ── Decorations ──────────────────────────────────────────── */
/* Corner glows: gone. */
html[data-ui="v2"] .rounded-bl-full.bg-gradient-to-bl {
  display: none;
}
/* Gradient bars and fills: flat. */
html[data-ui="v2"] .bg-gradient-to-r,
html[data-ui="v2"] .bg-gradient-to-l {
  background-image: none;
  background-color: var(--accent);
}
html[data-ui="v2"] .absolute.inset-0.bg-gradient-to-r {
  opacity: 0.35;
}
html[data-ui="v2"] .bg-gradient-to-br,
html[data-ui="v2"] .bg-gradient-to-b,
html[data-ui="v2"] .bg-gradient-to-t {
  background-image: none;
  background-color: var(--bg-hover);
}
/* Gradient headline text: plain heading text. */
html[data-ui="v2"] .bg-clip-text.text-transparent {
  background-image: none;
  background-color: transparent;
  color: var(--text-heading);
}
html[data-ui="v2"] .backdrop-blur,
html[data-ui="v2"] .backdrop-blur-sm,
html[data-ui="v2"] .backdrop-blur-md,
html[data-ui="v2"] .backdrop-blur-lg,
html[data-ui="v2"] .backdrop-blur-xl {
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
html[data-ui="v2"] .glow-purple,
html[data-ui="v2"] .glow-blue,
html[data-ui="v2"] .glow-slate {
  box-shadow: none;
}

/* ── Launcher (launcher.html, body.v2-launcher) ───────────── */
/* Same tokens as the dashboards: a plain page, the brand in the middle and
   one flat tile per agent. The star field, trail and connector lines are
   hidden (and their animation loops are not started under v2). */
html[data-ui="v2"] body.v2-launcher {
  background: var(--bg-primary);
  color: var(--text-heading);
  font-family: var(--font-sans);
  font-feature-settings: var(--font-features);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
html[data-ui="v2"] .v2-launcher #star-canvas,
html[data-ui="v2"] .v2-launcher #trail-canvas,
html[data-ui="v2"] .v2-launcher #svg-layer {
  display: none;
}
html[data-ui="v2"] .v2-launcher .brand,
html[data-ui="v2"] .v2-launcher .brand .subtitle {
  animation: none;
  opacity: 1;
  transform: none;
}
html[data-ui="v2"] .v2-launcher .brand-fallback {
  background: var(--bg-inset);
  border: 1px solid var(--border-primary);
  border-radius: 8px;
  color: var(--text-heading);
  font-weight: 600;
  filter: none;
}
html[data-ui="v2"] .v2-launcher .brand .subtitle {
  font-size: var(--fs-ui);
  line-height: var(--lh-ui);
  font-weight: 400;
  letter-spacing: var(--tr-ui);
  text-transform: none;
  color: var(--text-muted);
}
/* Tiles. Each tile carries its own inline --accent (a per-agent hue), so
   nothing here reads var(--accent) inside a tile. !important on transform
   and box-shadow: the page's own :hover rule uses !important, and its click
   handler writes both inline. */
html[data-ui="v2"] .v2-launcher .node,
html[data-ui="v2"] .v2-launcher .node.primary,
html[data-ui="v2"] .v2-launcher .node.solo {
  border: 1px solid var(--border-primary);
  border-radius: 8px;
  background: var(--bg-card);
  background-clip: padding-box;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  color: var(--text-heading);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-weight: 500;
  letter-spacing: var(--tr-body);
  opacity: 1;
  animation: none;
  transform: none !important;
  box-shadow: none !important;
  transition: border-color 0.15s, opacity 0.35s;
}
html[data-ui="v2"] .v2-launcher .node.solo {
  font-size: var(--fs-section);
  line-height: var(--lh-section);
  letter-spacing: var(--tr-section);
}
html[data-ui="v2"] .v2-launcher .node:hover,
html[data-ui="v2"] .v2-launcher .node.primary:hover {
  border-color: var(--border-strong);
  background: var(--bg-hover);
}
html[data-ui="v2"] .v2-launcher .node .icon {
  background: var(--text-muted);
  box-shadow: none;
}
html[data-ui="v2"] .v2-launcher .node .avatar {
  border: 1px solid var(--border-primary);
  box-shadow: none;
}
html[data-ui="v2"] .v2-launcher .live-badge {
  display: inline-flex;
  align-items: center;
  height: var(--chip-h);
  color: var(--success);
  font-size: var(--fs-meta);
  line-height: var(--lh-meta);
  font-weight: 500;
  letter-spacing: var(--tr-meta);
  text-transform: none;
}
html[data-ui="v2"] .v2-launcher .live-dot {
  background: var(--success);
  box-shadow: none;
  animation: none;
}
html[data-ui="v2"] .v2-launcher .transition-overlay {
  background: var(--bg-primary);
}

/* ── Utility remap ────────────────────────────────────────── */
/* Generated from the colour utilities the templates use that the purged
   Tailwind build defines (census of app/templates, 2026-09-19). A class
   added to a template later is not covered until this list is refreshed.
   - translucent white fills -> inset (<= 8%) or hover (>= 10%); borders ->
     one border colour; theme-prefixed so they outrank theme.css's light
     layer, and every :hover / group-hover variant has its own rule so hover
     still wins over the static remap
   - decorative hues (sky, blue, cyan, violet, indigo, teal, purple, pink,
     lime): solid fills -> the accent, tinted fills -> inset (blue, indigo
     and violet at >= 20% -> the soft accent, the selected-state fill), text
     -> secondary (accent inside links and buttons), faint borders -> the
     border colour, strong and focus borders -> the accent
   - state hues keep their meaning: red / rose -> danger, emerald / green ->
     success, amber / orange / yellow -> warning; solid green action fills
     (600 / 700) -> the accent, since the one solid button is the accent
   - dark-only neutral surfaces (slate / gray 700-900) -> card / hover /
     inset tokens, so they also read in light mode */
/* Translucent white fills -> the inset surface */
html[data-ui="v2"].dark .bg-white\/3,
html[data-ui="v2"]:not(.dark) .bg-white\/3,
html[data-ui="v2"].dark .bg-white\/5,
html[data-ui="v2"]:not(.dark) .bg-white\/5,
html[data-ui="v2"].dark .bg-white\/\[0\.02\],
html[data-ui="v2"]:not(.dark) .bg-white\/\[0\.02\],
html[data-ui="v2"].dark .bg-white\/\[0\.03\],
html[data-ui="v2"]:not(.dark) .bg-white\/\[0\.03\],
html[data-ui="v2"].dark .bg-white\/\[0\.04\],
html[data-ui="v2"]:not(.dark) .bg-white\/\[0\.04\] {
  background-color: var(--bg-inset);
}
/* Stronger translucent white fills -> the hover surface */
html[data-ui="v2"].dark .bg-white\/10,
html[data-ui="v2"]:not(.dark) .bg-white\/10 {
  background-color: var(--bg-hover);
}
/* Their hover / focus variants (outrank the static fills above) */
html[data-ui="v2"].dark .focus\:bg-white\/5:focus,
html[data-ui="v2"]:not(.dark) .focus\:bg-white\/5:focus,
html[data-ui="v2"].dark .hover\:bg-white\/10:hover,
html[data-ui="v2"]:not(.dark) .hover\:bg-white\/10:hover,
html[data-ui="v2"].dark .hover\:bg-white\/15:hover,
html[data-ui="v2"]:not(.dark) .hover\:bg-white\/15:hover,
html[data-ui="v2"].dark .hover\:bg-white\/3:hover,
html[data-ui="v2"]:not(.dark) .hover\:bg-white\/3:hover,
html[data-ui="v2"].dark .hover\:bg-white\/5:hover,
html[data-ui="v2"]:not(.dark) .hover\:bg-white\/5:hover,
html[data-ui="v2"].dark .hover\:bg-white\/\[0\.02\]:hover,
html[data-ui="v2"]:not(.dark) .hover\:bg-white\/\[0\.02\]:hover,
html[data-ui="v2"].dark .hover\:bg-white\/\[0\.03\]:hover,
html[data-ui="v2"]:not(.dark) .hover\:bg-white\/\[0\.03\]:hover,
html[data-ui="v2"].dark .hover\:bg-white\/\[0\.04\]:hover,
html[data-ui="v2"]:not(.dark) .hover\:bg-white\/\[0\.04\]:hover,
html[data-ui="v2"].dark .hover\:bg-white\/\[0\.06\]:hover,
html[data-ui="v2"]:not(.dark) .hover\:bg-white\/\[0\.06\]:hover,
html[data-ui="v2"].dark .hover\:bg-white\/\[0\.08\]:hover,
html[data-ui="v2"]:not(.dark) .hover\:bg-white\/\[0\.08\]:hover {
  background-color: var(--bg-hover);
}
/* Fills paint inside their own border, never under it (the bright rim) */
html[data-ui="v2"] .bg-white\/10,
html[data-ui="v2"] .bg-white\/3,
html[data-ui="v2"] .bg-white\/5,
html[data-ui="v2"] .bg-white\/\[0\.02\],
html[data-ui="v2"] .bg-white\/\[0\.03\],
html[data-ui="v2"] .bg-white\/\[0\.04\] {
  background-clip: padding-box;
}
/* Translucent white borders -> one border colour */
html[data-ui="v2"].dark .border-white\/10,
html[data-ui="v2"]:not(.dark) .border-white\/10,
html[data-ui="v2"].dark .border-white\/20,
html[data-ui="v2"]:not(.dark) .border-white\/20,
html[data-ui="v2"].dark .border-white\/5,
html[data-ui="v2"]:not(.dark) .border-white\/5,
html[data-ui="v2"].dark .border-white\/\[0\.03\],
html[data-ui="v2"]:not(.dark) .border-white\/\[0\.03\] {
  border-color: var(--border-primary);
}
/* Translucent white dividers */
html[data-ui="v2"].dark .divide-white\/5 > :not([hidden]) ~ :not([hidden]),
html[data-ui="v2"]:not(.dark) .divide-white\/5 > :not([hidden]) ~ :not([hidden]) {
  border-color: var(--border-primary);
}
/* Hover borders on clickable boxes */
html[data-ui="v2"].dark .hover\:border-white\/10:hover,
html[data-ui="v2"]:not(.dark) .hover\:border-white\/10:hover,
html[data-ui="v2"].dark .hover\:border-white\/20:hover,
html[data-ui="v2"]:not(.dark) .hover\:border-white\/20:hover {
  border-color: var(--border-strong);
}
/* Dark-only solid surfaces (modals, sticky bars) -> the card surface */
html[data-ui="v2"] .bg-gray-800,
html[data-ui="v2"] .bg-gray-900,
html[data-ui="v2"] .bg-slate-800 {
  background-color: var(--bg-card);
}
/* Dark-only raised fills -> the hover surface */
html[data-ui="v2"] .bg-gray-700,
html[data-ui="v2"] .bg-slate-700 {
  background-color: var(--bg-hover);
}
html[data-ui="v2"] .group:hover .group-hover\:bg-slate-500\/20,
html[data-ui="v2"] .hover\:bg-gray-500\/20:hover,
html[data-ui="v2"] .hover\:bg-slate-500\/20:hover,
html[data-ui="v2"] .hover\:bg-slate-500\/30:hover,
html[data-ui="v2"] .hover\:bg-slate-700:hover {
  background-color: var(--bg-hover);
}
/* Neutral and decorative tinted fills -> the inset surface */
html[data-ui="v2"] .bg-blue-500\/10,
html[data-ui="v2"] .bg-blue-500\/15,
html[data-ui="v2"] .bg-blue-500\/5,
html[data-ui="v2"] .bg-blue-500\/\[0\.06\],
html[data-ui="v2"] .bg-cyan-500\/10,
html[data-ui="v2"] .bg-cyan-500\/15,
html[data-ui="v2"] .bg-cyan-500\/20,
html[data-ui="v2"] .bg-cyan-500\/30,
html[data-ui="v2"] .bg-cyan-500\/5,
html[data-ui="v2"] .bg-gray-500\/10,
html[data-ui="v2"] .bg-gray-500\/15,
html[data-ui="v2"] .bg-gray-500\/20,
html[data-ui="v2"] .bg-gray-500\/30,
html[data-ui="v2"] .bg-gray-500\/5,
html[data-ui="v2"] .bg-gray-700\/50,
html[data-ui="v2"] .bg-gray-700\/60,
html[data-ui="v2"] .bg-gray-800\/50,
html[data-ui="v2"] .bg-gray-800\/60,
html[data-ui="v2"] .bg-gray-900\/40,
html[data-ui="v2"] .bg-lime-500\/15,
html[data-ui="v2"] .bg-pink-500\/10,
html[data-ui="v2"] .bg-pink-500\/15,
html[data-ui="v2"] .bg-sky-500\/10,
html[data-ui="v2"] .bg-sky-500\/15,
html[data-ui="v2"] .bg-sky-500\/20,
html[data-ui="v2"] .bg-slate-500\/10,
html[data-ui="v2"] .bg-slate-500\/15,
html[data-ui="v2"] .bg-slate-500\/20,
html[data-ui="v2"] .bg-slate-500\/30,
html[data-ui="v2"] .bg-slate-500\/40,
html[data-ui="v2"] .bg-slate-500\/5,
html[data-ui="v2"] .bg-slate-500\/60,
html[data-ui="v2"] .bg-slate-700\/30,
html[data-ui="v2"] .bg-slate-700\/50,
html[data-ui="v2"] .bg-slate-800\/30,
html[data-ui="v2"] .bg-slate-800\/40,
html[data-ui="v2"] .bg-slate-800\/50,
html[data-ui="v2"] .bg-teal-500\/10,
html[data-ui="v2"] .bg-teal-500\/15,
html[data-ui="v2"] .bg-teal-500\/20,
html[data-ui="v2"] .bg-violet-500\/15 {
  background-color: var(--bg-inset);
}
/* Control edges */
html[data-ui="v2"] .border-slate-600 {
  border-color: var(--border-input);
}
/* Neutral and faint decorative borders -> one border colour */
html[data-ui="v2"] .border-blue-500\/10,
html[data-ui="v2"] .border-blue-500\/15,
html[data-ui="v2"] .border-blue-500\/20,
html[data-ui="v2"] .border-blue-500\/30,
html[data-ui="v2"] .border-cyan-500\/10,
html[data-ui="v2"] .border-cyan-500\/20,
html[data-ui="v2"] .border-cyan-500\/30,
html[data-ui="v2"] .border-gray-500\/10,
html[data-ui="v2"] .border-gray-500\/15,
html[data-ui="v2"] .border-gray-500\/20,
html[data-ui="v2"] .border-gray-500\/30,
html[data-ui="v2"] .border-gray-700,
html[data-ui="v2"] .border-gray-700\/50,
html[data-ui="v2"] .border-gray-800,
html[data-ui="v2"] .border-lime-500\/20,
html[data-ui="v2"] .border-pink-500\/20,
html[data-ui="v2"] .border-sky-500\/20,
html[data-ui="v2"] .border-slate-500\/10,
html[data-ui="v2"] .border-slate-500\/15,
html[data-ui="v2"] .border-slate-500\/20,
html[data-ui="v2"] .border-slate-500\/30,
html[data-ui="v2"] .border-slate-700,
html[data-ui="v2"] .border-slate-700\/30,
html[data-ui="v2"] .border-slate-700\/50,
html[data-ui="v2"] .border-teal-500\/20,
html[data-ui="v2"] .border-teal-500\/30,
html[data-ui="v2"] .border-violet-500\/20 {
  border-color: var(--border-primary);
}
html[data-ui="v2"] .hover\:border-blue-500\/30:hover,
html[data-ui="v2"] .hover\:border-gray-500\/30:hover,
html[data-ui="v2"] .hover\:border-slate-500\/30:hover {
  border-color: var(--border-strong);
}
/* Selected-state fills -> the soft accent */
html[data-ui="v2"] .bg-blue-100,
html[data-ui="v2"] .bg-blue-500\/20,
html[data-ui="v2"] .bg-blue-500\/30,
html[data-ui="v2"] .bg-blue-500\/40,
html[data-ui="v2"] .bg-blue-600\/20,
html[data-ui="v2"] .peer:checked ~ .peer-checked\:bg-blue-500\/25 {
  background-color: var(--accent-soft);
}
/* State fills */
html[data-ui="v2"] .bg-red-500\/10,
html[data-ui="v2"] .bg-red-500\/15,
html[data-ui="v2"] .bg-red-500\/20,
html[data-ui="v2"] .bg-red-500\/90,
html[data-ui="v2"] .bg-red-700\/50,
html[data-ui="v2"] .bg-rose-500\/10,
html[data-ui="v2"] .bg-rose-500\/15 {
  background-color: var(--danger-fill);
}
html[data-ui="v2"] .bg-emerald-500\/10,
html[data-ui="v2"] .bg-emerald-500\/15,
html[data-ui="v2"] .bg-emerald-500\/20,
html[data-ui="v2"] .bg-emerald-500\/30,
html[data-ui="v2"] .bg-emerald-500\/5,
html[data-ui="v2"] .bg-emerald-500\/60,
html[data-ui="v2"] .bg-emerald-500\/90,
html[data-ui="v2"] .bg-emerald-500\/\[0\.04\],
html[data-ui="v2"] .bg-green-500\/10,
html[data-ui="v2"] .bg-green-500\/15,
html[data-ui="v2"] .bg-green-500\/20,
html[data-ui="v2"] .bg-green-500\/30,
html[data-ui="v2"] .bg-green-500\/40,
html[data-ui="v2"] .bg-green-500\/5,
html[data-ui="v2"] .bg-green-500\/\[0\.06\],
html[data-ui="v2"] .bg-green-600\/60,
html[data-ui="v2"] .bg-green-600\/80,
html[data-ui="v2"] .bg-green-600\/90,
html[data-ui="v2"] .bg-green-700\/40,
html[data-ui="v2"] .bg-green-700\/50,
html[data-ui="v2"] .bg-green-900\/30 {
  background-color: var(--success-fill);
}
html[data-ui="v2"] .bg-amber-500\/10,
html[data-ui="v2"] .bg-amber-500\/15,
html[data-ui="v2"] .bg-amber-500\/20,
html[data-ui="v2"] .bg-amber-500\/30,
html[data-ui="v2"] .bg-amber-500\/5,
html[data-ui="v2"] .bg-amber-500\/60,
html[data-ui="v2"] .bg-amber-500\/\[0\.04\],
html[data-ui="v2"] .bg-orange-500\/10,
html[data-ui="v2"] .bg-orange-500\/15,
html[data-ui="v2"] .bg-orange-500\/20,
html[data-ui="v2"] .bg-orange-500\/5,
html[data-ui="v2"] .bg-yellow-500\/10,
html[data-ui="v2"] .bg-yellow-500\/15,
html[data-ui="v2"] .bg-yellow-500\/20,
html[data-ui="v2"] .bg-yellow-700\/50,
html[data-ui="v2"] .bg-yellow-900\/30 {
  background-color: var(--warning-fill);
}
/* Hover on state fills: a step stronger than the fill */
html[data-ui="v2"] .hover\:bg-red-500\/10:hover,
html[data-ui="v2"] .hover\:bg-red-500\/20:hover,
html[data-ui="v2"] .hover\:bg-red-500\/30:hover {
  background-color: color-mix(in srgb, var(--danger) 18%, var(--danger-fill));
}
html[data-ui="v2"] .group:hover .group-hover\:bg-emerald-500\/20,
html[data-ui="v2"] .hover\:bg-emerald-500\/20:hover,
html[data-ui="v2"] .hover\:bg-green-500\/20:hover,
html[data-ui="v2"] .hover\:bg-green-500\/30:hover {
  background-color: color-mix(in srgb, var(--success) 18%, var(--success-fill));
}
html[data-ui="v2"] .group:hover .group-hover\:bg-amber-500\/20,
html[data-ui="v2"] .hover\:bg-amber-500\/10:hover,
html[data-ui="v2"] .hover\:bg-amber-500\/20:hover,
html[data-ui="v2"] .hover\:bg-amber-500\/25:hover,
html[data-ui="v2"] .hover\:bg-orange-500\/20:hover {
  background-color: color-mix(in srgb, var(--warning) 18%, var(--warning-fill));
}
/* State dots and bars */
html[data-ui="v2"] .bg-red-400,
html[data-ui="v2"] .bg-red-500 {
  background-color: var(--danger);
}
html[data-ui="v2"] .bg-emerald-400,
html[data-ui="v2"] .bg-emerald-500,
html[data-ui="v2"] .bg-green-400,
html[data-ui="v2"] .bg-green-500 {
  background-color: var(--success);
}
html[data-ui="v2"] .bg-amber-400,
html[data-ui="v2"] .bg-amber-500,
html[data-ui="v2"] .bg-orange-400,
html[data-ui="v2"] .bg-yellow-500 {
  background-color: var(--warning);
}
/* Solid decorative / action fills -> the one accent */
html[data-ui="v2"] .bg-blue-400,
html[data-ui="v2"] .bg-blue-500,
html[data-ui="v2"] .bg-blue-500\/60,
html[data-ui="v2"] .bg-blue-600,
html[data-ui="v2"] .bg-cyan-400,
html[data-ui="v2"] .bg-emerald-600,
html[data-ui="v2"] .bg-green-600,
html[data-ui="v2"] .bg-lime-400,
html[data-ui="v2"] .bg-pink-400,
html[data-ui="v2"] .bg-sky-400,
html[data-ui="v2"] .bg-sky-500\/60,
html[data-ui="v2"] .bg-teal-400,
html[data-ui="v2"] .bg-teal-600 {
  background-color: var(--accent);
}
/* Text on the accent fill (theme-prefixed: outranks the text-white remaps) */
html[data-ui="v2"].dark .bg-blue-400,
html[data-ui="v2"].dark .bg-blue-400 .text-white,
html[data-ui="v2"]:not(.dark) .bg-blue-400,
html[data-ui="v2"]:not(.dark) .bg-blue-400 .text-white,
html[data-ui="v2"].dark .bg-blue-500,
html[data-ui="v2"].dark .bg-blue-500 .text-white,
html[data-ui="v2"]:not(.dark) .bg-blue-500,
html[data-ui="v2"]:not(.dark) .bg-blue-500 .text-white,
html[data-ui="v2"].dark .bg-blue-500\/60,
html[data-ui="v2"].dark .bg-blue-500\/60 .text-white,
html[data-ui="v2"]:not(.dark) .bg-blue-500\/60,
html[data-ui="v2"]:not(.dark) .bg-blue-500\/60 .text-white,
html[data-ui="v2"].dark .bg-blue-600,
html[data-ui="v2"].dark .bg-blue-600 .text-white,
html[data-ui="v2"]:not(.dark) .bg-blue-600,
html[data-ui="v2"]:not(.dark) .bg-blue-600 .text-white,
html[data-ui="v2"].dark .bg-cyan-400,
html[data-ui="v2"].dark .bg-cyan-400 .text-white,
html[data-ui="v2"]:not(.dark) .bg-cyan-400,
html[data-ui="v2"]:not(.dark) .bg-cyan-400 .text-white,
html[data-ui="v2"].dark .bg-emerald-600,
html[data-ui="v2"].dark .bg-emerald-600 .text-white,
html[data-ui="v2"]:not(.dark) .bg-emerald-600,
html[data-ui="v2"]:not(.dark) .bg-emerald-600 .text-white,
html[data-ui="v2"].dark .bg-green-600,
html[data-ui="v2"].dark .bg-green-600 .text-white,
html[data-ui="v2"]:not(.dark) .bg-green-600,
html[data-ui="v2"]:not(.dark) .bg-green-600 .text-white,
html[data-ui="v2"].dark .bg-lime-400,
html[data-ui="v2"].dark .bg-lime-400 .text-white,
html[data-ui="v2"]:not(.dark) .bg-lime-400,
html[data-ui="v2"]:not(.dark) .bg-lime-400 .text-white,
html[data-ui="v2"].dark .bg-pink-400,
html[data-ui="v2"].dark .bg-pink-400 .text-white,
html[data-ui="v2"]:not(.dark) .bg-pink-400,
html[data-ui="v2"]:not(.dark) .bg-pink-400 .text-white,
html[data-ui="v2"].dark .bg-sky-400,
html[data-ui="v2"].dark .bg-sky-400 .text-white,
html[data-ui="v2"]:not(.dark) .bg-sky-400,
html[data-ui="v2"]:not(.dark) .bg-sky-400 .text-white,
html[data-ui="v2"].dark .bg-sky-500\/60,
html[data-ui="v2"].dark .bg-sky-500\/60 .text-white,
html[data-ui="v2"]:not(.dark) .bg-sky-500\/60,
html[data-ui="v2"]:not(.dark) .bg-sky-500\/60 .text-white,
html[data-ui="v2"].dark .bg-teal-400,
html[data-ui="v2"].dark .bg-teal-400 .text-white,
html[data-ui="v2"]:not(.dark) .bg-teal-400,
html[data-ui="v2"]:not(.dark) .bg-teal-400 .text-white,
html[data-ui="v2"].dark .bg-teal-600,
html[data-ui="v2"].dark .bg-teal-600 .text-white,
html[data-ui="v2"]:not(.dark) .bg-teal-600,
html[data-ui="v2"]:not(.dark) .bg-teal-600 .text-white {
  color: var(--on-accent);
}
/* Text on a status fill (danger, success, warning: the solid badges, count
   pills and dots above). The fills are deep in light and pale in dark, so
   --on-accent (white in light, near-black in dark) is the readable colour in
   both; on the element itself and on anything inside it. Same specificity as
   the text-white remaps and later in the file, so it wins. */
html[data-ui="v2"] :is(.bg-red-400, .bg-red-500, .bg-emerald-400, .bg-emerald-500, .bg-green-400, .bg-green-500, .bg-amber-400, .bg-amber-500, .bg-orange-400, .bg-yellow-500).text-white,
html[data-ui="v2"] :is(.bg-red-400, .bg-red-500, .bg-emerald-400, .bg-emerald-500, .bg-green-400, .bg-green-500, .bg-amber-400, .bg-amber-500, .bg-orange-400, .bg-yellow-500) .text-white {
  color: var(--on-accent);
}
html[data-ui="v2"] .hover\:bg-blue-500:hover,
html[data-ui="v2"] .hover\:bg-blue-700:hover,
html[data-ui="v2"] .hover\:bg-emerald-500:hover,
html[data-ui="v2"] .hover\:bg-emerald-700:hover,
html[data-ui="v2"] .hover\:bg-green-600:hover,
html[data-ui="v2"] .hover\:bg-green-700:hover,
html[data-ui="v2"] .hover\:bg-teal-500:hover {
  background-color: var(--accent-hover);
}
/* Tinted hover fills -> the hover surface */
html[data-ui="v2"] .group:hover .group-hover\:bg-blue-500\/20,
html[data-ui="v2"] .hover\:bg-blue-500\/20:hover,
html[data-ui="v2"] .hover\:bg-blue-600\/30:hover,
html[data-ui="v2"] .hover\:bg-cyan-500\/20:hover,
html[data-ui="v2"] .hover\:bg-pink-500\/20:hover,
html[data-ui="v2"] .hover\:bg-teal-500\/30:hover {
  background-color: var(--bg-hover);
}
/* Decorative text hues -> secondary text */
html[data-ui="v2"] .text-blue-100,
html[data-ui="v2"] .text-blue-300,
html[data-ui="v2"] .text-blue-400,
html[data-ui="v2"] .text-blue-500,
html[data-ui="v2"] .text-blue-500\/70,
html[data-ui="v2"] .text-blue-600,
html[data-ui="v2"] .text-blue-700,
html[data-ui="v2"] .text-cyan-300,
html[data-ui="v2"] .text-cyan-300\/60,
html[data-ui="v2"] .text-cyan-400,
html[data-ui="v2"] .text-cyan-400\/60,
html[data-ui="v2"] .text-cyan-500,
html[data-ui="v2"] .text-cyan-600,
html[data-ui="v2"] .text-indigo-400,
html[data-ui="v2"] .text-lime-400,
html[data-ui="v2"] .text-pink-400,
html[data-ui="v2"] .text-sky-300,
html[data-ui="v2"] .text-sky-400,
html[data-ui="v2"] .text-sky-400\/60,
html[data-ui="v2"] .text-teal-300,
html[data-ui="v2"] .text-teal-400,
html[data-ui="v2"] .text-violet-400 {
  color: var(--text-secondary);
}
/* State text */
html[data-ui="v2"] .text-red-300,
html[data-ui="v2"] .text-red-400,
html[data-ui="v2"] .text-red-400\/50,
html[data-ui="v2"] .text-red-400\/60,
html[data-ui="v2"] .text-red-400\/70,
html[data-ui="v2"] .text-red-400\/80,
html[data-ui="v2"] .text-red-500,
html[data-ui="v2"] .text-red-700,
html[data-ui="v2"] .text-rose-400 {
  color: var(--danger);
}
html[data-ui="v2"] .text-emerald-300,
html[data-ui="v2"] .text-emerald-400,
html[data-ui="v2"] .text-emerald-400\/50,
html[data-ui="v2"] .text-emerald-400\/70,
html[data-ui="v2"] .text-emerald-400\/80,
html[data-ui="v2"] .text-emerald-500,
html[data-ui="v2"] .text-green-200,
html[data-ui="v2"] .text-green-300,
html[data-ui="v2"] .text-green-400,
html[data-ui="v2"] .text-green-400\/70,
html[data-ui="v2"] .text-green-500,
html[data-ui="v2"] .text-green-500\/70,
html[data-ui="v2"] .text-green-600,
html[data-ui="v2"] .text-green-700 {
  color: var(--success);
}
html[data-ui="v2"] .text-amber-300,
html[data-ui="v2"] .text-amber-300\/80,
html[data-ui="v2"] .text-amber-400,
html[data-ui="v2"] .text-amber-400\/50,
html[data-ui="v2"] .text-amber-400\/70,
html[data-ui="v2"] .text-amber-500,
html[data-ui="v2"] .text-amber-500\/70,
html[data-ui="v2"] .text-orange-300,
html[data-ui="v2"] .text-orange-400,
html[data-ui="v2"] .text-orange-400\/70,
html[data-ui="v2"] .text-yellow-300,
html[data-ui="v2"] .text-yellow-400,
html[data-ui="v2"] .text-yellow-400\/50,
html[data-ui="v2"] .text-yellow-500\/70 {
  color: var(--warning);
}
/* ... except inside links and buttons, where they are the accent */
html[data-ui="v2"] a.text-blue-100,
html[data-ui="v2"] button.text-blue-100,
html[data-ui="v2"] a .text-blue-100,
html[data-ui="v2"] button .text-blue-100,
html[data-ui="v2"] a.text-blue-300,
html[data-ui="v2"] button.text-blue-300,
html[data-ui="v2"] a .text-blue-300,
html[data-ui="v2"] button .text-blue-300,
html[data-ui="v2"] a.text-blue-400,
html[data-ui="v2"] button.text-blue-400,
html[data-ui="v2"] a .text-blue-400,
html[data-ui="v2"] button .text-blue-400,
html[data-ui="v2"] a.text-blue-500,
html[data-ui="v2"] button.text-blue-500,
html[data-ui="v2"] a .text-blue-500,
html[data-ui="v2"] button .text-blue-500,
html[data-ui="v2"] a.text-blue-500\/70,
html[data-ui="v2"] button.text-blue-500\/70,
html[data-ui="v2"] a .text-blue-500\/70,
html[data-ui="v2"] button .text-blue-500\/70,
html[data-ui="v2"] a.text-blue-600,
html[data-ui="v2"] button.text-blue-600,
html[data-ui="v2"] a .text-blue-600,
html[data-ui="v2"] button .text-blue-600,
html[data-ui="v2"] a.text-blue-700,
html[data-ui="v2"] button.text-blue-700,
html[data-ui="v2"] a .text-blue-700,
html[data-ui="v2"] button .text-blue-700,
html[data-ui="v2"] a.text-cyan-300,
html[data-ui="v2"] button.text-cyan-300,
html[data-ui="v2"] a .text-cyan-300,
html[data-ui="v2"] button .text-cyan-300,
html[data-ui="v2"] a.text-cyan-300\/60,
html[data-ui="v2"] button.text-cyan-300\/60,
html[data-ui="v2"] a .text-cyan-300\/60,
html[data-ui="v2"] button .text-cyan-300\/60,
html[data-ui="v2"] a.text-cyan-400,
html[data-ui="v2"] button.text-cyan-400,
html[data-ui="v2"] a .text-cyan-400,
html[data-ui="v2"] button .text-cyan-400,
html[data-ui="v2"] a.text-cyan-400\/60,
html[data-ui="v2"] button.text-cyan-400\/60,
html[data-ui="v2"] a .text-cyan-400\/60,
html[data-ui="v2"] button .text-cyan-400\/60,
html[data-ui="v2"] a.text-cyan-500,
html[data-ui="v2"] button.text-cyan-500,
html[data-ui="v2"] a .text-cyan-500,
html[data-ui="v2"] button .text-cyan-500,
html[data-ui="v2"] a.text-cyan-600,
html[data-ui="v2"] button.text-cyan-600,
html[data-ui="v2"] a .text-cyan-600,
html[data-ui="v2"] button .text-cyan-600,
html[data-ui="v2"] a.text-indigo-400,
html[data-ui="v2"] button.text-indigo-400,
html[data-ui="v2"] a .text-indigo-400,
html[data-ui="v2"] button .text-indigo-400,
html[data-ui="v2"] a.text-lime-400,
html[data-ui="v2"] button.text-lime-400,
html[data-ui="v2"] a .text-lime-400,
html[data-ui="v2"] button .text-lime-400,
html[data-ui="v2"] a.text-pink-400,
html[data-ui="v2"] button.text-pink-400,
html[data-ui="v2"] a .text-pink-400,
html[data-ui="v2"] button .text-pink-400,
html[data-ui="v2"] a.text-sky-300,
html[data-ui="v2"] button.text-sky-300,
html[data-ui="v2"] a .text-sky-300,
html[data-ui="v2"] button .text-sky-300,
html[data-ui="v2"] a.text-sky-400,
html[data-ui="v2"] button.text-sky-400,
html[data-ui="v2"] a .text-sky-400,
html[data-ui="v2"] button .text-sky-400,
html[data-ui="v2"] a.text-sky-400\/60,
html[data-ui="v2"] button.text-sky-400\/60,
html[data-ui="v2"] a .text-sky-400\/60,
html[data-ui="v2"] button .text-sky-400\/60,
html[data-ui="v2"] a.text-teal-300,
html[data-ui="v2"] button.text-teal-300,
html[data-ui="v2"] a .text-teal-300,
html[data-ui="v2"] button .text-teal-300,
html[data-ui="v2"] a.text-teal-400,
html[data-ui="v2"] button.text-teal-400,
html[data-ui="v2"] a .text-teal-400,
html[data-ui="v2"] button .text-teal-400,
html[data-ui="v2"] a.text-violet-400,
html[data-ui="v2"] button.text-violet-400,
html[data-ui="v2"] a .text-violet-400,
html[data-ui="v2"] button .text-violet-400 {
  color: var(--accent);
}
html[data-ui="v2"] .group:hover .group-hover\:text-blue-300,
html[data-ui="v2"] .hover\:text-blue-300:hover,
html[data-ui="v2"] .hover\:text-blue-400:hover,
html[data-ui="v2"] .hover\:text-cyan-400:hover,
html[data-ui="v2"] .hover\:text-indigo-300:hover,
html[data-ui="v2"] .hover\:text-sky-300:hover,
html[data-ui="v2"] .hover\:text-sky-400:hover,
html[data-ui="v2"] .hover\:text-teal-300:hover {
  color: var(--accent-hover);
}
/* Hover text utilities, restored above the static colour remaps */
html[data-ui="v2"] .group:hover .group-hover\:text-slate-200,
html[data-ui="v2"] .hover\:text-gray-200:hover,
html[data-ui="v2"] .hover\:text-gray-300:hover,
html[data-ui="v2"] .hover\:text-slate-300:hover,
html[data-ui="v2"] .hover\:text-white:hover {
  color: var(--text-heading);
}
html[data-ui="v2"] .group:hover .group-hover\:text-slate-400,
html[data-ui="v2"] .hover\:text-gray-400:hover {
  color: var(--text-secondary);
}
html[data-ui="v2"] .hover\:text-red-300:hover,
html[data-ui="v2"] .hover\:text-red-400:hover,
html[data-ui="v2"] .hover\:text-red-500:hover {
  color: var(--danger);
}
html[data-ui="v2"] .hover\:text-emerald-300:hover,
html[data-ui="v2"] .hover\:text-green-400:hover {
  color: var(--success);
}
html[data-ui="v2"] .hover\:text-amber-300:hover,
html[data-ui="v2"] .hover\:text-amber-400:hover,
html[data-ui="v2"] .hover\:text-yellow-400:hover {
  color: var(--warning);
}
html[data-ui="v2"] .peer:checked ~ .peer-checked\:text-blue-300 {
  color: var(--accent);
}
/* Strong decorative borders and focus borders -> the accent */
html[data-ui="v2"] .border-blue-500,
html[data-ui="v2"] .border-cyan-400,
html[data-ui="v2"] .border-cyan-500\/50,
html[data-ui="v2"] .focus\:border-blue-500:focus,
html[data-ui="v2"] .focus\:border-blue-500\/50:focus,
html[data-ui="v2"] .focus\:border-cyan-500:focus,
html[data-ui="v2"] .focus\:border-sky-500\/50:focus,
html[data-ui="v2"] .peer:checked ~ .peer-checked\:border-blue-400\/40 {
  border-color: var(--accent);
}
/* Decorative rings -> a soft accent ring */
html[data-ui="v2"] .focus\:ring-cyan-500\/30:focus,
html[data-ui="v2"] .focus\:ring-cyan-500\/50:focus {
  --tw-ring-color: var(--accent-ring);
}

/* ── Typography (docs/ui-v2-typography.md) ─────────────────── */
/* The templates' size utilities, collapsed onto the scale. Size and tracking
   here; line-height in the rules after, which step aside (:where, zero
   weight) when the element sets its own leading-*. A lane class on the same
   element still wins: the lane files load after this one. */
/* Nothing a reviewer reads is under 13px: 8-12px all land on 13. The micro
   token is the same 13px on a 16px line — the rail count badge and the caps
   chip, both single lines in a fixed box. */
html[data-ui="v2"] .text-\[8px\],
html[data-ui="v2"] .text-\[9px\],
html[data-ui="v2"] .text-\[10px\],
html[data-ui="v2"] .text-\[11px\],
html[data-ui="v2"] .text-\[12px\],
html[data-ui="v2"] .text-xs {
  font-size: var(--fs-meta);
  letter-spacing: var(--tr-meta);
}
html[data-ui="v2"] .text-\[13px\],
html[data-ui="v2"] .text-sm {
  font-size: var(--fs-ui);
  letter-spacing: var(--tr-ui);
}
html[data-ui="v2"] .text-\[15px\],
html[data-ui="v2"] .text-base {
  font-size: var(--fs-body);
  letter-spacing: var(--tr-body);
}
html[data-ui="v2"] .text-lg {
  font-size: var(--fs-section);
  letter-spacing: var(--tr-section);
}
html[data-ui="v2"] .text-xl {
  font-size: var(--fs-title);
  letter-spacing: var(--tr-title);
}
/* 28px is the largest size: KPI figures. Tabular so columns of them align. */
html[data-ui="v2"] .text-2xl,
html[data-ui="v2"] .text-3xl,
html[data-ui="v2"] .text-4xl {
  font-size: var(--fs-kpi);
  letter-spacing: var(--tr-kpi);
  font-variant-numeric: tabular-nums;
}
html[data-ui="v2"] :is(.text-\[8px\], .text-\[9px\], .text-\[10px\], .text-\[11px\], .text-\[12px\], .text-xs):where(:not([class*="leading-"])) {
  line-height: var(--lh-meta);
}
html[data-ui="v2"] :is(.text-\[13px\], .text-sm):where(:not([class*="leading-"])) {
  line-height: var(--lh-ui);
}
html[data-ui="v2"] :is(.text-\[15px\], .text-base):where(:not([class*="leading-"])) {
  line-height: var(--lh-body);
}
html[data-ui="v2"] .text-lg:where(:not([class*="leading-"])) {
  line-height: var(--lh-section);
}
html[data-ui="v2"] .text-xl:where(:not([class*="leading-"])) {
  line-height: var(--lh-title);
}
html[data-ui="v2"] :is(.text-2xl, .text-3xl, .text-4xl):where(:not([class*="leading-"])) {
  line-height: var(--lh-kpi);
}
/* Letter-spaced text: calm. Lowercase never needs positive tracking. These
   two stay at 0 rather than a role value: the class can sit on any size, and
   0 only cancels the utility's extra tracking. Every component that used to
   spell out `letter-spacing: 0` for the meta role now names --tr-meta, which
   is -0.003em since meta became 13px. */
html[data-ui="v2"] .tracking-wide,
html[data-ui="v2"] .tracking-wider,
html[data-ui="v2"] .tracking-widest {
  letter-spacing: 0;
}

/* Sentence case (brief rule 8): the stock pages set small labels, table
   heads and headings in capitals. Under v2 they read as written. */
html[data-ui="v2"] .uppercase {
  text-transform: none;
}
html[data-ui="v2"] .uppercase[class*="tracking-"] {
  text-transform: none;
  letter-spacing: 0;
}
/* One exception: a short padded chip that only sets "uppercase" (its text is
   often a lowercase code from the data) keeps its capitals, drawn as the
   one caps style: 13/16, 500, +0.04em, with Inter's case-sensitive forms. */
html[data-ui="v2"] span.uppercase[class*="px-"]:not([class*="tracking-"]) {
  text-transform: uppercase;
  font-size: var(--fs-micro);
  line-height: var(--lh-micro);
  font-weight: 500;
  letter-spacing: var(--tr-caps);
  font-feature-settings: var(--font-features), "case";
}

/* Headings in the page body. A heading that carries a size utility gets the
   role (the [class*] step outranks the remap above); one that carries only a
   lane class (.v2p-title, .an-h1, .an-lane-title) is left to its lane. */
html[data-ui="v2"] main h1,
html[data-ui="v2"] main h1[class*="text-"] {
  font-size: var(--fs-title);
  line-height: var(--lh-title);
  font-weight: 600;
  letter-spacing: var(--tr-title);
  color: var(--text-heading);
  text-wrap: balance;
}
html[data-ui="v2"] main :is(h2, h3),
html[data-ui="v2"] main :is(h2, h3)[class*="text-"] {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-weight: 600;
  letter-spacing: var(--tr-body);
  text-wrap: balance;
}
/* A heading the stock page letter-spaced and capitalised keeps its role's
   tracking once the caps are dropped (outranks the tracking reset above). */
html[data-ui="v2"] main :is(h2, h3)[class*="tracking-"][class*="text-"] {
  letter-spacing: var(--tr-body);
}
html[data-ui="v2"] main :is(h4, h5, h6),
html[data-ui="v2"] main :is(h4, h5, h6)[class*="text-"] {
  font-size: var(--fs-meta);
  line-height: var(--lh-meta);
  font-weight: 500;
  letter-spacing: var(--tr-meta);
}

/* Tables: one header style, tabular figures in every cell. */
html[data-ui="v2"] main th,
html[data-ui="v2"] main th[class] {
  font-size: var(--fs-meta);
  line-height: var(--lh-meta);
  font-weight: 500;
  letter-spacing: var(--tr-meta);
  text-transform: none;
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}
html[data-ui="v2"] :is(td, time, .badge, .ticker-value, .tnum, .tabular-nums) {
  font-variant-numeric: tabular-nums;
}

/* Controls: one text size (13px) and one height per size, 32px default and
   28px compact (a text-xs / py-1 / py-0.5 control), padding 0 12px, 8px
   between buttons in a group. Single-line inputs and selects drop their
   vertical padding so the height, not the padding, sets the box. */
html[data-ui="v2"] :is(input, select, textarea),
html[data-ui="v2"] :is(input, select, textarea)[class] {
  font-size: var(--fs-ui);
  letter-spacing: var(--tr-ui);
}
html[data-ui="v2"] :is(input, textarea)::placeholder {
  color: var(--text-muted);
  opacity: 1;
}
html[data-ui="v2"] :is(input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="hidden"], [type="color"]), select)[class] {
  height: var(--ctl-h);
  padding-top: 0;
  padding-bottom: 0;
  line-height: var(--lh-ui);
}
html[data-ui="v2"] :is(input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="hidden"], [type="color"]), select)[class]:is(.text-xs, .text-\[11px\], .text-\[10px\], .py-1, .py-0\.5) {
  height: var(--ctl-h-sm);
}
html[data-ui="v2"] textarea[class] {
  line-height: var(--lh-ui);
}
html[data-ui="v2"] .btn,
html[data-ui="v2"] button.text-base,
html[data-ui="v2"] a.text-base[class*="px-"] {
  font-size: var(--fs-ui);
  line-height: var(--lh-meta);
  letter-spacing: var(--tr-ui);
}
html[data-ui="v2"] .btn {
  height: var(--ctl-h);
  padding: 0 var(--ctl-px);
  gap: 6px;
  font-weight: var(--fw-medium);
}
html[data-ui="v2"] .btn:is(.text-xs, .py-1, .py-1\.5) {
  height: var(--ctl-h-sm);
}
/* A variant class used without .btn (intelligence: "btn-primary text-sm")
   gets the whole button box, not just the colours. */
html[data-ui="v2"] :is(.btn-primary, .btn-secondary, .btn-ghost, .btn-danger, .btn-approve):not(.btn) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: var(--ctl-h);
  padding: 0 var(--ctl-px);
  border-radius: 6px;
  font-size: var(--fs-ui);
  line-height: var(--lh-meta);
  font-weight: var(--fw-medium);
  letter-spacing: var(--tr-ui);
  white-space: nowrap;
  cursor: pointer;
}
/* Legacy Tailwind buttons (a padded, rounded <button>) take the same two
   heights. Buttons centre their content, so dropping the vertical padding is
   enough; full-width, left-aligned and stacked buttons are list rows, not
   controls, and keep their padding. */
html[data-ui="v2"] main button[class*="px-"][class*="rounded"]:is(.py-1\.5, .py-2, .py-2\.5):not(.w-full, .text-left, .flex-col, .block) {
  height: var(--ctl-h);
  padding-top: 0;
  padding-bottom: 0;
}
html[data-ui="v2"] main button[class*="px-"][class*="rounded"]:is(.py-1, .py-0\.5, .text-xs, .text-\[10px\], .text-\[11px\]):is(.py-0\.5, .py-1, .py-1\.5, .py-2):not(.w-full, .text-left, .flex-col, .block) {
  height: var(--ctl-h-sm);
  padding-top: 0;
  padding-bottom: 0;
}
/* Legacy solid buttons: red is destructive (ghost, danger text); slate is
   secondary (ghost); amber was the old brand accent (the one solid accent).
   Orange (Retry / Reset) and the amber Upload label are secondary (ghost);
   yellow (Save rules), sky and violet were each a page's primary (accent).
   [class] and the theme prefix outrank the text-white remaps. */
html[data-ui="v2"] button.bg-red-600[class],
html[data-ui="v2"] button.bg-red-600[class]:hover {
  background: transparent;
  color: var(--danger);
  border: 1px solid var(--border-button);
}
html[data-ui="v2"] button.bg-red-600[class]:hover {
  background: var(--danger-fill);
  border-color: var(--border-input);
}
html[data-ui="v2"] button.bg-slate-600[class],
html[data-ui="v2"] button.bg-slate-600[class]:hover,
html[data-ui="v2"] button.bg-orange-600[class],
html[data-ui="v2"] button.bg-orange-600[class]:hover,
html[data-ui="v2"] label.bg-amber-600[class],
html[data-ui="v2"] label.bg-amber-600[class]:hover {
  background: transparent;
  color: var(--text-heading);
  border: 1px solid var(--border-button);
}
html[data-ui="v2"] button.bg-slate-600[class]:hover,
html[data-ui="v2"] button.bg-orange-600[class]:hover,
html[data-ui="v2"] label.bg-amber-600[class]:hover {
  background: var(--bg-hover);
  border-color: var(--border-input);
}
html[data-ui="v2"] button.bg-amber-600[class],
html[data-ui="v2"] button.bg-yellow-600[class],
html[data-ui="v2"] button.bg-sky-600[class],
html[data-ui="v2"] button.bg-violet-600[class] {
  background: var(--accent);
  color: var(--on-accent);
  border: 1px solid var(--accent);
}
html[data-ui="v2"] button.bg-amber-600[class]:hover,
html[data-ui="v2"] button.bg-yellow-600[class]:hover,
html[data-ui="v2"] button.bg-sky-600[class]:hover,
html[data-ui="v2"] button.bg-violet-600[class]:hover {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}
html[data-ui="v2"] :is(button.bg-amber-600, button.bg-yellow-600, button.bg-sky-600, button.bg-violet-600)[class] .text-white {
  color: var(--on-accent);
}
/* Destructive: ghost with danger text, never a solid block. */
html[data-ui="v2"] .btn-danger {
  background: transparent;
  color: var(--danger);
  border: 1px solid var(--border-button);
}
html[data-ui="v2"] .btn-danger:hover {
  background: var(--danger-fill);
  border-color: var(--border-input);
}
html[data-ui="v2"] .btn-ghost {
  color: var(--accent);
}
/* Nothing above 600: SVG text weights and the old inline 700s. */
html[data-ui="v2"] .dock-badge,
html[data-ui="v2"] .v2-launcher .brand-fallback {
  font-weight: var(--fw-semibold);
}
html[data-ui="v2"] svg text[font-weight="bold"],
html[data-ui="v2"] svg text[font-weight="700"],
html[data-ui="v2"] svg text[font-weight="800"],
html[data-ui="v2"] svg text[font-weight="900"] {
  font-weight: var(--fw-semibold);
  font-variant-numeric: tabular-nums;
}
html[data-ui="v2"] .badge {
  font-size: var(--fs-meta);
  line-height: var(--lh-meta);
  letter-spacing: var(--tr-meta);
}

/* Monospace is for code only. Data (ids, clocks, counts) is Inter with
   tabular figures; a key hint is a small sans label. */
html[data-ui="v2"] .font-mono {
  font-family: var(--font-sans);
  font-variant-numeric: tabular-nums;
}
html[data-ui="v2"] :is(code, pre, samp) {
  font-family: var(--font-mono);
  font-size: 0.929em;
}
html[data-ui="v2"] kbd {
  font-family: var(--font-sans);
  font-size: var(--fs-meta);
  line-height: var(--lh-meta);
  font-weight: 500;
}

/* Text colour roles: the stray greys the remaps above do not reach (raw
   slate-500 in light, slate-600 / 700 at 2.4:1 in dark, the /60 and /70
   alphas) become the muted role, which passes AA on every surface. */
html[data-ui="v2"] .text-slate-500,
html[data-ui="v2"] .text-slate-500\/70,
html[data-ui="v2"] .text-slate-400\/70,
html[data-ui="v2"] .text-slate-600,
html[data-ui="v2"] .text-slate-700,
html[data-ui="v2"] .text-gray-500\/60,
html[data-ui="v2"] .text-gray-600\/60,
html[data-ui="v2"].dark .text-gray-700 {
  color: var(--text-muted);
}

/* Shell text on the scale. */
html[data-ui="v2"] .dock-tooltip {
  font-size: var(--fs-meta);
  line-height: var(--lh-meta);
}
html[data-ui="v2"] .dock-badge-error {
  min-width: 18px;
  height: 18px;
  font-size: var(--fs-micro);
  line-height: 18px;
  font-variant-numeric: tabular-nums;
}
html[data-ui="v2"] .ticker-label {
  line-height: var(--lh-micro);
}

/* ── Finisher: launcher tile, textareas ───────────────────────────────── */
/* The launcher tile keeps one status dot (Live), not a grey dot before the
   name. (The brand mark moved to .v2-brand-mark, below.) */
html[data-ui="v2"] .v2-launcher .node .icon { display: none; }
html[data-ui="v2"] textarea.resize-none { resize: none; }

/* ── Finisher: rail overflow cue ──────────────────────────────────────── */
/* On a short window (a laptop's ~780px viewport) the rail's items run past
   the bottom. A soft 24px band at the bottom edge says "more below": the
   scroll-shadow technique, two backgrounds, one fixed to the nav's bottom
   edge and one cover that travels with the content (attachment: local) and
   hides the band once the list ends or when it does not overflow at all.
   No at-rules and no script. */
html[data-ui="v2"] .dock nav {
  background:
    linear-gradient(to top, var(--bg-sidebar) 50%, transparent) center bottom / 100% 48px no-repeat local,
    linear-gradient(to top, color-mix(in srgb, var(--text-muted) 28%, transparent), transparent) center bottom / 100% 24px no-repeat scroll;
}
/* A select whose stock markup writes its edge inline takes the button edge
   too (Signal ROI's window select). */
html[data-ui="v2"] main select[style*="border"]:not([multiple], [size]) {
  border-color: var(--border-button) !important;
}
html[data-ui="v2"] main select[style*="border"]:not([multiple], [size]):hover {
  border-color: var(--border-input) !important;
}
html[data-ui="v2"] main select[style*="border"]:not([multiple], [size]):focus {
  border-color: var(--accent) !important;
}

/* ── Brand mark (kit 2026-09) ─────────────────────────────────────────── */
/* One mark, two files: logos/<slug>-mark-black.svg for a light page and
   -mark-white.svg for a dark one. Which one shows is a display swap on
   html.dark — not a filter, which would grey the artwork and break the
   moment the mark stops being a flat silhouette. An <img> cannot take
   currentColor, and CSS cannot rewrite src, so both files are in the markup
   and one is hidden; they are ~450 bytes each.

   Size: the mark's own artwork fills 94% of its viewBox, so a 28px box
   leaves ~1px of clear space and draws 26px of mark — the optical height of
   the 28px tile it replaces. object-fit: contain, never a fixed width and
   height pair, so it cannot be stretched.

   Vertical position: no nudge. The mark is radially symmetric, so its centre
   is its optical centre, and the header row's align-items: center already
   puts it there. Re-measured after the type step to 14px, from the rendered
   pixels at 1440/DPR2 (ink extents, not derived metrics): the mark's ink runs
   y 9.5–33.5 and the name's leading capital runs 16.5–26.5 — both centre on
   21.5. A translate here would only break that. */
html[data-ui="v2"] .v2-brand-mark {
  display: block;
  width: 28px;
  height: 28px;
  flex: 0 0 28px;
}
html[data-ui="v2"] .v2-brand-mark img {
  display: none;
  width: 100%;
  height: 100%;
  object-fit: contain;
}
html[data-ui="v2"]:not(.dark) .v2-brand-mark .v2-brand-mark-on-light,
html[data-ui="v2"].dark .v2-brand-mark .v2-brand-mark-on-dark {
  display: block;
}
/* Launcher: the same 120px box the old brand image was given (it was a
   full-bleed square, so 120px of artwork; the mark draws 113px in the same
   box and reads at the same weight). */
html[data-ui="v2"] .v2-launcher .v2-brand-mark {
  width: 120px;
  height: 120px;
  flex: 0 0 120px;
}
/* Agent IQ falls back to the brand mark when an agent has no headshot: a
   64px box on the inset disc the headshot uses.
   Radius 6, not 8: the headshot this stands in for is `.w-16.h-16.rounded-2xl`
   inside the persona `.card`, and `.card .rounded-2xl` is the 6px inner radius,
   not the 8px card one. Measured in Chromium at 1440: both boxes are 64x64 at
   the same x/y, so the corner is the only thing that could differ, and at 8 it
   did. */
html[data-ui="v2"] .v2-brand-mark-tile {
  width: 64px;
  height: 64px;
  flex: 0 0 64px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  background: var(--bg-inset);
  border: 1px solid var(--border-primary);
}
html[data-ui="v2"] .v2-brand-mark-tile .v2-brand-mark {
  width: 40px;
  height: 40px;
  flex: 0 0 40px;
}

/* ── Shell: the rail opens on hover (2026-09-21) ──────────────────────── */
/* The stock .dock-tooltip sits outside the 58px rail and is clipped by the
   nav's overflow-x: hidden, so it never showed; people fell back to the slow
   native title tooltip. Under v2 the rail widens OVER the page on hover or
   keyboard focus (content does not move) and shows each item's name beside
   its icon. Icons keep their x position: 8px margin + 11px padding = the
   collapsed rail's centred 19px. A short delay on open stops the rail from
   flashing open when the pointer only crosses it. The mobile drawer
   (.dock-mobile) keeps its own layout. */
html[data-ui="v2"] .dock:not(.dock-mobile) {
  transition: width 140ms ease, box-shadow 140ms ease;
}
html[data-ui="v2"] .dock:not(.dock-mobile):hover,
html[data-ui="v2"] .dock:not(.dock-mobile):focus-within {
  width: 224px;
  box-shadow: var(--shadow-float);
  border-right: 1px solid var(--border-primary);
  transition-delay: 120ms;
}
html[data-ui="v2"] .dock:not(.dock-mobile) .dock-item {
  width: auto;
  margin: 2px 8px;
  padding: 0 11px;
  justify-content: flex-start;
  gap: 12px;
  overflow: hidden;
}
html[data-ui="v2"] .dock:not(.dock-mobile) .dock-item-text.hidden {
  display: inline;
  opacity: 0;
  white-space: nowrap;
  font-size: var(--fs-ui);
  line-height: var(--lh-ui);
  font-weight: 500;
  letter-spacing: var(--tr-ui);
  transition: opacity 100ms ease;
}
html[data-ui="v2"] .dock:not(.dock-mobile):hover .dock-item-text.hidden,
html[data-ui="v2"] .dock:not(.dock-mobile):focus-within .dock-item-text.hidden {
  opacity: 1;
  transition-delay: 180ms;
}
html[data-ui="v2"] .dock:not(.dock-mobile) .dock-divider {
  width: auto;
  margin: 4px 16px;
}
/* The names are on screen now, so the clipped tooltip is redundant. */
html[data-ui="v2"] .dock-tooltip {
  display: none;
}

/* ── Shell: rail badge dot (2026-09-22) ───────────────────────────────── */
/* The stock dot is absolutely positioned from the item's right edge, so where it lands
   depends on the item's width: it bit into the icon on the collapsed rail, sat above the
   icon's centre on a scaled Windows screen with the rail's scrollbar showing, and jumped
   to the far edge when the rail opened. Put it IN THE FLOW right after the icon instead
   (order 1, between the icon and the label) and pull it onto the icon's top-right corner
   with negative margins, so it follows the icon whatever the item's width or padding.
   The right margin gives back exactly the space the dot and its gap take, so labels on
   items with a dot line up with the rest when the rail is open. */
html[data-ui="v2"] .dock:not(.dock-mobile) .dock-item svg { order: 0; }
html[data-ui="v2"] .dock:not(.dock-mobile) .dock-item-text { order: 2; }
html[data-ui="v2"] .dock:not(.dock-mobile) .dock-badge {
  position: relative;
  order: 1;
  flex: 0 0 auto;
  top: -9px;
  right: auto;
  left: auto;
  width: 7px;
  height: 7px;
  margin: 0 -5px 0 -14px;   /* 12 gap - 14 + 7 + 12 gap - 5 = the 12px icon->label gap */
  border: 0;
  box-shadow: none;
}
html[data-ui="v2"] .dock:not(.dock-mobile) .dock-badge-error {
  position: relative;
  order: 1;
  flex: 0 0 auto;
  top: -9px;
  right: auto;
  left: auto;
  margin: 0 -9px 0 -21px;   /* 18px pill centred on the icon's corner; 12-21+18+12-9 = 12 */
}
