:root {
  --bg: #0e0f16;
  --panel: #171926;
  --panel-line: #262a3c;
  --ink: #f6f1e7;
  --ink-dim: rgba(246,241,231,0.55);
  --ink-faint: rgba(246,241,231,0.32);
  --accent-claude: #7fb8a3;
  --accent-coder: #e8a857;
  --accent-reviewer: #d97a6b;
  --accent-danger: #e0796f;
  --accent-good: #6fe08a;
  /* Was the exact same literal rgba()/hex tint duplicated in 4 separate
     pages' error/success banners (login, signup, complete-profile,
     edit-profile) -- hoisted here so those banners actually reskin along
     with everything else under a new visual theme, instead of staying
     stuck in retro's colors forever. */
  --accent-danger-bg: rgba(224,121,111,0.14);
  --accent-danger-border: rgba(224,121,111,0.35);
  --accent-danger-text: #f0b0a8;
  --accent-good-bg: rgba(111,224,138,0.1);
  --accent-good-border: rgba(111,224,138,0.3);
  --font-mono: ui-monospace, "SF Mono", "Cascadia Code", Consolas, "Liberation Mono", monospace;
  --font-serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  /* Matches .panel's/.btn's own current hardcoded border-radius values --
     tokenized so a visual theme (Modern) can round them out further
     without rewriting either rule. */
  --radius-panel: 14px;
  --radius-btn: 8px;
  /* .btn's own surface tint -- was a hardcoded white overlay, invisible
     against a light theme's near-white --panel/--bg (confirmed: 6-12%
     white-on-white reads as no button at all). Tokenized so light theme
     can key the same tint off --ink instead, below. */
  --btn-bg: rgba(255,255,255,0.06);
  --btn-bg-hover: rgba(255,255,255,0.12);
  /* Text color for anything sitting on a solid var(--accent-good) fill
     (.btn--primary, .visual-theme-control__option.is-active). Computed
     real WCAG contrast for this exact value against --accent-good across
     every theme combo before choosing it -- see shared.css's own
     .btn--primary rule for the one combo (modern light) that needs a
     different value. */
  --accent-good-ink: #0b1a10;
  /* Retro never got its own --field-bg (Modern/Futuristic did, below) --
     every retro-theme input field fell back to a hardcoded literal
     wherever it was consumed (e.g. .field input's own
     var(--field-bg, rgba(0,0,0,0.25))) instead of a real token. Reusing
     --btn-bg's exact value here rather than inventing a new one -- same
     "a subtle surface tint that reads on either a dark or light canvas"
     concept, no reason for a field's tint and a button's tint to diverge
     for retro specifically when Modern/Futuristic don't either. */
  --field-bg: var(--btn-bg);
  /* Validated 8-hue categorical palette (dataviz skill's reference
     instance, used verbatim -- these are the stock hex values, not a
     custom brand ramp, so no re-validation is needed per the skill's own
     rule). Promoted here from dashboard.html's own <style> block once a
     second page (dashboard-platform.html) needed the exact same values --
     CODING_STANDARDS.md's own Decoupling section names this the point to
     share, not before. */
  --series-1: #3987e5; --series-2: #d95926; --series-3: #199e70; --series-4: #c98500;
  --series-5: #d55181; --series-6: #008300; --series-7: #9085e9; --series-8: #e66767;
}

:root[data-theme="light"] {
  --bg: #f7f5f0;
  --panel: #ffffff;
  --panel-line: #e2ddd0;
  --ink: #23241f;
  --ink-dim: rgba(35,36,31,0.6);
  --ink-faint: rgba(35,36,31,0.35);
  --series-1: #2a78d6; --series-2: #eb6834; --series-3: #1baf7a; --series-4: #eda100;
  --series-5: #e87ba4; --series-6: #008300; --series-7: #4a3aa7; --series-8: #e34948;
  --accent-claude: #3f7a63;
  --accent-coder: #a8631a;
  --accent-reviewer: #a13f30;
  --accent-danger: #b8392c;
  --accent-good: #2f8f4e;
  --btn-bg: rgba(35,36,31,0.06);
  --btn-bg-hover: rgba(35,36,31,0.12);
}

