/* ============================================================================
   Data Pilot — Liquid Glass design system
   ----------------------------------------------------------------------------
   Apple-inspired (macOS Sonoma / iOS 18) translucent material layered over an
   ambient light field: real backdrop blur + saturation, specular inset
   highlights, soft multi-layer tinted shadows, restrained spring motion.

   Two themes (light | dark) driven entirely by the design tokens below. The
   root element carries `data-theme="light|dark"` (resolved before first paint
   by the inline boot script in index.html) and `data-theme-pref` records the
   user's stored choice, which may be "system".

   Density rule: this app is data-dense (run IDs, sensor values, confidence
   scores, evidence tables). Blur is applied to *structural* surfaces only —
   chrome, panels, cards, modals. Repeated data rows sit on near-opaque wells
   so text contrast is never left to a translucent stack.

   One documented exception: alert cards use --surface-card, a translucent
   fill over a scrim, because they are short high-contrast lines rather than
   a wall of small numerics — and because the alerts sidebar is the one place
   the ambient field should visibly read through the content. Nested glass is
   done with fills, never a second backdrop-filter: blur does not nest.
   ========================================================================= */

@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600&family=Fira+Sans:wght@400;500;600;700&display=swap');

/* ---------------------------------------------------------------------------
   1. Tokens — shared
   ------------------------------------------------------------------------ */
:root {
  --font-sans: "Fira Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono: "Fira Code", "SF Mono", "Cascadia Mono", Consolas, monospace;

  /* Spacing — 4px base, generous at the container level */
  --sp-1: 0.25rem; --sp-2: 0.5rem;  --sp-3: 0.75rem; --sp-4: 1rem;
  --sp-5: 1.25rem; --sp-6: 1.5rem;  --sp-7: 1.75rem; --sp-8: 2rem;
  --sp-10: 2.5rem; --sp-12: 3rem;

  /* One shared width for every workspace column, so switching modes never
     reflows the content area. */
  --measure-column: 1320px;

  /* Corner radii — tighter inside, softer outside (Apple continuous-ish) */
  --r-xs: 6px;
  --r-sm: 9px;
  --r-md: 13px;
  --r-lg: 20px;
  --r-xl: 28px;
  --r-pill: 999px;

  /* Motion — restrained, springy on press, never gratuitous */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1);
  --transition: 200ms var(--ease-out);
  --transition-slow: 380ms var(--ease-out);
  --transition-spring: 420ms var(--ease-spring);

  /* Layering */
  --z-chrome: 20;
  --z-modal: 100;
  --z-skip: 200;

  /* Glass filter — one token so every surface refracts identically */
  --glass-blur: 34px;
  --glass-filter: blur(var(--glass-blur)) saturate(200%);
  --glass-filter-light: blur(20px) saturate(170%);

  /* Brand mark palette (logo / login chrome only — never status meaning) */
  --brand-1: #ffd43b; --brand-2: #ffb51b; --brand-3: #ff8a1c;
  --brand-4: #f45a18; --brand-5: #d93616;
}

/* ---------------------------------------------------------------------------
   2. Tokens — dark theme (default)
   ------------------------------------------------------------------------ */
:root,
:root[data-theme="dark"] {
  color-scheme: dark;

  --color-background: #080c16;
  --color-foreground: #f2f5fa;
  --color-muted-foreground: #98a4bb;
  --color-faint-foreground: #6b7893;

  /* Ambient light field painted behind every glass surface. Without enough
     colour here the blur has nothing to refract and the glass collapses into
     a flat dark rectangle. Deliberately one cohesive hue family (sky blue ->
     indigo -> violet) at restrained opacity — real Apple ambient materials
     read as soft light bleeding through, not a scattered rainbow of every
     brand/status colour at once. Warning/nominal/critical stay reserved for
     status semantics only and never appear back here. */
  /* Only two ambient pools are used (body::before). Kept low enough that
     the field reads as a tint on the page, never as a visible gradient. */
  --amb-1: rgba(56, 189, 248, 0.10);
  --amb-3: rgba(124, 58, 237, 0.09);

  /* Glass material */
  --glass-bg:        rgba(23, 30, 48, 0.55);
  --glass-bg-strong: rgba(16, 21, 36, 0.80);
  --glass-solid:     rgba(19, 25, 41, 0.94);
  --glass-well:      rgba(10, 14, 25, 0.42);
  --glass-inset:     rgba(255, 255, 255, 0.05);
  --glass-raised:    rgba(255, 255, 255, 0.12);
  /* A data card resting on an already-blurred surface. Deliberately a
     translucent fill rather than a second backdrop-filter: blur does not
     usefully nest (the child samples the parent's composited result) and a
     scrolling list of blurred layers is a real GPU cost for no visual gain.
     This is the documented exception to the density rule above — alert
     cards are short, high-contrast, and never a wall of small numerics. */
  --surface-card:       rgba(255, 255, 255, 0.10);
  --surface-card-scrim: rgba(8, 12, 22, 0.28);
  --glass-border:    rgba(255, 255, 255, 0.09);
  --glass-border-strong: rgba(255, 255, 255, 0.16);
  --glass-highlight: rgba(255, 255, 255, 0.11);
  --glass-lowlight:  rgba(0, 0, 0, 0.28);
  --glass-sheen:     rgba(255, 255, 255, 0.11);
  --hairline:        rgba(255, 255, 255, 0.08);

  /* Tinted, layered shadows — single light source from above */
  --shadow-sm: 0 1px 2px rgba(2, 5, 12, 0.5), 0 2px 8px rgba(2, 5, 12, 0.35);
  --shadow-md: 0 2px 4px rgba(2, 5, 12, 0.45), 0 12px 32px rgba(2, 5, 12, 0.45);
  --shadow-lg: 0 4px 8px rgba(2, 5, 12, 0.4), 0 28px 70px rgba(2, 5, 12, 0.6);
  --shadow-raised: 0 1px 2px rgba(2, 5, 12, 0.6), 0 4px 12px rgba(2, 5, 12, 0.35);
  --inset-top: inset 0 1px 0 var(--glass-highlight);
  --inset-edge: inset 0 1px 0 var(--glass-highlight), inset 0 -1px 0 var(--glass-lowlight);

  /* Status semantics — graphic tone + accessible ink for text */
  --color-accent:      #38bdf8;   /* blue   — interactive */
  --color-accent-ink:  #7dd3fc;
  --color-on-accent:   #04121f;
  --color-accent-2:    #0ea5e9;

  --color-nominal:     #22c55e;   /* green  — nominal / confirmed */
  --color-nominal-ink: #4ade80;

  --color-warning:     #f59e0b;   /* amber  — needs review */
  --color-warning-ink: #fbbf24;

  /* Critical red is deliberately the most saturated tone in the system —
     against translucent surfaces a desaturated red disappears, and "critical"
     must be legible at a glance from across a fab floor. Graphic tone is
     full-chroma; the ink is lifted just enough to clear 4.5:1 on glass. */
  --color-critical:    #ff453a;   /* red    — critical / low confidence */
  --color-critical-ink:#ff7a70;

  --color-market:      #c084fc;   /* violet — live web sources */
  --color-market-ink:  #d8b4fe;
  --color-on-market:   #1a0b2e;

  --color-ring: #60a5fa;
  --scrollbar-thumb: rgba(255, 255, 255, 0.16);
  --scrollbar-thumb-hover: rgba(255, 255, 255, 0.28);
}

/* ---------------------------------------------------------------------------
   3. Tokens — light theme
   ------------------------------------------------------------------------ */
:root[data-theme="light"] {
  color-scheme: light;

  --color-background: #e9edf5;
  --color-foreground: #10192b;
  --color-muted-foreground: #55637d;
  --color-faint-foreground: #7b879c;

  --amb-1: rgba(56, 189, 248, 0.14);
  --amb-3: rgba(124, 58, 237, 0.13);

  --glass-bg:        rgba(255, 255, 255, 0.58);
  --glass-bg-strong: rgba(255, 255, 255, 0.80);
  --glass-solid:     rgba(255, 255, 255, 0.93);
  --glass-well:      rgba(255, 255, 255, 0.40);
  --glass-inset:     rgba(15, 23, 42, 0.05);
  --glass-raised:    rgba(255, 255, 255, 0.95);
  /* Light theme glass is brighter, not darker: the card lifts toward white
     while still letting the ambient field through underneath. */
  --surface-card:       rgba(255, 255, 255, 0.62);
  --surface-card-scrim: rgba(255, 255, 255, 0.30);
  --glass-border:    rgba(15, 23, 42, 0.10);
  --glass-border-strong: rgba(15, 23, 42, 0.20);
  --glass-highlight: rgba(255, 255, 255, 0.85);
  --glass-lowlight:  rgba(15, 23, 42, 0.05);
  --glass-sheen:     rgba(255, 255, 255, 0.55);
  --hairline:        rgba(15, 23, 42, 0.09);

  --shadow-sm: 0 1px 2px rgba(23, 40, 74, 0.08), 0 2px 8px rgba(23, 40, 74, 0.06);
  --shadow-md: 0 2px 4px rgba(23, 40, 74, 0.07), 0 12px 32px rgba(23, 40, 74, 0.11);
  --shadow-lg: 0 4px 8px rgba(23, 40, 74, 0.08), 0 28px 70px rgba(23, 40, 74, 0.18);
  --shadow-raised: 0 1px 2px rgba(23, 40, 74, 0.12), 0 4px 12px rgba(23, 40, 74, 0.12);
  --inset-top: inset 0 1px 0 var(--glass-highlight);
  --inset-edge: inset 0 1px 0 var(--glass-highlight), inset 0 -1px 0 var(--glass-lowlight);

  --color-accent:      #0369a1;
  --color-accent-ink:  #075985;
  --color-on-accent:   #ffffff;
  /* Darker companion to --color-accent. Filled surfaces are solid now (the
     downward shade was decorative, not informative); this remains for hover
     and pressed states, where a real state change justifies the shift. */
  --color-accent-2:    #075985;

  --color-nominal:     #15803d;
  --color-nominal-ink: #14653a;

  --color-warning:     #b45309;
  --color-warning-ink: #92400e;

  --color-critical:    #ff3b30;
  --color-critical-ink:#d70015;

  --color-market:      #7c3aed;
  --color-market-ink:  #6d28d9;
  --color-on-market:   #ffffff;

  --color-ring: #0369a1;
  --scrollbar-thumb: rgba(15, 23, 42, 0.20);
  --scrollbar-thumb-hover: rgba(15, 23, 42, 0.34);
}

/* ---------------------------------------------------------------------------
   4. Base
   ------------------------------------------------------------------------ */
* { box-sizing: border-box; }

/* Any element using the `hidden` attribute must actually hide, even when a
   later rule sets display:flex/grid on the same element (classic footgun). */
[hidden] { display: none !important; }

html {
  height: 100%;
  background: var(--color-background);
}

body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  background: transparent;
  color: var(--color-foreground);
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  transition: color var(--transition-slow);
}

/* The ambient field. Two soft, off-axis colour pools so the glass surfaces
   above have something to refract.
   Deliberately restrained: this was five stacked radial gradients under a
   30px blur, on a permanent 52s transform loop. That read as decoration
   rather than material — five overlapping hues muddied into a purple wash
   behind every screen — and it cost a continuous full-viewport GPU repaint
   for an effect almost nobody consciously registers. Two pools at lower
   opacity give the same sense of depth; the drift is gone, not merely
   slowed, so an idle tab does no compositing work at all. */
body::before {
  content: "";
  position: fixed;
  inset: -10%;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(46% 48% at 12% 6%,  var(--amb-1), transparent 70%),
    radial-gradient(50% 46% at 86% 92%, var(--amb-3), transparent 72%);
  filter: blur(40px);
  transition: opacity var(--transition-slow);
}

.mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
  letter-spacing: -0.01em;
}

h1, h2, h3 { font-weight: 600; margin: 0; letter-spacing: -0.015em; text-wrap: balance; }
p { text-wrap: pretty; }

/* Fixed-height app shell — the page itself never scrolls. Only regions
   explicitly marked `.scroll` scroll, each independently. */
.screen {
  position: relative;
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* ---------------------------------------------------------------------------
   5. Focus, motion, accessibility
   ------------------------------------------------------------------------ */
:focus-visible {
  outline: 2px solid var(--color-ring);
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

.skip-link {
  position: absolute; left: -999px; top: 0; z-index: var(--z-skip);
  background: var(--color-accent); color: var(--color-on-accent);
  padding: 0.65rem 1.1rem; border-radius: 0 0 var(--r-md) 0;
  font-weight: 600; font-size: 0.85rem; box-shadow: var(--shadow-md);
}
.skip-link:focus { left: 0; }

.ph { font-size: 1.05em; line-height: 1; vertical-align: -0.12em; }
.ph-spin { animation: dp-spin 1s linear infinite; display: inline-block; }
@keyframes dp-spin { to { transform: rotate(360deg); } }

/* Shared status inks — used inline by app.js in chat, tables and uploads */
.ok  { color: var(--color-nominal-ink); }
.err { color: var(--color-critical-ink); }

/* ---------------------------------------------------------------------------
   6. Scrollbars
   ------------------------------------------------------------------------ */
.scroll, .admin-main, .rca-result, .doc-registry, .modal-glass {
  scrollbar-width: thin;
  scrollbar-color: var(--scrollbar-thumb) transparent;
}
.scroll::-webkit-scrollbar,
.admin-main::-webkit-scrollbar,
.rca-result::-webkit-scrollbar,
.doc-registry::-webkit-scrollbar,
.modal-glass::-webkit-scrollbar { width: 10px; height: 10px; }
.scroll::-webkit-scrollbar-thumb,
.admin-main::-webkit-scrollbar-thumb,
.rca-result::-webkit-scrollbar-thumb,
.doc-registry::-webkit-scrollbar-thumb,
.modal-glass::-webkit-scrollbar-thumb {
  background: var(--scrollbar-thumb);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: var(--r-pill);
}
.scroll::-webkit-scrollbar-thumb:hover,
.admin-main::-webkit-scrollbar-thumb:hover { background: var(--scrollbar-thumb-hover); background-clip: content-box; }

/* ---------------------------------------------------------------------------
   7. Theme switch — a three-way appearance picker (Light / Auto / Dark),
      modelled on the macOS System Settings appearance control rather than a
      sun-moon toggle. Present on every screen: login, app, admin.
   ------------------------------------------------------------------------ */
.theme-switch {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border-radius: var(--r-pill);
  background: var(--glass-inset);
  border: 1px solid var(--glass-border);
  backdrop-filter: var(--glass-filter-light);
  -webkit-backdrop-filter: var(--glass-filter-light);
  box-shadow: var(--inset-top);
}
.theme-opt {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 26px; padding: 0;
  border: none; background: transparent; cursor: pointer;
  border-radius: var(--r-pill);
  color: var(--color-muted-foreground);
  font-size: 0.9rem;
  transition: background var(--transition), color var(--transition), transform var(--transition), box-shadow var(--transition);
}
.theme-opt:hover { color: var(--color-foreground); }
.theme-opt:active { transform: scale(0.92); }
.theme-opt[aria-pressed="true"] {
  background: var(--glass-raised);
  color: var(--color-foreground);
  box-shadow: var(--shadow-raised), var(--inset-top);
}

/* ---------------------------------------------------------------------------
   8. Login
   ------------------------------------------------------------------------ */
#login-screen { align-items: center; justify-content: center; padding: var(--sp-6); }

#login-screen .theme-switch { position: absolute; top: var(--sp-6); right: var(--sp-6); }

.login-card {
  position: relative;
  width: 400px;
  max-width: 100%;
  padding: var(--sp-10) var(--sp-8) var(--sp-8);
  border-radius: var(--r-xl);
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-filter);
  -webkit-backdrop-filter: var(--glass-filter);
  border: 1px solid var(--glass-border);
  box-shadow: var(--shadow-lg), var(--inset-edge);
  animation: dp-rise 560ms var(--ease-out) both;
  overflow: hidden;
}
/* Specular sheen along the top edge — simulated edge refraction */
.login-card::before {
  content: "";
  position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: linear-gradient(175deg, var(--glass-sheen) 0%, transparent 38%);
}
.login-card > * { position: relative; }

@keyframes dp-rise {
  from { opacity: 0; transform: translateY(14px) scale(0.985); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.brand { display: flex; align-items: center; gap: var(--sp-4); margin-bottom: var(--sp-8); }
.brand-mark {
  display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; flex-shrink: 0;
}
.brand-mark img { width: 100%; height: 100%; filter: drop-shadow(0 2px 10px rgba(255, 138, 28, 0.4)); }
.brand-name { font-weight: 700; letter-spacing: 0.08em; font-size: 1.18rem; line-height: 1.2; }
.brand-sub { color: var(--color-muted-foreground); font-size: 0.74rem; margin-top: 0.2rem; }

#login-form label {
  display: block; margin-bottom: var(--sp-5);
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--color-muted-foreground);
}
#login-form input {
  display: block; width: 100%; margin-top: var(--sp-2);
  padding: 0.7rem 0.85rem;
  background: var(--glass-inset);
  border: 1px solid var(--glass-border);
  border-radius: var(--r-sm);
  color: var(--color-foreground);
  font-size: 0.92rem; font-family: var(--font-sans); font-weight: 500;
  letter-spacing: normal; text-transform: none;
  box-shadow: inset 0 1px 2px var(--glass-lowlight);
  transition: border-color var(--transition), background var(--transition), box-shadow var(--transition);
}
#login-form input:focus {
  border-color: var(--color-accent);
  background: var(--glass-bg);
  box-shadow: inset 0 1px 2px var(--glass-lowlight), 0 0 0 3px color-mix(in srgb, var(--color-accent) 22%, transparent);
}
#login-form input::placeholder { color: var(--color-faint-foreground); }

.login-footnote {
  color: var(--color-faint-foreground); font-size: 0.72rem;
  margin: var(--sp-7) 0 0; text-align: center;
}
.error-text {
  color: var(--color-critical-ink); font-size: 0.8rem; margin: var(--sp-3) 0 0;
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 0.5rem 0.7rem; border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--color-critical) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-critical) 30%, transparent);
}

/* ---------------------------------------------------------------------------
   9. Buttons
   ------------------------------------------------------------------------ */
.btn-primary,
#login-form button,
.query-form button {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  border: none; cursor: pointer;
  border-radius: var(--r-sm);
  font-family: var(--font-sans); font-weight: 600; font-size: 0.88rem;
  color: var(--color-on-accent);
  background: var(--color-accent);
  box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.18);
  transition: transform var(--transition), filter var(--transition), box-shadow var(--transition);
}
.btn-primary, #login-form button {
  width: 100%; padding: 0.72rem 1rem; margin-top: var(--sp-3);
}
.query-form button { align-self: flex-start; padding: 0.55rem 1.4rem; }

.btn-primary:hover,
#login-form button:hover,
.query-form button:hover {
  filter: brightness(1.07) saturate(1.05);
  transform: translateY(-1px);
  box-shadow: var(--shadow-md), inset 0 1px 0 rgba(255, 255, 255, 0.3);
}
.btn-primary:active,
#login-form button:active,
.query-form button:active { transform: translateY(0) scale(0.985); filter: brightness(0.97); }

.ghost-btn {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  background: var(--glass-inset);
  border: 1px solid var(--glass-border);
  color: var(--color-foreground);
  padding: 0.42rem 0.9rem;
  border-radius: var(--r-sm);
  cursor: pointer; font-size: 0.8rem; font-weight: 500;
  font-family: var(--font-sans);
  backdrop-filter: var(--glass-filter-light);
  -webkit-backdrop-filter: var(--glass-filter-light);
  box-shadow: var(--inset-top);
  transition: background var(--transition), border-color var(--transition),
              transform var(--transition), box-shadow var(--transition), color var(--transition);
}
.ghost-btn:hover {
  background: var(--glass-raised);
  border-color: var(--glass-border-strong);
  transform: translateY(-1px);
  box-shadow: var(--shadow-raised), var(--inset-top);
}
.ghost-btn:active { transform: scale(0.97); }

.link-btn {
  background: none; border: none; padding: 0; margin: 0;
  font-family: var(--font-mono, monospace); font-size: inherit;
  color: var(--color-accent-ink); cursor: pointer; text-align: left;
  text-decoration: underline; text-decoration-color: transparent;
  transition: text-decoration-color var(--transition), color var(--transition);
}
.link-btn:hover { text-decoration-color: currentColor; color: var(--color-accent); }
.ghost-btn.danger:hover {
  border-color: color-mix(in srgb, var(--color-critical) 55%, transparent);
  color: var(--color-critical-ink);
  background: color-mix(in srgb, var(--color-critical) 12%, transparent);
}

.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: var(--r-sm);
  background: var(--glass-inset); border: 1px solid var(--glass-border);
  color: var(--color-foreground); cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}
.icon-btn:hover { background: var(--glass-raised); border-color: var(--color-accent); }

/* ---------------------------------------------------------------------------
   10. Top bar — the primary glass chrome
   ------------------------------------------------------------------------ */
.topbar {
  position: sticky; top: 0; z-index: var(--z-chrome);
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-4);
  padding: 0.6rem 1.35rem;
  min-height: 64px; max-height: 64px;
  background: var(--glass-bg);
  backdrop-filter: var(--glass-filter);
  -webkit-backdrop-filter: var(--glass-filter);
  border-bottom: 1px solid var(--hairline);
  box-shadow: 0 1px 0 var(--glass-highlight) inset, var(--shadow-sm);
}

.logo {
  display: flex; align-items: center; gap: var(--sp-3);
  font-weight: 700; letter-spacing: 0.06em; font-size: 0.98rem;
  cursor: pointer; background: transparent; border: none;
  color: var(--color-foreground);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  font-family: var(--font-sans);
  transition: background var(--transition), transform var(--transition);
}
.logo:hover { background: var(--glass-inset); }
.logo:active { transform: scale(0.98); }
.logo .brand-mark { width: 30px; height: 30px; }