/* Second, independent theme dimension -- data-visual-theme, orthogonal to
   data-theme (light/dark) above (see theme-toggle.js). 'retro' is today's
   existing look, kept as an explicit no-op block (equal to the bare :root
   values) rather than just letting it fall through unstyled, so it's a
   real, addressable value of this dimension rather than "the absence of
   one" -- and so the pattern here (retro/modern/futuristic all being
   real, equally-weighted sibling blocks) is consistent from day one.
   [data-visual-theme="modern"] and [data-visual-theme="futuristic"] are
   later phases of the same plan -- selecting them is fully wired already
   (see theme-toggle.js), they just have no visual effect yet. */
:root[data-visual-theme="retro"] {
  --bg: #0e0f16;
  --panel: #171926;
  --panel-line: #262a3c;
  --ink: #f6f1e7;
  --ink-dim: rgba(246,241,231,0.55);
  --ink-faint: rgba(246,241,231,0.32);
  --accent-claude: #7fb8a3;
  --accent-coder: #e8a857;
  --accent-reviewer: #d97a6b;
  --accent-danger: #e0796f;
  --accent-good: #6fe08a;
  --radius-panel: 14px;
  --radius-btn: 8px;
}
:root[data-theme="light"][data-visual-theme="retro"] {
  --bg: #f7f5f0;
  --panel: #ffffff;
  --panel-line: #e2ddd0;
  --ink: #23241f;
  --ink-dim: rgba(35,36,31,0.6);
  --ink-faint: rgba(35,36,31,0.35);
  --accent-claude: #3f7a63;
  --accent-coder: #a8631a;
  --accent-reviewer: #a13f30;
  --accent-danger: #b8392c;
  --accent-good: #2f8f4e;
}

/* Modern (Phase 3 of the multi-theme UI plan): soft/glass aesthetic --
   rounder panels/buttons, a soft drop shadow on every panel, and a single
   clean sans-serif for both font slots (this app's chrome is built
   entirely on var(--font-mono)/var(--font-serif), so overriding just
   these two tokens reskins every page's typography with no other
   changes needed). Dark and light variants both exist, same as retro --
   selecting Modern doesn't force one or the other. */