/* iOS-style segmented control: recessed glass track, raised active pill */
.mode-toggle {
  display: flex; gap: 3px;
  padding: 3px;
  border-radius: var(--r-pill);
  background: var(--glass-inset);
  border: 1px solid var(--glass-border);
  box-shadow: inset 0 1px 3px var(--glass-lowlight);
}
.mode-btn {
  display: flex; align-items: center; gap: var(--sp-2);
  background: transparent; border: none;
  color: var(--color-muted-foreground);
  padding: 0.42rem 1.05rem;
  border-radius: var(--r-pill);
  cursor: pointer; font-size: 0.84rem; font-weight: 500;
  font-family: var(--font-sans); white-space: nowrap;
  transition: background var(--transition), color var(--transition),
              box-shadow var(--transition), transform var(--transition);
}
.mode-btn:hover { color: var(--color-foreground); }
.mode-btn:active { transform: scale(0.97); }
.mode-btn.active {
  background: var(--color-accent);
  color: var(--color-on-accent);
  font-weight: 600;
  box-shadow: var(--shadow-raised), inset 0 1px 0 rgba(255, 255, 255, 0.18);
}
/* Market stays unmistakable in both themes — violet fill, never blue */
.mode-btn[data-mode="market"].active {
  background: var(--color-market);
  color: var(--color-on-market);
}

.user-box {
  display: flex; align-items: center; gap: var(--sp-3);
  font-size: 0.8rem; color: var(--color-muted-foreground);
}
#user-display {
  padding: 0.3rem 0.7rem;
  border-radius: var(--r-pill);
  background: var(--glass-inset);
  border: 1px solid var(--glass-border);
  font-size: 0.74rem;
  white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   11. Market banner — persistent, violet, unmistakable in both themes
   ------------------------------------------------------------------------ */
.market-banner {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
  padding: 0.55rem var(--sp-4);
  font-size: 0.82rem; font-weight: 500; text-align: center;
  color: var(--color-market-ink);
  background: color-mix(in srgb, var(--color-market) 14%, transparent);
  backdrop-filter: var(--glass-filter-light);
  -webkit-backdrop-filter: var(--glass-filter-light);
  border-bottom: 1px solid color-mix(in srgb, var(--color-market) 38%, transparent);
  box-shadow: inset 0 1px 0 var(--glass-highlight);
  animation: dp-slide-down 320ms var(--ease-out);
}
@keyframes dp-slide-down {
  from { opacity: 0; transform: translateY(-8px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---------------------------------------------------------------------------
   12. Layout
   ------------------------------------------------------------------------ */
.main-area { flex: 1; overflow: hidden; min-height: 0; }
.workspace { display: flex; height: 100%; min-height: 0; position: relative; }

.sidebar,
.sessions-sidebar {
  width: 288px; flex-shrink: 0;
  padding: var(--sp-5) var(--sp-4);
  display: flex; flex-direction: column; min-height: 0;
  background: var(--glass-bg);
  backdrop-filter: var(--glass-filter);
  -webkit-backdrop-filter: var(--glass-filter);
  border-right: 1px solid var(--hairline);
  box-shadow: inset -1px 0 0 var(--glass-highlight);
  overflow: hidden; /* clips the content instead of letting it spill past the
    shrinking box while width/padding animate to 0 on collapse. */
  transition: width var(--transition-slow), padding var(--transition-slow),
              max-height var(--transition-slow), opacity var(--transition),
              transform var(--transition-slow), border-color var(--transition);
}
/* Collapsed: width -> 0 in the row layout so `.content` reclaims the space
   (not visibility/opacity alone, which would leave the flex track intact),
   and max-height -> 0 too so the same rule also collapses the stacked
   layout at <=1000px, where the sidebar's cross axis is height, not width. */
.sidebar.collapsed,
.sessions-sidebar.collapsed {
  width: 0; max-height: 0;
  padding-top: 0; padding-bottom: 0; padding-left: 0; padding-right: 0;
  border: none; box-shadow: none;
  opacity: 0;
  transform: translateX(-24px);
  pointer-events: none;
}
.sidebar-title {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
  font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--color-muted-foreground); font-weight: 600;
  margin-bottom: var(--sp-4); flex-shrink: 0;
}
.sidebar-title-text { display: flex; align-items: center; gap: var(--sp-2); min-width: 0; }
.sidebar-title .ph { color: var(--color-warning); font-size: 0.95rem; }
.sessions-sidebar .sidebar-title .ph { color: var(--color-accent); }

.alerts-collapse-btn {
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  width: 22px; height: 22px; padding: 0;
  border-radius: var(--r-xs);
  border: 1px solid transparent;
  background: transparent;
  color: var(--color-muted-foreground);
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), color var(--transition);
}
.alerts-collapse-btn:hover {
  background: var(--glass-raised);
  border-color: var(--glass-border);
  color: var(--color-foreground);
}
.alerts-collapse-btn .ph { color: inherit; font-size: 0.85rem; }

/* Restore rail — a slim tab flush to the left edge of the Manufacturing
   workspace, shown only while the sidebar is collapsed. Anchored to
   #workspace-mfg (position: relative, set alongside .workspace below) so it
   stays put regardless of the row/column layout switch at the responsive
   breakpoint. */
.alerts-restore-btn {
  position: absolute; left: 0; top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-1);
  padding: var(--sp-3) var(--sp-2);
  border: 1px solid var(--glass-border);
  border-left: none;
  border-radius: 0 var(--r-lg) var(--r-lg) 0;
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-filter);
  -webkit-backdrop-filter: var(--glass-filter);
  box-shadow: var(--shadow-md);
  color: var(--color-foreground);
  cursor: pointer;
  transition: background var(--transition), transform var(--transition), box-shadow var(--transition);
}
.alerts-restore-btn:hover {
  background: var(--glass-raised);
  box-shadow: var(--shadow-lg);
  transform: translateY(-50%) translateX(3px);
}
.alerts-restore-btn .ph-bold { color: var(--color-warning); font-size: 1.05rem; }
.alerts-restore-count {
  font-size: 0.68rem; font-weight: 600;
  min-width: 1.2em;
  padding: 0.05rem 0.4rem; border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--color-critical) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-critical) 34%, transparent);
  color: var(--color-critical-ink);
}
/* Nothing queued: same shape, neutral tone rather than the alert-red tint. */
.alerts-restore-count.zero {
  background: var(--glass-inset);
  border-color: var(--glass-border);
  color: var(--color-muted-foreground);
}

/* Every workspace column shares one measure. Manufacturing had no max-width
   at all, so on a wide monitor its Ask box and answer cards stretched the
   full remaining width beside the sidebar while Documents and Market (which
   did set one) stayed centred -- switching tabs visibly reflowed the page.
   `.full` is retained as a no-op alias for the two panels that carry it. */
.content {
  flex: 1; min-width: 0; min-height: 0; overflow: hidden;
  display: flex; flex-direction: column; gap: var(--sp-4);
  padding: var(--sp-6);
  width: 100%; max-width: var(--measure-column); margin-inline: auto;
}
.content.full { max-width: var(--measure-column); }

/* Independently scrollable region — never the page itself. min-height: 0
   is required alongside flex: 1 so the box actually shrinks and scrolls
   instead of stretching its flex-column ancestors past the viewport
   (the cause of the whole-page-scrolls-with-the-sidebar bug). */
.scroll { overflow-y: auto; min-height: 0; }

/* ---------------------------------------------------------------------------
   13. Alerts sidebar
   ------------------------------------------------------------------------ */
.alerts-list { flex: 1; min-height: 0; display: flex; flex-direction: column; gap: var(--sp-2); padding-right: 2px; }

.alert-item {
  position: relative;
  padding: 0.6rem 0.75rem 0.6rem 0.9rem;
  border-radius: var(--r-md);
  background:
    linear-gradient(var(--surface-card-scrim), var(--surface-card-scrim)),
    var(--surface-card);
  border: 1px solid var(--glass-border);
  box-shadow: var(--shadow-sm), var(--inset-top);
  font-size: 0.78rem; cursor: pointer;
  flex-shrink: 0;
  transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
}
/* Severity is carried by a soft inner rail, not a hard slab border */
.alert-item::before {
  content: ""; position: absolute; left: 0; top: 10px; bottom: 10px; width: 3px;
  border-radius: var(--r-pill);
  background: var(--color-warning);
  box-shadow: 0 0 8px color-mix(in srgb, var(--color-warning) 55%, transparent);
}
.alert-item:hover {
  transform: translateY(-1px);
  border-color: var(--glass-border-strong);
  box-shadow: var(--shadow-md), var(--inset-top);
}
.alert-item:active { transform: scale(0.99); }
/* Critical alerts carry their severity permanently, not only while unseen:
   a tinted surface and a saturated border, so "red" is unmistakable in a
   scanned list even after the pulse has been dismissed. */
.alert-item.red {
  background: color-mix(in srgb, var(--color-critical) 8%, var(--surface-card));
  border-color: color-mix(in srgb, var(--color-critical) 36%, transparent);
}
.alert-item.red::before {
  width: 4px;
  background: var(--color-critical);
  box-shadow: 0 0 10px color-mix(in srgb, var(--color-critical) 70%, transparent);
}
.alert-item.red:hover { border-color: color-mix(in srgb, var(--color-critical) 55%, transparent); }

/* Unseen critical alerts breathe. Deliberately not a strobe: one slow
   expansion per 2.6s on a decelerating curve, so it reads as a pulse of
   light rather than a blinking alarm lamp. Two coordinated layers — an
   expanding halo off the card and a widening glow on the severity rail —
   give it presence at a glance without any hard on/off frame. */
.alert-item.red.pulse {
  animation: dp-alert-pulse 2.6s cubic-bezier(0.33, 0, 0.2, 1) infinite;
}
@keyframes dp-alert-pulse {
  0% {
    box-shadow: var(--shadow-sm), var(--inset-top),
                0 0 0 0 color-mix(in srgb, var(--color-critical) 60%, transparent);
    border-color: color-mix(in srgb, var(--color-critical) 70%, transparent);
    background: color-mix(in srgb, var(--color-critical) 15%, var(--surface-card));
  }
  70% {
    box-shadow: var(--shadow-sm), var(--inset-top),
                0 0 0 14px color-mix(in srgb, var(--color-critical) 0%, transparent);
    border-color: color-mix(in srgb, var(--color-critical) 28%, transparent);
    background: color-mix(in srgb, var(--color-critical) 7%, var(--surface-card));
  }
  100% {
    /* Halo is fully transparent here, so collapsing the spread back to 0 is
       invisible — the loop restarts without a seam. */
    box-shadow: var(--shadow-sm), var(--inset-top),
                0 0 0 0 color-mix(in srgb, var(--color-critical) 0%, transparent);
    border-color: color-mix(in srgb, var(--color-critical) 70%, transparent);
    background: color-mix(in srgb, var(--color-critical) 15%, var(--surface-card));
  }
}
.alert-item.red.pulse::before {
  transform-origin: left center;
  animation: dp-alert-rail 2.6s cubic-bezier(0.33, 0, 0.2, 1) infinite;
}
@keyframes dp-alert-rail {
  0%, 100% { transform: scaleX(1);   box-shadow: 0 0 10px color-mix(in srgb, var(--color-critical) 70%, transparent); }
  45%      { transform: scaleX(1.9); box-shadow: 0 0 22px color-mix(in srgb, var(--color-critical) 95%, transparent); }
}
.alert-item .alert-param {
  display: flex; align-items: center; gap: var(--sp-2);
  color: var(--color-accent-ink); font-size: 0.76rem; font-weight: 500;
}
.alert-item.red .alert-param { color: var(--color-critical-ink); }
.alert-item .alert-meta {
  color: var(--color-muted-foreground); font-size: 0.7rem; margin-top: var(--sp-1);
  font-family: var(--font-mono);
}

.empty-note {
  color: var(--color-muted-foreground); font-size: 0.82rem;
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3) 0;
}
.empty-note.err { color: var(--color-critical-ink); }

/* ---------------------------------------------------------------------------
   14. Upload
   ------------------------------------------------------------------------ */
.upload-row { display: flex; flex-direction: column; gap: var(--sp-3); flex-shrink: 0; }

.drop-zone {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-3);
  padding: var(--sp-6);
  border-radius: var(--r-lg);
  border: 1.5px dashed var(--glass-border-strong);
  background: var(--glass-well);
  backdrop-filter: var(--glass-filter-light);
  -webkit-backdrop-filter: var(--glass-filter-light);
  color: var(--color-muted-foreground);
  cursor: pointer; font-size: 0.85rem; text-align: center;
  transition: border-color var(--transition), background var(--transition),
              color var(--transition), transform var(--transition), box-shadow var(--transition);
}
.drop-zone:hover, .drop-zone.dragover {
  border-color: var(--color-accent);
  color: var(--color-foreground);
  background: color-mix(in srgb, var(--color-accent) 10%, var(--glass-well));
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}
.drop-zone.dragover { border-style: solid; }
.drop-zone .ph { font-size: 1.45rem; color: var(--color-accent); }

.upload-status {
  font-size: 0.76rem; color: var(--color-muted-foreground);
  font-family: var(--font-mono); min-height: 1.2em;
  display: flex; flex-direction: column; gap: var(--sp-1);
}
.upload-row-item { line-height: 1.6; }

/* ---------------------------------------------------------------------------
   15. Tabs, forms, chat
   ------------------------------------------------------------------------ */
/* Tab pill on the left, destructive action on the right. The pill keeps
   holding only tabs — a "Clear chat" button inside it would read as a fourth
   tab and inherit the selected-tab styling. */
.toolbar-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3); flex-wrap: wrap; flex-shrink: 0;
}

.query-toolbar {
  display: inline-flex; gap: 3px; padding: 3px;
  border-radius: var(--r-pill);
  background: var(--glass-inset);
  border: 1px solid var(--glass-border);
  box-shadow: inset 0 1px 3px var(--glass-lowlight);
  align-self: flex-start; flex-shrink: 0;
}
.tab-btn {
  display: flex; align-items: center; gap: var(--sp-2);
  background: transparent; border: none;
  color: var(--color-muted-foreground);
  padding: 0.4rem 1rem;
  border-radius: var(--r-pill);
  cursor: pointer; font-size: 0.82rem; font-weight: 500;
  font-family: var(--font-sans);
  transition: color var(--transition), background var(--transition),
              box-shadow var(--transition), transform var(--transition);
}
.tab-btn:hover { color: var(--color-foreground); }
.tab-btn:active { transform: scale(0.97); }
.tab-btn.active {
  color: var(--color-foreground); font-weight: 600;
  background: var(--glass-raised);
  box-shadow: var(--shadow-raised), var(--inset-top);
}

.query-form { display: flex; flex-direction: column; gap: var(--sp-3); flex-shrink: 0; }
.query-form textarea {
  padding: 0.75rem 0.9rem;
  border-radius: var(--r-md);
  background: var(--glass-solid);
  border: 1px solid var(--glass-border);
  color: var(--color-foreground);
  font-size: 0.88rem; font-family: var(--font-sans);
  min-height: 3.2rem; resize: vertical;
  box-shadow: inset 0 1px 2px var(--glass-lowlight);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.query-form textarea:focus {
  border-color: var(--color-accent);
  box-shadow: inset 0 1px 2px var(--glass-lowlight), 0 0 0 3px color-mix(in srgb, var(--color-accent) 20%, transparent);
}
.query-form textarea::placeholder { color: var(--color-faint-foreground); }

.rca-scope-row { display: flex; gap: var(--sp-3); flex-wrap: wrap; }
.rca-scope-row input, .rca-scope-row select {
  padding: 0.48rem 0.7rem;
  border-radius: var(--r-sm);
  background: var(--glass-solid);
  border: 1px solid var(--glass-border);
  color: var(--color-foreground);
  font-size: 0.8rem; font-family: var(--font-sans);
  box-shadow: inset 0 1px 2px var(--glass-lowlight);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.rca-scope-row input::placeholder { color: var(--color-faint-foreground); }
.rca-scope-row input:focus, .rca-scope-row select:focus {
  border-color: var(--color-accent);
  box-shadow: inset 0 1px 2px var(--glass-lowlight), 0 0 0 3px color-mix(in srgb, var(--color-accent) 20%, transparent);
}

/* Recessed "well" material — shared by every sunken content region (chat,
   RCA results, doc registry). One declaration instead of three copies: a
   well is a well, whichever panel it sits inside of. Each caller only adds
   its own layout (flex vs scroll, padding). Not another sheet of glass —
   stacking blur on blur washes the type out; the bubbles/rows inside carry
   the material instead. */
.chat-panel, .rca-result, .doc-registry {
  flex: 1; min-height: 0;
  border-radius: var(--r-lg);
  background: var(--glass-well);
  border: 1px solid var(--hairline);
  box-shadow: inset 0 1px 3px var(--glass-lowlight);
}
.chat-panel {
  display: flex; flex-direction: column; gap: var(--sp-3);
  padding: var(--sp-4);
}

/* Composed empty state — app.js appends children, so `:empty` is an exact
   proxy for "no messages yet" without any JS coupling. */
.chat-panel:empty::before {
  content: "Answers appear here, each with its citations and a confidence badge.";
  margin: auto;
  max-width: 34ch;
  text-align: center;
  font-size: 0.84rem;
  color: var(--color-faint-foreground);
}

.msg {
  /* Percentage alone let an answer run ~1030px on a wide column -- far past a
     comfortable line length. Whichever limit binds first wins, so narrow
     viewports still get the percentage behaviour. */
  max-width: min(78%, 82ch);
  position: relative;
  padding: 0.7rem 0.95rem;
  border-radius: var(--r-md);
  font-size: 0.87rem; line-height: 1.6;
  animation: dp-msg-in 340ms var(--ease-out) both;
}
@keyframes dp-msg-in {
  from { opacity: 0; transform: translateY(8px) scale(0.99); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.msg.user {
  align-self: flex-end;
  background: var(--color-accent);
  color: var(--color-on-accent);
  box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.16);
  border-bottom-right-radius: var(--r-xs);
}
.msg.assistant {
  align-self: flex-start;
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-filter);
  -webkit-backdrop-filter: var(--glass-filter);
  border: 1px solid var(--glass-border);
  box-shadow: var(--shadow-sm), var(--inset-top);
  border-bottom-left-radius: var(--r-xs);
}
.msg.assistant.needs-review {
  border-color: color-mix(in srgb, var(--color-warning) 55%, transparent);
  box-shadow: var(--shadow-sm), var(--inset-top), 0 0 0 1px color-mix(in srgb, var(--color-warning) 22%, transparent);
}

.confidence-badge {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  font-family: var(--font-mono); font-size: 0.68rem; font-weight: 500;
  padding: 0.18rem 0.55rem;
  border-radius: var(--r-pill);
  margin-top: var(--sp-2);
  white-space: nowrap;
  color: var(--color-nominal-ink);
  background: color-mix(in srgb, var(--color-nominal) 15%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-nominal) 32%, transparent);
}
.confidence-badge.review {
  color: var(--color-warning-ink);
  background: color-mix(in srgb, var(--color-warning) 15%, transparent);
  border-color: color-mix(in srgb, var(--color-warning) 34%, transparent);
}
.confidence-badge.low {
  color: var(--color-critical-ink);
  background: color-mix(in srgb, var(--color-critical) 15%, transparent);
  border-color: color-mix(in srgb, var(--color-critical) 34%, transparent);
}

.citations { margin-top: var(--sp-2); display: flex; flex-wrap: wrap; gap: var(--sp-2); }
/* One chip per source document: filename, then the locators it contributed.
   Wide enough that two long spreadsheet names are distinguishable -- at the
   old fixed 230px every name in this corpus truncated to the same prefix. */
.citation-chip {
  display: inline-flex; align-items: baseline; gap: var(--sp-2);
  max-width: 100%; min-width: 0;
  font-family: var(--font-mono); font-size: 0.67rem;
  padding: 0.2rem 0.55rem;
  border-radius: var(--r-xs);
  background: var(--glass-inset);
  border: 1px solid var(--glass-border);
  color: var(--color-muted-foreground);
  cursor: default;
  transition: color var(--transition), border-color var(--transition);
}
.citation-source {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--color-foreground); min-width: 0;
}
.citation-locators { flex-shrink: 0; color: var(--color-faint-foreground); }
.citation-chip:hover { color: var(--color-foreground); border-color: var(--glass-border-strong); }

/* ---------------------------------------------------------------------------
   16. RCA
   ------------------------------------------------------------------------ */
.rca-result { overflow-y: auto; padding: var(--sp-5); }
.rca-dominant {
  display: flex; align-items: center; gap: var(--sp-3); flex-wrap: wrap;
  font-size: 1rem; margin-bottom: var(--sp-5);
}
.rca-dominant .ph { color: var(--color-accent); }
.rca-dominant .cause { color: var(--color-accent-ink); font-weight: 700; }

.rca-bars { display: flex; flex-direction: column; gap: var(--sp-3); margin-bottom: var(--sp-6); }
.rca-bar-row {
  display: grid; grid-template-columns: 116px 1fr 52px;
  align-items: center; gap: var(--sp-3); font-size: 0.82rem;
}
.rca-bar-track {
  height: 14px; border-radius: var(--r-pill); overflow: hidden;
  background: var(--glass-inset);
  box-shadow: inset 0 1px 2px var(--glass-lowlight);
}
.rca-bar-fill {
  height: 100%; border-radius: var(--r-pill);
  background: var(--color-accent);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2);
  transition: width 620ms var(--ease-out);
}
.rca-bar-fill.dominant {
  background: var(--color-nominal);
}
.rca-reasoning { color: var(--color-muted-foreground); font-size: 0.86rem; line-height: 1.7; max-width: 74ch; }
.rca-evidence-table th, .rca-evidence-table td { font-size: 0.76rem; }