:root[data-visual-theme="modern"] {
  /* Revised per a reference graphic showing a vivid violet-to-blue
     gradient backdrop with a central robot hub and glowing gradient
     icon-tiles, rather than the flatter soft-white/glass look this theme
     shipped with initially. --bg stays a plain solid (several existing
     rules use var(--bg) as a literal color -- e.g. text-on-accent-pill --
     a gradient there would break them); --bg-gradient is the actual
     vivid backdrop, applied only to html/body below. */
  --bg: #1c1147;
  --bg-gradient: linear-gradient(135deg, #241a5c 0%, #2d1f8f 32%, #3a2db8 62%, #1c3fc4 100%);
  --panel: #2a2170;
  --panel-line: rgba(150,130,255,0.32);
  --ink: #f5f3ff;
  --ink-dim: rgba(245,243,255,0.66);
  --ink-faint: rgba(245,243,255,0.4);
  --accent-claude: #7ee0e8;
  --accent-coder: #ffb86e;
  --accent-reviewer: #ff8fd1;
  --accent-danger: #ff6b7a;
  --accent-good: #5ee6ff;
  --accent-danger-bg: rgba(255,107,122,0.16);
  --accent-danger-border: rgba(255,107,122,0.4);
  --accent-danger-text: #ffb3ba;
  --accent-good-bg: rgba(94,230,255,0.14);
  --accent-good-border: rgba(94,230,255,0.35);
  --radius-panel: 20px;
  --radius-btn: 12px;
  --panel-shadow: 0 20px 40px -20px rgba(10,5,40,0.6), 0 0 0 1px rgba(150,130,255,0.12);
  --field-bg: rgba(255,255,255,0.08);
  --font-mono: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, "Helvetica Neue", Arial, sans-serif;
}
:root[data-theme="light"][data-visual-theme="modern"] {
  --bg: #eef0fb;
  --bg-gradient: linear-gradient(135deg, #eef0fb 0%, #e6e9fb 45%, #dee6fc 100%);
  --panel: #ffffff;
  --panel-line: #dfe2f7;
  --ink: #241b4d;
  --ink-dim: rgba(36,27,77,0.62);
  --ink-faint: rgba(36,27,77,0.38);
  --accent-claude: #2f8fa0;
  --accent-coder: #b4650f;
  --accent-reviewer: #a8317f;
  --accent-danger: #b8342f;
  --accent-good: #2f6fdc;
  --accent-danger-bg: rgba(184,52,47,0.1);
  --accent-danger-border: rgba(184,52,47,0.3);
  --accent-danger-text: #8f2a26;
  --accent-good-bg: rgba(47,111,220,0.1);
  --accent-good-border: rgba(47,111,220,0.3);
  --panel-shadow: 0 20px 40px -24px rgba(36,27,77,0.18);
  /* rgba(0,0,0,0.25) (the app-wide default) reads as a heavy gray box on
     a white panel -- a soft neutral tint instead, still a clearly visible
     input against --panel's white. */
  --field-bg: rgba(36,27,77,0.05);
  /* The only combo where dark text on --accent-good fails WCAG AA
     outright (computed: 3.79:1 with #0b1a10, needs 4.5:1) -- white text
     clears it (4.74:1). Every other combo already passes with the base
     :root's #0b1a10, so this is the one deliberate override. */
  --accent-good-ink: #ffffff;
}
/* Only Modern defines --bg-gradient -- the fallback keeps retro/
   futuristic on their existing plain var(--bg) fill, unchanged. :root
   IS the <html> element itself (not an ancestor of it), so it's targeted
   directly here; body is a genuine descendant and needs its own rule. */
:root[data-visual-theme="modern"] { background: var(--bg-gradient, var(--bg)); }
:root[data-visual-theme="modern"] body { background: var(--bg-gradient, var(--bg)); }

/* Futuristic (Phase 4): a JARVIS-style HUD -- near-black glass, thin
   glowing cyan edges, sharp/angular corners (a deliberate contrast to
   Modern's roundness), monospace kept throughout (no font override --
   a technical/HUD look wants the terminal typeface, not a swap to
   sans-serif). Dark is the hero variant here (matches the reference
   image); light is a "daylight HUD" variant for consistency with the
   architecture, not the star of the show. */
:root[data-visual-theme="futuristic"] {
  --bg: #05070d;
  --panel: #0a1220;
  --panel-line: rgba(110,230,255,0.25);
  --ink: #e8faff;
  --ink-dim: rgba(232,250,255,0.6);
  --ink-faint: rgba(232,250,255,0.32);
  --accent-claude: #6ee7ff;
  --accent-coder: #ffd166;
  --accent-reviewer: #ff6e9c;
  --accent-danger: #ff5f6e;
  --accent-good: #4ff0ff;
  --accent-danger-bg: rgba(255,95,110,0.14);
  --accent-danger-border: rgba(255,95,110,0.4);
  --accent-danger-text: #ffb0b8;
  --accent-good-bg: rgba(79,240,255,0.12);
  --accent-good-border: rgba(79,240,255,0.35);
  --radius-panel: 4px;
  --radius-btn: 2px;
  --panel-shadow: 0 0 24px rgba(110,230,255,0.12), inset 0 0 0 1px rgba(110,230,255,0.12);
  --panel-shadow-strong: 0 0 32px rgba(110,230,255,0.22), inset 0 0 0 1px rgba(110,230,255,0.22);
  --field-bg: rgba(110,230,255,0.06);
}
:root[data-theme="light"][data-visual-theme="futuristic"] {
  --bg: #eef7fb;
  --panel: #ffffff;
  /* --panel-line/--panel-shadow* bumped well past dark's own alpha values
     (0.3->0.55, 0.1/0.2->0.3/0.5) -- confirmed via live screenshot
     comparison against the dark variant that matching alpha numerically
     does NOT match perceived strength: the same rgba glow reads far
     weaker against this theme's near-white --panel/--bg than against
     dark's near-black canvas, which is real physics (background
     luminance dominates a translucent overlay's contrast), not a token
     bug. This was flagged as visibly flatter than Retro/Modern's own
     light variants -- boosted until a live screenshot showed real,
     legible cyan presence instead of an near-invisible tint. Reuses
     --accent-claude's own hue (#0891b2) rather than the previous
     separate rgba(14,120,150,...) literal, so the border/glow and this
     theme's own accent color are visibly the same cyan, not two
     slightly-different blues. */
  --panel-line: rgba(8,145,178,0.55);
  --ink: #08202a;
  --ink-dim: rgba(8,32,42,0.6);
  --ink-faint: rgba(8,32,42,0.35);
  --accent-claude: #0891b2;
  --accent-coder: #b45309;
  --accent-reviewer: #be185d;
  --accent-danger: #b91c1c;
  --accent-good: #0e9f8e;
  --accent-danger-bg: rgba(185,28,28,0.1);
  --accent-danger-border: rgba(185,28,28,0.3);
  --accent-danger-text: #991b1b;
  --accent-good-bg: rgba(14,159,142,0.1);
  --accent-good-border: rgba(14,159,142,0.3);
  --radius-panel: 4px;
  --radius-btn: 2px;
  --panel-shadow: 0 0 20px rgba(8,145,178,0.3), inset 0 0 0 1px rgba(8,145,178,0.32);
  --panel-shadow-strong: 0 0 30px rgba(8,145,178,0.5), inset 0 0 0 1px rgba(8,145,178,0.5);
  --field-bg: rgba(8,32,42,0.05);
}
/* A faint living glow on every panel's edge -- reinforces the "HUD is
   alive" feel from the reference image without being distracting (long
   8s cycle, subtle opacity swing only). Keyed off --panel-shadow-strong
   rather than a hardcoded color so dark and light variants each glow in
   their own tone instead of both animating toward the dark variant's
   brighter cyan. */
:root[data-visual-theme="futuristic"] .panel,
:root[data-theme="light"][data-visual-theme="futuristic"] .panel {
  animation: futuristic-panel-glow 8s ease-in-out infinite;
}
@keyframes futuristic-panel-glow {
  0%, 100% { box-shadow: var(--panel-shadow); }
  50% { box-shadow: var(--panel-shadow-strong); }
}

/* .app-nav__dropdown-item is normally an <a> -- these are <button>s (the
   theme toggle, and the visual-theme flyout's 3 options), so browser
   button defaults need resetting to actually look like their sibling
   dropdown items instead of native button chrome (confirmed directly:
   without this, the flyout's option buttons rendered as blank white
   default buttons with barely-visible text). */
.app-nav__theme-toggle-item,
.app-nav__theme-picker__menu .app-nav__dropdown-item {
  width: 100%; text-align: left; background: none; border: none;
  font: inherit; text-transform: inherit; letter-spacing: inherit;
}
.app-nav__theme-toggle-item {
  /* var(--font-serif)'s stack has no glyph for the "sun" symbol (U+2600)
     used in the Light theme label, so it fell back to a .notdef box that
     rendered as a bare asterisk -- system-ui reliably covers it. Scoped to
     just this button, not the shared .app-nav__dropdown-item selector
     above, so plain text nav links keep the serif font unchanged. */
  font-family: system-ui, sans-serif;
}

* { box-sizing: border-box; }
html, body {
  margin: 0; padding: 0;
  background: var(--bg); color: var(--ink);
  font-family: var(--font-serif);
}

a { color: inherit; }

.app-shell { max-width: 1320px; margin: 0 auto; padding: clamp(1rem, 3vw, 2.5rem); }

.app-nav {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; margin-bottom: clamp(1.2rem, 2.5vw, 2rem);
  padding-bottom: 1rem; border-bottom: 1px solid var(--panel-line);
}
/* Below ~640px, .app-nav__links wraps onto 2-3 rows (it already has its
   own flex-wrap) -- .app-nav's default align-items:center then centers the
   single-line brand against that whole multi-row block's height, landing
   it visually in the middle of the wrapped rows instead of above them
   (confirmed via computed rects at 375px, 2026-08-05). Stacking brand above
   links instead removes the ambiguity outright. */
@media (max-width: 640px) {
  .app-nav { flex-direction: column; align-items: flex-start; gap: 0.6rem; }
}
.app-nav__brand {
  font-family: var(--font-mono); font-size: 0.85rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ink);
}
.app-nav__brand span { color: var(--accent-good); }
.app-nav__links { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.app-nav__link {
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.05em;
  text-transform: uppercase; text-decoration: none; color: var(--ink-dim);
  padding: 0.5em 0.9em; border-radius: 999px; border: 1px solid transparent;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.app-nav__link:hover { color: var(--ink); border-color: var(--panel-line); }
.app-nav__link.active { color: var(--bg); background: var(--accent-good); }

/* The avatar button doubles as its own dropdown's open/close toggle (no
   separate "real destination" link the way Project Management/Settings
   have -- see nav.js) -- round, small, shows a photo if the user has one
   or their initial otherwise. */
.app-nav__user-avatar {
  width: 30px; height: 30px; border-radius: 50%; overflow: hidden;
  background: var(--accent-good); color: #0b1a10; border: 1px solid var(--panel-line);
  font-family: var(--font-mono); font-weight: bold; font-size: 0.78rem;
  display: flex; align-items: center; justify-content: center; cursor: pointer; padding: 0;
}
.app-nav__user-avatar img { width: 100%; height: 100%; object-fit: cover; }
.app-nav__user-menu .app-nav__dropdown-menu { right: 0; left: auto; }
.app-nav__user-menu-label {
  font-family: var(--font-mono); font-size: 0.66rem; color: var(--ink-faint);
  padding: 0.4em 0.7em 0.6em; border-bottom: 1px solid var(--panel-line); margin-bottom: 0.3em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 220px;
}

/* Nav item that reveals a small menu of related pages. Opens on hover
   (desktop) AND on click via .is-open (touch, keyboard) -- hover alone
   doesn't fire on touch devices, so the toggle link's own click is
   intercepted once to open-only before it's allowed to navigate. */
.app-nav__dropdown { position: relative; display: inline-flex; align-items: center; }
/* Separate from the link on purpose: the toggle link is a real destination
   in its own right, so its click must always navigate on the first try,
   never get intercepted to "just open the submenu" first (that's what
   caused a real first-click-does-nothing bug). This caret is the ONLY
   thing that opens the menu by click/tap -- hover still opens it too, for
   desktop mouse users, independent of this button. */
.app-nav__dropdown-caret {
  background: none; border: none; cursor: pointer; padding: 0 0.35em;
  margin-left: -0.3em; color: var(--ink-dim); font-size: 0.62rem; line-height: 1;
  display: inline-flex; align-items: center; border-radius: 4px;
}
.app-nav__dropdown-caret:hover { color: var(--ink); }
.app-nav__dropdown-caret:focus-visible { outline: 2px solid var(--accent-good); outline-offset: 1px; }
.app-nav__dropdown-menu {
  /* top:100% with NO margin -- the box itself must be pixel-flush against
     the toggle link's bottom edge. A margin-top gap here is a dead zone:
     .app-nav__dropdown only sizes to the link itself (inline-flex), so
     that gap sits outside every hoverable box, and moving the pointer
     down through it drops :hover before the mouse ever reaches the menu
     (menu closes mid-transit, unclickable). Visual breathing room comes
     from padding-top instead -- inside the box, so hover stays contiguous
     from the toggle straight into it. */
  display: none; position: absolute; top: 100%; left: 0; padding-top: 0.4rem;
  min-width: 180px; z-index: 20;
}
.app-nav__dropdown-menu__panel {
  background: var(--panel); border: 1px solid var(--panel-line);
  border-radius: 10px; padding: 0.35rem; box-shadow: 0 8px 24px rgba(0,0,0,0.35);
}
.app-nav__dropdown:hover .app-nav__dropdown-menu,
.app-nav__dropdown.is-open .app-nav__dropdown-menu { display: block; }
.app-nav__dropdown-item {
  display: block; font-family: var(--font-mono); font-size: 0.68rem;
  letter-spacing: 0.05em; text-transform: uppercase; text-decoration: none;
  color: var(--ink-dim); padding: 0.55em 0.7em; border-radius: 6px;
  white-space: nowrap; transition: background 0.2s ease, color 0.2s ease;
}
.app-nav__dropdown-item:hover { color: var(--ink); background: var(--bg); }
.app-nav__dropdown-item.active { color: var(--bg); background: var(--accent-good); }

/* Nested flyout for the visual-theme picker, living inside the user-menu
   panel (see nav.js/theme-toggle.js). Deliberately its own is-open/hover
   toggle, independent of .app-nav__dropdown's -- opening this must never
   close the user-menu it's nested inside. Opens to the LEFT (right:100%),
   not below/right like a top-level dropdown: the user-menu itself is
   already right-aligned to the edge of the viewport, so a flyout that
   opened rightward or downward-then-rightward would run off-screen. */
.app-nav__theme-picker { position: relative; }
.app-nav__theme-picker__toggle { cursor: pointer; }
.app-nav__theme-picker__menu {
  display: none; position: absolute; top: 0; right: 100%; padding-right: 0.4rem; min-width: 140px; z-index: 25;
}
.app-nav__theme-picker:hover .app-nav__theme-picker__menu,
.app-nav__theme-picker.is-open .app-nav__theme-picker__menu { display: block; }

/* Simple segmented-control rendering of the same 3 options for Edit
   Profile -- a full page section, not a nav dropdown, so no flyout/hover
   needed there, just 3 directly-clickable buttons. */
.visual-theme-control { display: flex; gap: 0.5rem; flex-wrap: wrap; }
.visual-theme-control__option.is-active { background: var(--accent-good); color: var(--accent-good-ink); border-color: transparent; }

.panel {
  background: var(--panel); border: 1px solid var(--panel-line); border-radius: var(--radius-panel);
  padding: clamp(1rem, 2vw, 1.5rem); box-shadow: var(--panel-shadow, none);
}

.flag-row {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.9rem 0; border-bottom: 1px solid var(--panel-line);
}
.flag-row:last-child { border-bottom: none; }
.flag-row__info { min-width: 0; }
.flag-row__label { font-size: 0.95rem; }
.flag-row__description { font-size: 0.82rem; color: var(--ink-dim); margin-top: 0.2rem; }
.flag-row__error { color: #f0b0a8; }
/* Groups the toggle + delete button together at the row's right edge --
   without this, .flag-row's own space-between (3 children instead of 2
   once Delete was added) would spread them apart unevenly instead of
   keeping them together, same reasoning users.html's own .user-row__actions
   wrapper already exists for. */
.flag-row__actions { display: flex; align-items: center; gap: 0.6rem; flex-shrink: 0; }

.flag-toggle { position: relative; display: inline-flex; flex-shrink: 0; width: 42px; height: 24px; cursor: pointer; }
.flag-toggle__input { position: absolute; opacity: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.flag-toggle__track {
  position: absolute; inset: 0; background: rgba(255,255,255,0.1); border: 1px solid var(--panel-line);
  border-radius: 999px; transition: background 0.2s ease;
}
.flag-toggle__track::before {
  content: ''; position: absolute; top: 2px; left: 2px; width: 18px; height: 18px;
  background: var(--ink); border-radius: 50%; transition: transform 0.2s ease;
}
.flag-toggle__input:checked ~ .flag-toggle__track { background: var(--accent-good); border-color: transparent; }
.flag-toggle__input:checked ~ .flag-toggle__track::before { transform: translateX(18px); background: var(--bg); }
.flag-toggle__input:focus-visible ~ .flag-toggle__track { outline: 2px solid var(--accent-good); outline-offset: 2px; }

/* Plan-card action feedback (2026-08-18). A rejected Approve/Cancel/Queue
   used to be indistinguishable from a successful one -- the board just
   re-polled and nothing changed. These two carry the explanation. */
.plan-action-error {
  margin: 0.6rem 0 0; padding: 0.5em 0.7em; border-radius: 6px;
  font-size: 0.8rem; color: #f0b0a8;
  background: rgba(224,121,111,0.14); border: 1px solid rgba(224,121,111,0.35);
}
.plan-approval-scope { margin: 0 0 0.5rem; font-size: 0.82rem; color: var(--ink-dim); }
.plan-approval-scope--empty { color: #e8c07a; }

.archive-row {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.9rem 0; border-bottom: 1px solid var(--panel-line);
}
.archive-row:last-child { border-bottom: none; }
.archive-row__info { min-width: 0; }
.archive-row__label { font-size: 0.95rem; }
.archive-row__description { font-size: 0.82rem; color: var(--ink-dim); margin-top: 0.2rem; }
.archive-row__error { color: #f0b0a8; }
.archive-row__actions { display: flex; align-items: center; gap: 0.6rem; flex-shrink: 0; }

.grid { display: grid; gap: clamp(0.8rem, 1.6vw, 1.2rem); }
.grid--cards { grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }

.card-metric { }
.card-metric__label {
  font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--ink-faint); margin-bottom: 0.5rem;
}
.card-metric__value {
  font-family: var(--font-mono); font-size: clamp(1.3rem, 3vw, 1.8rem);
  font-variant-numeric: tabular-nums; color: var(--ink);
}
.card-metric__sub { font-family: var(--font-mono); font-size: 0.62rem; color: var(--ink-faint); margin-top: 0.3rem; }

.section-title {
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--ink-dim); margin: 0 0 0.9rem;
}

table.data-table { width: 100%; border-collapse: collapse; font-family: var(--font-mono); font-size: 0.78rem; }
table.data-table th, table.data-table td { text-align: left; padding: 0.55rem 0.6rem; border-bottom: 1px solid var(--panel-line); }
table.data-table th { color: var(--ink-faint); font-size: 0.64rem; letter-spacing: 0.08em; text-transform: uppercase; }
table.data-table td.num { font-variant-numeric: tabular-nums; text-align: right; }

.btn {
  display: inline-flex; align-items: center; gap: 0.4em;
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.04em;
  color: var(--ink); background: var(--btn-bg); border: 1px solid var(--panel-line);
  border-radius: var(--radius-btn); padding: 0.55em 1em; cursor: pointer; transition: background 0.2s ease, border-color 0.2s ease;
}
.btn:hover { background: var(--btn-bg-hover); }
.btn:focus-visible { outline: 2px solid var(--accent-good); outline-offset: 2px; }
.btn--primary { background: var(--accent-good); color: var(--accent-good-ink); border-color: transparent; }
/* Was a hardcoded #85e89b (a lighter green) -- correct only for retro's
   green accent-good; modern/futuristic use cyan/blue there, so hovering
   the active button would flash a mismatched color. brightness() stays
   correct for whatever --accent-good actually is in the current theme. */
.btn--primary:hover { filter: brightness(1.08); }
.btn--danger { background: rgba(224,121,111,0.18); border-color: rgba(224,121,111,0.4); color: #f0b0a8; }
.btn--danger:hover { background: rgba(224,121,111,0.28); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; }

.pill {
  display: inline-flex; align-items: center; gap: 0.3em; font-family: var(--font-mono);
  font-size: 0.6rem; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 0.22em 0.6em; border-radius: 999px; background: var(--btn-bg); color: var(--ink-dim);
}
.pill--ok { background: rgba(111,224,138,0.16); color: var(--accent-good); }
.pill--bad { background: rgba(224,121,111,0.16); color: var(--accent-danger); }

label.field { display: block; margin-bottom: 0.9rem; }
label.field span.field__label {
  display: block; font-family: var(--font-mono); font-size: 0.64rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink-dim); margin-bottom: 0.35rem;
}
.field input, .field select, .field textarea {
  width: 100%; background: var(--field-bg, rgba(0,0,0,0.25)); color: var(--ink); border: 1px solid var(--panel-line);
  border-radius: 8px; padding: 0.6em 0.7em; font-family: var(--font-mono); font-size: 0.78rem;
}
.field input:focus, .field select:focus, .field textarea:focus { outline: 2px solid var(--accent-good); outline-offset: 1px; }
.field textarea { resize: vertical; min-height: 5em; }
.field-hint { font-family: var(--font-mono); font-size: 0.62rem; color: var(--ink-faint); margin-top: 0.3rem; }

.empty-state { font-family: var(--font-mono); font-size: 0.78rem; color: var(--ink-faint); padding: 2rem 0; text-align: center; }

/* Was duplicated verbatim across projects.html, settings.html, users.html,
   and edit-profile.html -- consolidated here so it can't drift again. */
.form-grid { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 0 1.2rem; }
.form-grid .field--full { grid-column: 1 / -1; }
@media (max-width: 640px) { .form-grid { grid-template-columns: 1fr; } }

/* Wrap any wide table/board content in this so it scrolls horizontally on
   narrow viewports instead of blowing out .app-shell's width. */
.table-wrap { overflow-x: auto; }

/* Promoted from dashboard.html's own <style> block once dashboard-platform.html
   needed the exact same tooltip + From/To/Agents filter-form look (same
   Decoupling-section rule as --series-N above). */
.viz-tooltip {
  position: fixed; z-index: 50; pointer-events: none; opacity: 0; transform: translateY(4px);
  transition: opacity 0.12s ease, transform 0.12s ease;
  background: var(--panel); border: 1px solid var(--panel-line); border-radius: 8px;
  padding: 0.5em 0.7em; font-family: var(--font-mono); font-size: 0.72rem; color: var(--ink);
  box-shadow: 0 10px 24px -8px rgba(0,0,0,0.5); white-space: nowrap; max-width: 240px;
}
.viz-tooltip.is-visible { opacity: 1; transform: translateY(0); }

.dash-filters { display: flex; align-items: flex-end; flex-wrap: wrap; gap: 16px; margin-bottom: 1.5rem; padding: 16px; }
.dash-filters .field { margin-bottom: 0; }
.dash-filters input[type="date"] { color-scheme: dark; max-width: 10em; }
.dash-filters__actions { display: flex; gap: 8px; margin-left: auto; }

/* A closed, single-line dropdown standing in for a native
   <select multiple> -- that control has no "closed" rendering mode, so
   it was always taller than the date inputs next to it no matter how the
   row's CSS was tuned. Matches .field input's own height/look exactly so
   the row reads as one aligned line. */
.agent-dropdown { position: relative; }
.agent-dropdown__toggle {
  width: 100%; min-width: 12em; text-align: left; background: var(--field-bg, rgba(0,0,0,0.25)); color: var(--ink);
  border: 1px solid var(--panel-line); border-radius: 8px; padding: 0.6em 0.7em; font-family: var(--font-mono);
  font-size: 0.78rem; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 0.5em;
}
.agent-dropdown__toggle:hover { border-color: #3a3f56; }
.agent-dropdown__toggle:focus-visible, .agent-dropdown[data-open="true"] .agent-dropdown__toggle { outline: 2px solid var(--accent-good); outline-offset: 1px; }
.agent-dropdown__toggle-caret { color: var(--ink-faint); flex-shrink: 0; }
.agent-dropdown__panel {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 5; min-width: max(100%, 14em);
  background: var(--panel); border: 1px solid var(--panel-line); border-radius: 8px;
  padding: 6px; max-height: 12em; overflow-y: auto; box-shadow: 0 12px 24px -8px rgba(0,0,0,0.5);
}
.agent-dropdown__option { display: flex; align-items: center; gap: 0.6em; padding: 0.45em 0.5em; border-radius: 6px; cursor: pointer; font-family: var(--font-mono); font-size: 0.76rem; color: var(--ink); white-space: nowrap; }
.agent-dropdown__option:hover { background: var(--btn-bg); }
.agent-dropdown__option input { margin: 0; accent-color: var(--accent-good); }

/* Basic hourly bar-chart building blocks -- promoted here once
   dashboard-platform.html's cache-hit-rate chart needed the same "bars
   in columns, labeled underneath, with a dot-legend" shape the Project
   dashboard's token-usage timeline already had (same Decoupling-section
   rule as --series-N/.viz-tooltip above). The Bar/Line/Area toggle, SVG
   line/area rendering, and absolutely-positioned hour-label row that
   timeline chart ALSO has stay page-local (dashboard.html's own <style>)
   -- only the bar-only pieces are shared, since the cache chart doesn't
   need chart-type switching. */
.timeline-chart { display: flex; align-items: flex-end; gap: 6px; height: 160px; padding-top: 8px; overflow-x: auto; }
.timeline-col { display: flex; flex-direction: column; align-items: center; flex: 1; min-width: 18px; height: 100%; }
.timeline-col__bars { display: flex; align-items: flex-end; gap: 2px; flex: 1; width: 100%; }
.timeline-bar { flex: 1; border-radius: 2px 2px 0 0; min-height: 0; transition: height 0.4s ease, filter 0.15s ease; }
.timeline-bar:hover { filter: brightness(1.25); }
.timeline-col__label { margin-top: 6px; font-family: var(--font-mono); font-size: 0.58rem; color: var(--ink-faint); white-space: nowrap; }
.timeline-legend { display: flex; gap: 12px; margin-top: 10px; flex-wrap: wrap; }
.timeline-legend__item { display: flex; align-items: center; gap: 6px; font-family: var(--font-mono); font-size: 0.66rem; color: var(--ink-dim); }
.timeline-legend__dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* Platform update notice -- fixed to the bottom so it never displaces the
   page it appears over. Styled entirely from the shared tokens so it
   follows the theme rather than pinning its own colours. */
.platform-update-banner {
  position: fixed;
  left: 50%;
  bottom: 1.25rem;
  transform: translateX(-50%);
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  max-width: min(46rem, calc(100vw - 2rem));
  padding: 0.7rem 0.9rem;
  background: var(--panel);
  color: var(--ink);
  border: 1px solid var(--panel-line);
  border-left: 3px solid var(--accent-good);
  border-radius: 6px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.28);
  font-size: 0.9rem;
}
.platform-update-banner[hidden] { display: none; }
.platform-update-banner__text {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.platform-update-banner__action {
  flex: 0 0 auto;
  padding: 0.35rem 0.8rem;
  border: 1px solid var(--accent-good);
  border-radius: 4px;
  background: transparent;
  color: var(--accent-good);
  font: inherit;
  cursor: pointer;
}
.platform-update-banner__action:hover:not(:disabled) {
  background: var(--accent-good);
  color: var(--bg);
}
.platform-update-banner__action:disabled { opacity: 0.6; cursor: default; }
.platform-update-banner__dismiss {
  flex: 0 0 auto;
  padding: 0 0.25rem;
  border: 0;
  background: none;
  color: var(--ink-faint);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
}
.platform-update-banner__dismiss:hover { color: var(--ink); }
@media (max-width: 34rem) {
  .platform-update-banner { flex-wrap: wrap; }
  .platform-update-banner__text { white-space: normal; }
}