.rca-action {
  margin-top: var(--sp-5);
  padding: var(--sp-4) var(--sp-5);
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--color-nominal) 10%, var(--surface-card));
  border: 1px solid color-mix(in srgb, var(--color-nominal) 30%, transparent);
  box-shadow: var(--shadow-sm), var(--inset-top);
  font-size: 0.86rem; display: flex; gap: var(--sp-3); align-items: flex-start;
}
.rca-action .ph { color: var(--color-nominal-ink); font-size: 1.15rem; flex-shrink: 0; margin-top: 0.15rem; }

/* ---------------------------------------------------------------------------
   17. Tables — glass sheets with hairline rules
   ------------------------------------------------------------------------ */
.data-table {
  width: 100%;
  border-collapse: separate; border-spacing: 0;
  margin-bottom: var(--sp-6);
  font-size: 0.82rem;
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-filter);
  -webkit-backdrop-filter: var(--glass-filter);
  border: 1px solid var(--glass-border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm), var(--inset-top);
  overflow: hidden;
}
.data-table th {
  text-align: left; font-size: 0.66rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--color-muted-foreground);
  padding: 0.65rem 0.85rem;
  background: var(--glass-inset);
  border-bottom: 1px solid var(--hairline);
  white-space: nowrap;
}
.data-table td {
  padding: 0.62rem 0.85rem;
  border-bottom: 1px solid var(--hairline);
  vertical-align: middle;
}
.data-table tbody tr:last-child td { border-bottom: none; }
.data-table tbody tr { transition: background var(--transition); }
.data-table tbody tr:hover td { background: var(--glass-inset); }
.data-table .ghost-btn { padding: 0.28rem 0.6rem; font-size: 0.74rem; }
.data-table tbody tr.clickable-row { cursor: pointer; }
.data-table tbody tr.clickable-row:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }

/* ---------------------------------------------------------------------------
   18. Admin
   ------------------------------------------------------------------------ */
.admin-main {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: var(--sp-8) var(--sp-6) var(--sp-12);
  max-width: 1400px; margin: 0 auto; width: 100%;
}
.admin-main section { margin-bottom: var(--sp-10); }
.admin-main h2 {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: 0.72rem; font-weight: 600;
  color: var(--color-muted-foreground);
  text-transform: uppercase; letter-spacing: 0.1em;
  margin: 0 0 var(--sp-4);
}
.admin-main h2 .ph { color: var(--color-accent); font-size: 1rem; }

.hitl-actions { display: flex; gap: var(--sp-2); flex-wrap: wrap; }
.hitl-edit { margin-top: var(--sp-3); display: flex; flex-direction: column; gap: var(--sp-2); min-width: 260px; }
.hitl-edit textarea {
  padding: 0.55rem 0.7rem;
  border-radius: var(--r-sm);
  background: var(--glass-solid);
  border: 1px solid var(--glass-border);
  color: var(--color-foreground);
  font-size: 0.8rem; resize: vertical;
  box-shadow: inset 0 1px 2px var(--glass-lowlight);
}
.hitl-edit textarea:focus {
  border-color: var(--color-accent);
  box-shadow: inset 0 1px 2px var(--glass-lowlight), 0 0 0 3px color-mix(in srgb, var(--color-accent) 20%, transparent);
}
.hitl-edit .ghost-btn { align-self: flex-start; }

.admin-user-form {
  flex-direction: row; flex-wrap: wrap; align-items: center;
  margin-bottom: var(--sp-5);
}
.admin-user-form input, .admin-user-form select {
  padding: 0.55rem 0.75rem;
  border-radius: var(--r-sm);
  background: var(--glass-solid);
  border: 1px solid var(--glass-border);
  color: var(--color-foreground);
  font-size: 0.85rem; font-family: var(--font-sans);
  box-shadow: inset 0 1px 2px var(--glass-lowlight);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.admin-user-form input:focus, .admin-user-form select:focus {
  border-color: var(--color-accent);
  box-shadow: inset 0 1px 2px var(--glass-lowlight), 0 0 0 3px color-mix(in srgb, var(--color-accent) 20%, transparent);
}
.admin-user-form input { flex: 1 1 200px; }
.admin-user-form button { flex-shrink: 0; }
.admin-user-form .error-text { flex-basis: 100%; margin: 0; }
.role-badge {
  font-family: var(--font-sans); font-weight: 600; font-size: 0.66rem;
  padding: 0.1rem 0.5rem; border-radius: var(--r-pill);
  text-transform: uppercase; letter-spacing: 0.04em;
  background: color-mix(in srgb, var(--color-accent) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-accent) 32%, transparent);
  color: var(--color-accent-ink);
}
.role-badge.user {
  background: var(--glass-inset);
  border-color: var(--glass-border);
  color: var(--color-muted-foreground);
}

.section-hint {
  color: var(--color-muted-foreground); font-size: 0.82rem;
  margin: -0.4rem 0 var(--sp-4); max-width: 68ch;
}
/* Provider status cards — read-only. No inputs here by design: keys are set
   in .env, so this surface reports and tests, it never captures. */
.subsection-heading {
  margin: var(--sp-6) 0 var(--sp-2); font-size: 0.78rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.07em;
  color: var(--color-muted-foreground);
}
.subsection-heading:first-of-type { margin-top: var(--sp-4); }
.provider-sub {
  font-weight: 400; font-size: 0.78rem; text-transform: none;
  letter-spacing: 0; color: var(--color-muted-foreground);
}
.provider-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(248px, 1fr));
  gap: var(--sp-4); margin-bottom: var(--sp-4);
}
.provider-card {
  display: flex; flex-direction: column; gap: var(--sp-3);
  padding: var(--sp-4); border-radius: var(--r-md);
  background: var(--surface-card); border: 1px solid var(--glass-border);
}
/* Name left, status pill hard right — the pill is the scannable column, so it
   aligns across cards regardless of how long each provider's name is. */
.provider-card-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-2); min-height: 1.5rem;
}
.provider-name {
  font-weight: 600; font-size: 0.92rem;
  display: flex; align-items: baseline; gap: var(--sp-2); flex-wrap: wrap;
}
/* Two-column definition list: fixed label column so every value in the stack
   starts on the same x, which is what makes a spec block read as a table. */
.provider-meta { margin: 0; display: flex; flex-direction: column; gap: var(--sp-2); }
.provider-meta > div {
  display: grid; grid-template-columns: 4.25rem 1fr;
  align-items: baseline; gap: var(--sp-3);
}
.provider-meta dt {
  font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.05em;
  color: var(--color-muted-foreground);
}
.provider-meta dd {
  margin: 0; font-size: 0.82rem; min-width: 0;
  overflow-wrap: anywhere;
}
.provider-meta dd code {
  font-family: var(--font-mono); font-size: 0.76rem;
  padding: 0.05rem 0.3rem; border-radius: var(--r-xs);
  background: var(--glass-inset); color: var(--color-muted-foreground);
}
.provider-card-actions {
  display: flex; align-items: center; gap: var(--sp-2);
  margin-top: auto; padding-top: var(--sp-1);
}
.order-badge {
  font-size: 0.66rem; font-weight: 600;
  padding: 0.1rem 0.5rem; border-radius: var(--r-pill);
  text-transform: uppercase; letter-spacing: 0.04em;
  background: color-mix(in srgb, var(--color-accent) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-accent) 30%, transparent);
  color: var(--color-accent-ink);
}
.provider-result { margin: 0; font-size: 0.8rem; overflow-wrap: anywhere; }
.provider-result.ok { color: var(--color-nominal-ink); }
.provider-result.err { color: var(--color-critical-ink); }
.provider-result.pending { color: var(--color-muted-foreground); }
.status-pill {
  flex-shrink: 0;
  font-family: var(--font-sans); font-weight: 600; font-size: 0.62rem;
  padding: 0.08rem 0.45rem; border-radius: var(--r-pill);
  text-transform: uppercase; letter-spacing: 0.04em;
  background: var(--glass-inset); border: 1px solid var(--glass-border);
  color: var(--color-muted-foreground);
}
.status-pill.ok {
  background: color-mix(in srgb, var(--color-nominal) 16%, transparent);
  border-color: color-mix(in srgb, var(--color-nominal) 32%, transparent);
  color: var(--color-nominal-ink);
}
.status-pill.off {
  background: var(--glass-inset); border-color: var(--glass-border);
  color: var(--color-muted-foreground);
}
.status-pill.err {
  background: color-mix(in srgb, var(--color-critical) 16%, transparent);
  border-color: color-mix(in srgb, var(--color-critical) 34%, transparent);
  color: var(--color-critical-ink);
}

/* ---------------------------------------------------------------------------
   19. Analytics
   ------------------------------------------------------------------------ */
.stat-tiles {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--sp-4); margin-bottom: var(--sp-6);
}
/* Raised glass panel with a specular sheen — shared by every "card floating
   on the light field" surface (stat tiles, chart cards). One material, one
   set of rules; each caller only adds what makes it a stat tile vs a chart
   card. */
.stat-tile, .chart-card {
  position: relative; overflow: hidden;
  padding: var(--sp-5);
  border-radius: var(--r-lg);
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-filter);
  -webkit-backdrop-filter: var(--glass-filter);
  border: 1px solid var(--glass-border);
  box-shadow: var(--shadow-sm), var(--inset-edge);
  transition: transform var(--transition), box-shadow var(--transition), border-color var(--transition);
}
.stat-tile::before, .chart-card::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: linear-gradient(170deg, var(--glass-sheen) 0%, transparent 42%);
}
.stat-tile > *, .chart-card > * { position: relative; }
.stat-tile:hover, .chart-card:hover {
  transform: translateY(-2px);
  border-color: var(--glass-border-strong);
  box-shadow: var(--shadow-md), var(--inset-edge);
}
.stat-value { font-size: 1.9rem; font-weight: 600; color: var(--color-accent-ink); line-height: 1.05; letter-spacing: -0.02em; }
.stat-label { font-size: 0.74rem; color: var(--color-muted-foreground); margin-top: var(--sp-2); }

.charts-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: var(--sp-4); }
.chart-title {
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-muted-foreground); margin-bottom: var(--sp-4);
}
.chart-body { min-height: 60px; }

.bar-chart { width: 100%; height: 140px; overflow: visible; }
.chart-baseline { stroke: var(--hairline); stroke-width: 1; }
.chart-bar { fill: var(--color-accent); transition: opacity var(--transition); }
.chart-bar:hover { opacity: 0.7; }

.hbar-row {
  display: grid; grid-template-columns: 96px 1fr 40px;
  align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-3); font-size: 0.8rem;
}
.hbar-row:last-child { margin-bottom: 0; }
button.hbar-row-clickable {
  width: 100%; background: none; border: none; padding: var(--sp-1) 0; margin-bottom: var(--sp-2);
  font-family: var(--font-sans); cursor: pointer; border-radius: var(--r-sm);
  transition: background var(--transition);
}
button.hbar-row-clickable:hover { background: var(--glass-inset); }
button.hbar-row-clickable:hover .hbar-label { color: var(--color-foreground); }
.hbar-label { color: var(--color-muted-foreground); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.hbar-track {
  height: 12px; border-radius: var(--r-pill); overflow: hidden;
  background: var(--glass-inset);
  box-shadow: inset 0 1px 2px var(--glass-lowlight);
}
.hbar-fill {
  height: 100%; border-radius: var(--r-pill);
  background: var(--color-accent);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2);
  transition: width 620ms var(--ease-out);
}
.hbar-value { text-align: right; color: var(--color-foreground); }

/* ---------------------------------------------------------------------------
   20. Alert detail modal
   ------------------------------------------------------------------------ */
.modal-backdrop {
  position: fixed; inset: 0; z-index: var(--z-modal);
  display: flex; align-items: center; justify-content: center;
  padding: var(--sp-6);
  /* Plain dim scrim, no blur — a blurred scrim behind an already-frosted card
     compounds into a washed-out, low-contrast mess (two backdrop-filters
     stacked blur an already-blurred layer). The card below does the framing. */
  background: rgba(4, 7, 14, 0.55);
  animation: dp-fade-in 200ms ease-out;
}
:root[data-theme="light"] .modal-backdrop { background: rgba(23, 40, 74, 0.32); }
@keyframes dp-fade-in { from { opacity: 0; } to { opacity: 1; } }

.modal-glass {
  position: relative;
  width: 100%; max-width: 580px; max-height: 84vh; overflow-y: auto;
  padding: var(--sp-7);
  border-radius: var(--r-xl);
  background: var(--glass-bg-strong);
  backdrop-filter: blur(40px) saturate(190%);
  -webkit-backdrop-filter: blur(40px) saturate(190%);
  border: 1px solid var(--glass-border-strong);
  box-shadow: var(--shadow-lg), var(--inset-edge);
  animation: dp-modal-in var(--transition-spring);
}
@keyframes dp-modal-in {
  from { opacity: 0; transform: translateY(18px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.modal-close {
  position: absolute; top: var(--sp-5); right: var(--sp-5);
  display: flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border-radius: var(--r-pill);
  border: 1px solid var(--glass-border);
  background: var(--glass-inset);
  color: var(--color-muted-foreground);
  cursor: pointer;
  transition: background var(--transition), color var(--transition), transform var(--transition);
}
.modal-close:hover { background: var(--glass-raised); color: var(--color-foreground); transform: rotate(90deg); }

.modal-header {
  display: flex; align-items: center; gap: var(--sp-3);
  margin-bottom: var(--sp-5); padding-right: var(--sp-8);
}
.alert-severity-dot {
  width: 10px; height: 10px; border-radius: var(--r-pill); flex-shrink: 0;
  background: var(--color-warning);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-warning) 22%, transparent), 0 0 12px currentColor;
}
.alert-severity-dot.red {
  background: var(--color-critical);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-critical) 22%, transparent), 0 0 12px currentColor;
}
.modal-header h2 { font-size: 1.08rem; font-weight: 600; }

.modal-body {
  display: flex; flex-direction: column;
  font-size: 0.86rem; color: var(--color-muted-foreground);
  margin-bottom: var(--sp-6);
  border-radius: var(--r-md);
  background: var(--glass-well);
  border: 1px solid var(--hairline);
  padding: var(--sp-2) var(--sp-4);
}
.modal-body .kv {
  display: flex; justify-content: space-between; gap: var(--sp-4);
  padding: 0.5rem 0; border-bottom: 1px solid var(--hairline);
}
.modal-body .kv:last-child { border-bottom: none; }
.modal-body .kv span:first-child { color: var(--color-muted-foreground); }
.modal-body .kv span:last-child { color: var(--color-foreground); text-align: right; }

/* User chat-history transcript (openUserChatHistory) -- deliberately not
   built from .kv like the rest of this modal body. .kv right-aligns its
   second span, which is fine for a short "Run 4471" value but wraps a full
   answer paragraph into a ragged right-aligned block; a transcript reads
   left-to-right instead, grouped under day headings the way any real chat
   history does. */
.chat-transcript-day {
  display: flex; align-items: center; gap: var(--sp-3);
  margin: var(--sp-4) 0 var(--sp-2);
  font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.08em;
  font-weight: 600; color: var(--color-muted-foreground);
}
.chat-transcript-day:first-child { margin-top: 0; }
.chat-transcript-day::before, .chat-transcript-day::after { content: ""; flex: 1; height: 1px; background: var(--hairline); }

.chat-transcript-msg { padding: var(--sp-3) 0; border-bottom: 1px solid var(--hairline); }
.chat-transcript-msg:last-child { border-bottom: none; }
.chat-transcript-meta {
  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
  margin-bottom: var(--sp-1);
  font-size: 0.72rem; font-weight: 600;
}
.chat-transcript-role { text-transform: uppercase; letter-spacing: 0.04em; }
.chat-transcript-msg.role-user .chat-transcript-role { color: var(--color-accent-ink); }
.chat-transcript-msg.role-assistant .chat-transcript-role { color: var(--color-nominal-ink); }
.chat-transcript-time { color: var(--color-muted-foreground); font-weight: 400; }
.chat-transcript-relative { color: var(--color-faint-foreground); font-weight: 400; font-style: italic; }
.chat-transcript-content {
  font-size: 0.86rem; line-height: 1.6; color: var(--color-foreground);
  white-space: pre-wrap; overflow-wrap: anywhere;
}

.modal-actions { display: flex; gap: var(--sp-3); flex-wrap: wrap; align-items: center; }
.modal-actions .btn-primary { width: auto; margin-top: 0; padding: 0.5rem 1.2rem; }

.bulb-btn {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: 0.5rem 1.05rem;
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--brand-3) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--brand-3) 40%, transparent);
  color: var(--color-foreground);
  font-family: var(--font-sans); font-weight: 600; font-size: 0.84rem;
  cursor: pointer;
  box-shadow: var(--inset-top);
  transition: background var(--transition), transform var(--transition), box-shadow var(--transition);
}
.bulb-btn:hover {
  background: color-mix(in srgb, var(--brand-3) 24%, transparent);
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm), var(--inset-top);
}
.bulb-btn:active { transform: scale(0.98); }
.bulb-btn .ph { color: var(--brand-4); }
:root[data-theme="dark"] .bulb-btn .ph { color: var(--brand-1); }

.alert-fix-result {
  margin-top: var(--sp-5); padding-top: var(--sp-5);
  border-top: 1px solid var(--hairline); font-size: 0.86rem;
}
.alert-fix-result .rca-reasoning { margin: var(--sp-3) 0; }

.research-note {
  padding: var(--sp-4);
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--brand-3) 10%, var(--surface-card));
  border: 1px solid color-mix(in srgb, var(--brand-3) 32%, transparent);
  box-shadow: var(--inset-top);
  font-size: 0.8rem; line-height: 1.65;
  color: var(--color-muted-foreground);
  display: flex; gap: var(--sp-3); align-items: flex-start;
  flex-shrink: 0;
}
.research-note .ph { color: var(--brand-4); flex-shrink: 0; margin-top: 0.15rem; font-size: 1rem; }
:root[data-theme="dark"] .research-note .ph { color: var(--brand-1); }

/* ---------------------------------------------------------------------------
   21. Documents mode — citations, revision/OCR badges, conflicts, registry
   ------------------------------------------------------------------------ */
.doc-citation-row { margin-top: var(--sp-2); display: flex; flex-direction: column; gap: var(--sp-1); align-items: flex-start; }
.doc-citation {
  display: inline-flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
  font-family: var(--font-mono); font-size: 0.69rem;
  padding: 0.28rem 0.6rem;
  border-radius: var(--r-xs);
  background: var(--glass-inset);
  border: 1px solid var(--glass-border);
  color: var(--color-muted-foreground);
  transition: color var(--transition), border-color var(--transition);
}
.doc-citation:hover { color: var(--color-foreground); border-color: var(--glass-border-strong); }
.doc-citation .ph { color: var(--color-accent); }

.rev-badge {
  font-family: var(--font-sans); font-weight: 600; font-size: 0.64rem;
  padding: 0.08rem 0.45rem; border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--color-accent) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-accent) 32%, transparent);
  color: var(--color-accent-ink);
  white-space: nowrap;
}
.rev-badge.superseded {
  background: var(--glass-inset);
  border-color: var(--glass-border);
  color: var(--color-muted-foreground);
}
.ocr-badge {
  font-family: var(--font-sans); font-weight: 600; font-size: 0.64rem;
  padding: 0.08rem 0.45rem; border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--color-warning) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-warning) 34%, transparent);
  color: var(--color-warning-ink);
  white-space: nowrap;
}

.conflict-block {
  margin-top: var(--sp-3);
  padding: var(--sp-4);
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--color-warning) 9%, var(--surface-card));
  border: 1px solid color-mix(in srgb, var(--color-warning) 38%, transparent);
  box-shadow: var(--shadow-sm), var(--inset-top);
}
.conflict-block .conflict-title {
  display: flex; align-items: center; gap: var(--sp-2);
  color: var(--color-warning-ink); font-weight: 700; font-size: 0.84rem;
  margin-bottom: var(--sp-3);
}
.conflict-positions { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--sp-3); }
.conflict-position {
  padding: var(--sp-3);
  border-radius: var(--r-sm);
  background: var(--surface-card);
  border: 1px solid var(--glass-border);
  box-shadow: var(--inset-top);
  font-size: 0.82rem;
}
.conflict-position .value { font-weight: 700; color: var(--color-foreground); font-size: 0.95rem; }
.conflict-position .source { color: var(--color-muted-foreground); font-family: var(--font-mono); font-size: 0.71rem; margin-top: var(--sp-1); }
.conflict-note { margin-top: var(--sp-3); font-size: 0.77rem; color: var(--color-muted-foreground); font-style: italic; }

.revision-note {
  margin-top: var(--sp-2); font-size: 0.76rem; color: var(--color-warning-ink);
  display: flex; align-items: flex-start; gap: var(--sp-2);
}

.handoff-row { margin-top: var(--sp-3); }

.doc-registry { overflow-y: auto; padding: var(--sp-5); }
.family-group { margin-bottom: var(--sp-6); }
.family-group:last-child { margin-bottom: 0; }
.family-group-title {
  display: flex; align-items: center; gap: var(--sp-2);
  font-weight: 600; font-size: 0.9rem; margin-bottom: var(--sp-3);
  letter-spacing: -0.01em;
}
.family-group-title .ph { color: var(--color-accent); }

/* Market results sit on the ambient field with room to breathe. The market
   workspace has no flex:1 scroll region of its own, so the column itself
   scrolls once a long results table arrives. */
#workspace-market .content { overflow-y: auto; }
#workspace-market .data-table { margin-top: var(--sp-2); }
#market-export-btn { align-self: flex-start; flex-shrink: 0; }

/* A run takes tens of seconds with no other feedback on the page — a
   disabled, visibly inert submit button is what stops a second click from
   reading as "did that work?" and firing a duplicate run. */
#market-submit-btn:disabled {
  opacity: 0.6; cursor: not-allowed; transform: none; filter: none;
  box-shadow: var(--shadow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.18);
}

/* The conversational answer from market/answer.py — always shown when a run
   completes, distinct from the raw entity table below it (which may be
   empty even when the answer itself says something useful, e.g. a
   clarifying question for an off-topic query). */
.market-answer {
  margin-top: var(--sp-2);
  padding: var(--sp-3);
  background: var(--glass-well);
  border: 1px solid var(--glass-border);
  border-left: 3px solid var(--color-market);
  border-radius: var(--r-sm);
  font-size: 0.9rem; line-height: 1.5;
  white-space: pre-wrap;
}
.market-answer.answer-not-found,
.market-answer.answer-off-topic { border-left-color: var(--color-muted-foreground); }

/* Research history — past runs persist across a refresh; this is how you
   get back to them instead of losing the results (and the spend that
   produced them) the moment the tab reloads. */
.market-history { margin-top: var(--sp-3); }
.market-history-list {
  list-style: none; margin: var(--sp-2) 0 0; padding: 0;
  display: flex; flex-direction: column; gap: var(--sp-2);
  max-height: 260px; overflow-y: auto;
}
.market-history-item {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
  background: var(--glass-well);
  border: 1px solid var(--glass-border);
  border-radius: var(--r-sm);
  padding: var(--sp-2) var(--sp-3);
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}
.market-history-item:hover {
  background: var(--glass-inset);
  border-color: var(--glass-border-strong);
}
.market-history-item .query {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 0.86rem;
}
.market-history-item .meta {
  flex-shrink: 0; display: flex; align-items: center; gap: var(--sp-2);
  font-size: 0.72rem; color: var(--color-muted-foreground);
}
.market-history-item .meta .status-running { color: var(--color-accent-ink); }
.market-history-item .meta .status-failed { color: var(--color-critical-ink); }

/* ---------------------------------------------------------------------------
   21b. RFQ Package
   ------------------------------------------------------------------------ */
.upload-meta-row {
  display: flex; gap: var(--sp-3); flex-wrap: wrap; align-items: center;
}
.upload-meta-row select, .upload-meta-row input[type="text"] {
  padding: 0.48rem 0.7rem;
  border-radius: var(--r-sm);
  background: var(--glass-solid);
  border: 1px solid var(--glass-border);
  color: var(--color-foreground);
  font-size: 0.8rem; font-family: var(--font-sans);
  box-shadow: inset 0 1px 2px var(--glass-lowlight);
  transition: border-color var(--transition), box-shadow var(--transition);
}
.upload-meta-row input[type="text"]::placeholder { color: var(--color-faint-foreground); }
.upload-meta-row select:focus, .upload-meta-row input[type="text"]:focus {
  border-color: var(--color-accent);
  box-shadow: inset 0 1px 2px var(--glass-lowlight), 0 0 0 3px color-mix(in srgb, var(--color-accent) 20%, transparent);
}
.checkbox-label {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-size: 0.8rem; color: var(--color-muted-foreground);
  cursor: pointer;
}
.checkbox-label input[type="checkbox"] { accent-color: var(--color-accent); }

.rfq-panel { overflow-y: auto; padding: var(--sp-5) 0; display: flex; flex-direction: column; gap: var(--sp-5); }
.rfq-panel #rfq-form { flex-direction: row; flex-wrap: wrap; }
.rfq-panel #rfq-form input[type="text"] {
  flex: 1; min-width: 220px;
  padding: 0.75rem 0.9rem;
  border-radius: var(--r-md);
  background: var(--glass-solid);
  border: 1px solid var(--glass-border);
  color: var(--color-foreground);
  font-size: 0.86rem;
}
.rfq-panel #rfq-form input[type="text"]:focus {
  border-color: var(--color-accent);
  box-shadow: inset 0 1px 2px var(--glass-lowlight), 0 0 0 3px color-mix(in srgb, var(--color-accent) 20%, transparent);
}

.rfq-download-bar {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  background: var(--glass-inset);
  border: 1px solid var(--hairline);
}
.rfq-download-label {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  font-size: 0.8rem; color: var(--color-muted-foreground);
}
.rfq-download-bar .ghost-btn { display: inline-flex; align-items: center; gap: var(--sp-2); }

.rfq-section { margin-bottom: var(--sp-6); }
.rfq-section-title {
  display: flex; align-items: center; gap: var(--sp-2);
  font-size: 0.92rem; font-weight: 600; margin: 0 0 var(--sp-3);
  letter-spacing: -0.01em;
}
.rfq-section-title .ph-bold { color: var(--color-accent); }

.rfq-category-row td { background: var(--glass-inset); padding: var(--sp-2) 0.85rem; border-bottom: 1px solid var(--hairline); }
.rfq-category-row h4 { margin: 0; font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-muted-foreground); }

.rfq-multi-value { display: flex; flex-direction: column; gap: var(--sp-1); }
.rfq-multi-value div:not(:last-child) { padding-bottom: var(--sp-1); border-bottom: 1px dashed var(--glass-border); }

.rfq-status-badge {
  display: inline-flex; align-items: center; gap: 0.3em;
  font-size: 0.74rem; font-weight: 600; white-space: nowrap;
}
.rfq-status-nominal { color: var(--color-nominal-ink); }
.rfq-status-critical { color: var(--color-critical-ink); }
.rfq-status-warning { color: var(--color-warning-ink); }
.rfq-status-benchmark { color: var(--color-muted-foreground); }

/* An Industry Suggestion is neither a pass nor a fail — it must never read
   like a sourced project requirement, so it gets its own accent-tinted,
   dashed-border treatment distinct from the nominal/warning/critical trio. */
.rfq-suggestion {
  margin-top: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--color-accent) 10%, transparent);
  border: 1px dashed color-mix(in srgb, var(--color-accent) 45%, transparent);
  color: var(--color-accent-ink);
  font-size: 0.78rem; font-style: italic;
}

.rfq-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--sp-3); }
.rfq-list-item {
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  background: var(--surface-card);
  border: 1px solid var(--glass-border);
}
.rfq-list-item.rfq-mandatory { border-color: color-mix(in srgb, var(--color-critical) 34%, transparent); }
.rfq-list-param { font-size: 0.85rem; margin-bottom: var(--sp-1); }
.rfq-list-notes { font-size: 0.78rem; color: var(--color-muted-foreground); }

.rfq-conflict-group { margin-bottom: var(--sp-4); }
.rfq-conflict-group h4 { margin: 0 0 var(--sp-2); font-size: 0.8rem; font-weight: 700; color: var(--color-warning-ink); }
.rfq-conflict-group.rfq-conflict-critical h4 { color: var(--color-critical-ink); }
.rfq-conflict-group .conflict-block { margin-top: var(--sp-3); }
.rfq-conflict-group .conflict-block:first-of-type { margin-top: 0; }

/* Type 4 (code vs. project) means the project fails a code minimum, not just
   two sources disagreeing — give it the critical/red accent, not amber. */
.conflict-block.rfq-conflict-critical {
  background: color-mix(in srgb, var(--color-critical) 9%, var(--surface-card));
  border-color: color-mix(in srgb, var(--color-critical) 40%, transparent);
}
.conflict-block.rfq-conflict-critical .conflict-title { color: var(--color-critical-ink); }

.rfq-zero-hit {
  display: flex; align-items: flex-start; gap: var(--sp-2);
  margin-bottom: var(--sp-4);
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  background: color-mix(in srgb, var(--color-warning) 10%, var(--surface-card));
  border: 1px solid color-mix(in srgb, var(--color-warning) 36%, transparent);
  color: var(--color-warning-ink);
  font-size: 0.82rem;
}

.rfq-coverage-stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--sp-4); margin-bottom: var(--sp-4);
}

/* ---------------------------------------------------------------------------
   22. Responsive
   ------------------------------------------------------------------------ */
@media (max-width: 1000px) {
  .workspace { flex-direction: column; }
  .sidebar,
  .sessions-sidebar {
    width: 100%; max-height: 220px;
    border-right: none; border-bottom: 1px solid var(--hairline);
    box-shadow: inset 0 -1px 0 var(--glass-highlight);
  }
  .sidebar.collapsed,
  .sessions-sidebar.collapsed { border-bottom: none; }
  .topbar { flex-wrap: wrap; min-height: auto; max-height: none; padding: var(--sp-3) var(--sp-4); }
  .mode-toggle { order: 3; width: 100%; justify-content: center; }
  .content { padding: var(--sp-4); }

  /* The row-layout rail (vertically centred on the left edge) reads as a
     sidebar tab; stacked, the workspace is only one column wide and that
     same position would float mid-page over the chat. Re-anchor it as a
     compact pill in the top-left corner instead, clear of both the drop
     zone below it and the chat panel further down. */
  .alerts-restore-btn {
    left: var(--sp-3); top: var(--sp-3);
    flex-direction: row;
    transform: none;
    border: 1px solid var(--glass-border);
    border-radius: var(--r-pill);
  }
  .alerts-restore-btn:hover { transform: translateY(-1px); }
}

@media (max-width: 640px) {
  .msg { max-width: 92%; }
  .user-box { gap: var(--sp-2); }
  #user-display { display: none; }
  .rca-bar-row { grid-template-columns: 88px 1fr 44px; }
}


/* ------------------------------------------------------------------
   Per-message delete. The gutter is reserved only once the message has a
   server-side id (data-msg-id) — a question that has just been sent and is
   not yet stored has nothing to delete, shows no control, and needs no
   space held for one. The button stays hidden until the message is hovered
   or something inside it takes focus, so a long transcript isn't a column
   of trash icons, but it is still reachable by keyboard.
   ------------------------------------------------------------------ */
.msg[data-msg-id] { padding-right: 2.25rem; }

.msg-delete {
  position: absolute; top: 0.3rem; right: 0.3rem;
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.6rem; height: 1.6rem; padding: 0;
  border: none; border-radius: var(--r-sm);
  background: transparent; color: inherit;
  font-size: 0.9rem; line-height: 1; cursor: pointer;
  opacity: 0;
  transition: opacity var(--transition), background var(--transition), color var(--transition);
}
.msg:hover .msg-delete,
.msg:focus-within .msg-delete { opacity: 0.55; }
.msg .msg-delete:hover,
.msg .msg-delete:focus-visible {
  opacity: 1;
  background: color-mix(in srgb, var(--color-critical) 16%, transparent);
  color: var(--color-critical-ink);
}
.msg.user .msg-delete:hover,
.msg.user .msg-delete:focus-visible {
  /* The user bubble is already the accent fill — a danger tint on top of it
     muddies rather than warns, so lift the icon instead. */
  background: rgba(0, 0, 0, 0.18);
  color: var(--color-on-accent);
}
.msg-delete:disabled { opacity: 0.3; cursor: default; }


/* ------------------------------------------------------------------
   Chat sessions panel — the list of past conversations, one per
   workspace. It reuses .sidebar's chrome and collapse behaviour (see the
   shared selectors above); everything below is only what the list itself
   needs.
   ------------------------------------------------------------------ */
.sessions-sidebar { width: 244px; }

.new-chat-btn {
  display: flex; align-items: center; justify-content: center; gap: var(--sp-2);
  width: 100%; flex-shrink: 0;
  margin-bottom: var(--sp-3); padding: 0.5rem 0.8rem;
  border: 1px solid var(--glass-border);
  border-radius: var(--r-sm);
  background: var(--glass-inset);
  color: var(--color-foreground);
  font-family: var(--font-sans); font-size: 0.8rem; font-weight: 500;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition), transform var(--transition);
}
.new-chat-btn:hover {
  background: var(--glass-raised);
  border-color: var(--glass-border-strong);
  transform: translateY(-1px);
}
.new-chat-btn:active { transform: scale(0.98); }

.sessions-list {
  list-style: none; margin: 0; padding: 0;
  flex: 1; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 2px;
}
.sessions-empty {
  padding: var(--sp-3);
  font-size: 0.76rem; line-height: 1.5;
  color: var(--color-faint-foreground);
}
.sessions-empty.err { color: var(--color-critical-ink); }

.session-item {
  display: flex; align-items: stretch; gap: 2px;
  border-radius: var(--r-sm);
  transition: background var(--transition);
}
.session-item:hover { background: var(--glass-inset); }
.session-item.active { background: var(--glass-raised); }
.session-item.active .session-title { color: var(--color-accent-ink); font-weight: 600; }

.session-open {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 1px;
  padding: 0.45rem 0.55rem;
  background: none; border: none; border-radius: var(--r-sm);
  font-family: var(--font-sans); text-align: left; cursor: pointer;
  color: var(--color-foreground);
}
.session-title {
  font-size: 0.79rem; line-height: 1.35;
  /* One line, clipped — a long first question is the auto-title, and letting
     it wrap to four lines would turn the list into a wall of text. */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.session-meta {
  font-size: 0.67rem;
  color: var(--color-faint-foreground);
}

.session-actions {
  display: flex; align-items: center; gap: 1px;
  padding-right: 2px;
  opacity: 0;
  transition: opacity var(--transition);
}
/* Revealed on hover or keyboard focus so the list stays calm, but the
   controls are never keyboard-unreachable. */
.session-item:hover .session-actions,
.session-item:focus-within .session-actions { opacity: 1; }

.session-action {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.55rem; height: 1.55rem; padding: 0;
  border: none; border-radius: var(--r-sm);
  background: transparent; color: var(--color-muted-foreground);
  font-size: 0.85rem; cursor: pointer;
  transition: background var(--transition), color var(--transition);
}
.session-action:hover { background: var(--glass-raised); color: var(--color-foreground); }
.session-action.danger:hover {
  background: color-mix(in srgb, var(--color-critical) 16%, transparent);
  color: var(--color-critical-ink);
}

/* Restore rail. Sits near the top rather than vertically centred, because in
   the Manufacturing workspace the alerts rail already owns the middle of the
   left edge and two centred rails would land on top of each other. */
.sessions-restore-btn {
  position: absolute; left: 0; top: var(--sp-5);
  z-index: 2;
  display: flex; align-items: center; justify-content: center;
  padding: var(--sp-3) var(--sp-2);
  border: 1px solid var(--glass-border);
  border-left: none;
  border-radius: 0 var(--r-lg) var(--r-lg) 0;
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-filter);
  -webkit-backdrop-filter: var(--glass-filter);
  box-shadow: var(--shadow-md);
  color: var(--color-foreground);
  cursor: pointer;
  transition: background var(--transition), transform var(--transition), box-shadow var(--transition);
}
.sessions-restore-btn:hover {
  background: var(--glass-raised);
  transform: translateX(2px);
  box-shadow: var(--shadow-raised);
}

@media (max-width: 1000px) {
  /* Stacked layout: the workspace is one column, so a left-edge rail would
     float over the chat. Match what the alerts rail does here. */
  .sessions-restore-btn {
    position: static; width: 100%;
    border-left: 1px solid var(--glass-border);
    border-radius: 0;
  }
}

/* Footer control on the alerts list when the lower-priority tier is hidden. */
.alerts-show-more {
  width: 100%;
  justify-content: center;
  margin-top: var(--sp-2);
  font-size: 0.74rem;
  color: var(--color-muted-foreground);
}

/* ------------------------------------------------------------------
   Pilot — the in-app assistant. Fixed to the viewport rather than to a
   workspace so a single instance covers all three modes and the admin
   overlay, which is why the markup sits outside every .workspace.
   ------------------------------------------------------------------ */
.pilot-fab {
  position: fixed; right: var(--sp-5); bottom: var(--sp-5);
  z-index: 60;
  width: 3.1rem; height: 3.1rem;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--glass-border-strong);
  border-radius: 50%;
  background: var(--color-accent);
  color: var(--color-on-accent);
  font-size: 1.35rem; cursor: pointer;
  box-shadow: var(--shadow-md);
  transition: transform var(--transition), box-shadow var(--transition), background var(--transition);
}
.pilot-fab:hover { transform: translateY(-2px) scale(1.04); box-shadow: var(--shadow-raised); }
.pilot-fab:active { transform: scale(0.96); }

.pilot-panel {
  position: fixed; right: var(--sp-5); bottom: calc(var(--sp-5) + 3.9rem);
  z-index: 60;
  width: min(23rem, calc(100vw - 2 * var(--sp-5)));
  max-height: min(30rem, calc(100vh - 9rem));
  display: flex; flex-direction: column;
  border: 1px solid var(--glass-border);
  border-radius: var(--r-lg);
  background: var(--glass-bg-strong);
  backdrop-filter: var(--glass-filter);
  -webkit-backdrop-filter: var(--glass-filter);
  box-shadow: var(--shadow-md), var(--inset-top);
  overflow: hidden;
  animation: dp-msg-in 200ms var(--ease-out) both;
}

.pilot-head {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--hairline);
  flex-shrink: 0;
}
.pilot-title { display: flex; align-items: center; gap: var(--sp-2); font-weight: 600; font-size: 0.85rem; }
.pilot-title .ph { color: var(--color-accent); }
.pilot-scope {
  margin-left: auto; font-size: 0.66rem;
  color: var(--color-faint-foreground);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.pilot-icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.6rem; height: 1.6rem; padding: 0;
  border: none; border-radius: var(--r-sm);
  background: transparent; color: var(--color-muted-foreground);
  cursor: pointer; font-size: 0.9rem;
  transition: background var(--transition), color var(--transition);
}
.pilot-icon-btn:hover { background: var(--glass-raised); color: var(--color-foreground); }

.pilot-log {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: var(--sp-3) var(--sp-4);
  display: flex; flex-direction: column; gap: var(--sp-3);
}
.pilot-msg { font-size: 0.8rem; line-height: 1.55; max-width: 100%; }
.pilot-msg p { margin: 0 0 0.4rem; }
.pilot-msg p:last-child { margin-bottom: 0; }
.pilot-msg.user {
  align-self: flex-end;
  background: var(--color-accent); color: var(--color-on-accent);
  padding: 0.4rem 0.7rem; border-radius: var(--r-md);
  border-bottom-right-radius: var(--r-xs);
  max-width: 85%;
}
.pilot-msg.assistant { align-self: flex-start; color: var(--color-foreground); }
.pilot-msg.needs-review { border-left: 2px solid var(--color-warning); padding-left: var(--sp-3); }
.pilot-list { margin: 0.2rem 0 0.4rem; padding-left: 1.05rem; }
.pilot-list li { margin-bottom: 0.2rem; }
.pilot-cites { display: flex; flex-wrap: wrap; gap: 4px; margin-top: var(--sp-2); }

.pilot-actions { display: flex; flex-wrap: wrap; gap: 4px; margin-top: var(--sp-2); }
.pilot-action {
  padding: 0.28rem 0.6rem;
  border: 1px solid var(--glass-border);
  border-radius: var(--r-pill);
  background: var(--glass-inset);
  color: var(--color-accent-ink);
  font-family: var(--font-sans); font-size: 0.72rem;
  cursor: pointer;
  transition: background var(--transition), border-color var(--transition);
}
.pilot-action:hover { background: var(--glass-raised); border-color: var(--glass-border-strong); }

.pilot-form {
  display: flex; gap: var(--sp-2);
  padding: var(--sp-3);
  border-top: 1px solid var(--hairline);
  flex-shrink: 0;
}
.pilot-form input {
  flex: 1; min-width: 0;
  padding: 0.45rem 0.7rem;
  border: 1px solid var(--glass-border);
  border-radius: var(--r-sm);
  background: var(--glass-inset);
  color: var(--color-foreground);
  font-family: var(--font-sans); font-size: 0.78rem;
}
.pilot-form input:focus { outline: none; border-color: var(--color-accent); }
.pilot-form button {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2rem; border: none; border-radius: var(--r-sm);
  background: var(--color-accent); color: var(--color-on-accent);
  cursor: pointer;
}

@media (max-width: 1000px) {
  /* Full-width sheet on a narrow screen — a 23rem panel pinned to the corner
     covers most of a phone viewport anyway, so stop pretending it floats. */
  .pilot-panel {
    right: 0; left: 0; bottom: 0;
    width: 100%;
    max-height: 70vh;
    border-radius: var(--r-lg) var(--r-lg) 0 0;
  }
  .pilot-fab { right: var(--sp-4); bottom: var(--sp-4); }
}

/* A link whose target was not an http(s) URL — shown, but not clickable. */
.unsafe-link {
  color: var(--color-muted-foreground);
  text-decoration: underline dotted;
  cursor: help;
}

/* Equipment types offered after an RFQ refusal. */
.rfq-suggested-types { margin-top: var(--sp-3); }

/* ------------------------------------------------------------------
   "Thinking" indicator for the ask boxes. Three dots on a staggered
   bounce — enough motion to read as activity without becoming the
   loudest thing on screen while you wait a minute for an answer.
   ------------------------------------------------------------------ */
.msg.is-thinking {
  background: var(--glass-inset);
  border: 1px dashed var(--glass-border);
  box-shadow: none;
  color: var(--color-muted-foreground);
}
.thinking { display: inline-flex; align-items: center; gap: var(--sp-2); }
.thinking-label { font-size: 0.8rem; }
.thinking-elapsed { font-size: 0.72rem; color: var(--color-faint-foreground); }

.thinking-dots { display: inline-flex; align-items: flex-end; gap: 3px; height: 0.85rem; }
.thinking-dots i {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--color-accent);
  animation: dp-thinking 1.15s ease-in-out infinite;
}
.thinking-dots i:nth-child(2) { animation-delay: 0.16s; }
.thinking-dots i:nth-child(3) { animation-delay: 0.32s; }

@keyframes dp-thinking {
  0%, 70%, 100% { transform: translateY(0); opacity: 0.35; }
  35%           { transform: translateY(-5px); opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  /* Still shows state, just holds still — the dots stay visible at full
     opacity rather than vanishing along with the animation. */
  .thinking-dots i { animation: none; opacity: 0.8; }
}
