/* =========================================================================
   Nimbus Analytics — Tudor Health brand system (light canvas)
   Single source of truth for the Django app shell, dashboards and login.
   Mirrors the original Streamlit brand (BRAND_GUIDELINES.md): white content,
   navy ink, vibrant accents, frosted glass panels, AI-futuristic mesh bg.
   ========================================================================= */

:root {
  /* Brand palette */
  --tudor-navy: #0e1d3c;
  --tudor-blue: #15aff8;
  --tudor-green: #83c842;
  --tudor-cyan: #0bd0d9;
  --tudor-teal: #10cf9b;
  --tudor-mint: #85dfd0;
  --tudor-orange: #f49100;
  --tudor-pale-blue: #dbeff9;

  /* Functional tokens */
  --canvas: #ffffff;
  --canvas-tint: #f4f9fd;
  --glass-bg: rgba(255, 255, 255, 0.78);
  --glass-border: rgba(14, 29, 60, 0.10);
  --glass-border-strong: rgba(14, 29, 60, 0.16);
  --text-primary: #0e1d3c;
  --text-secondary: #33456b;
  --text-muted: #64748b;
  --shadow-sm: 0 1px 2px rgba(14, 29, 60, 0.06);
  --shadow-md: 0 6px 20px rgba(14, 29, 60, 0.08);
  --shadow-lg: 0 18px 48px rgba(14, 29, 60, 0.12);

  /* Destructive actions. Promoted from the values .auth__error already used,
     so the system has one red rather than a second one drifting beside it. */
  --danger-ink: #a32a2a;
  --danger-solid: #c33a3a;
  --danger-surface: rgba(214, 69, 69, 0.08);
  --danger-border: rgba(214, 69, 69, 0.30);

  --font-brand: "Aptos", "Segoe UI", system-ui, -apple-system, sans-serif;
  --radius-sm: 8px;
  --radius-md: 12px;
  --radius-lg: 18px;

  --sidebar-w: 320px;
  --nav-h: 52px;
}

@font-face {
  font-family: "Aptos";
  src: local("Aptos"), local("Aptos-Regular");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Aptos";
  src: local("Aptos Bold"), local("Aptos-Bold");
  font-weight: 700;
  font-display: swap;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  min-height: 100dvh;
  font-family: var(--font-brand);
  color: var(--text-primary);
  background: var(--canvas);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* ---- AI-futuristic mesh background (3 layers) ------------------------- */
.nimbus-bg {
  position: fixed;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(160deg, #ffffff 0%, #f2f8fd 46%, #e9f4fb 100%);
  background-attachment: fixed;
}
.nimbus-bg::before {  /* corner brand blobs + tech grid */
  content: "";
  position: absolute;
  inset: 0;
  background:
    radial-gradient(closest-side at 8% 6%, rgba(21, 175, 248, 0.13), transparent),
    radial-gradient(closest-side at 94% 4%, rgba(11, 208, 217, 0.11), transparent),
    radial-gradient(closest-side at 96% 96%, rgba(131, 200, 66, 0.10), transparent),
    radial-gradient(closest-side at 4% 92%, rgba(16, 207, 155, 0.10), transparent),
    linear-gradient(rgba(14, 29, 60, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(14, 29, 60, 0.045) 1px, transparent 1px);
  background-size: auto, auto, auto, auto, 44px 44px, 44px 44px;
  -webkit-mask-image: radial-gradient(ellipse 80% 70% at 50% 40%, #000 55%, transparent 100%);
  mask-image: radial-gradient(ellipse 80% 70% at 50% 40%, #000 55%, transparent 100%);
}
.nimbus-bg::after {  /* drifting aurora */
  content: "";
  position: absolute;
  inset: -20%;
  background:
    radial-gradient(28% 34% at 22% 30%, rgba(21, 175, 248, 0.18), transparent 70%),
    radial-gradient(26% 30% at 78% 24%, rgba(11, 208, 217, 0.14), transparent 70%),
    radial-gradient(30% 32% at 66% 78%, rgba(131, 200, 66, 0.13), transparent 70%);
  filter: blur(48px);
  animation: nimbusAurora 28s ease-in-out infinite alternate;
}
@keyframes nimbusAurora {
  0%   { transform: translate3d(0, 0, 0) scale(1); }
  50%  { transform: translate3d(2%, -1.5%, 0) scale(1.06); }
  100% { transform: translate3d(-2%, 2%, 0) scale(1.02); }
}
@media (prefers-reduced-motion: reduce) {
  .nimbus-bg::after { animation: none; }
}

a { color: var(--tudor-blue); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4 { color: var(--text-primary); font-weight: 700; letter-spacing: -0.01em; }

/* =========================================================================
   App shell
   ========================================================================= */
.app-shell { display: flex; min-height: 100dvh; }

/* Keyboard users land on the sidebar first; give them a way past it. */
.skip-link {
  position: absolute; left: 12px; top: 0; z-index: 200;
  padding: 10px 18px; border-radius: 0 0 10px 10px;
  background: var(--tudor-navy); color: #fff;
  font-size: 13px; font-weight: 700;
  transform: translateY(-110%); transition: transform 160ms ease;
}
.skip-link:focus { transform: translateY(0); text-decoration: none; }
@media (prefers-reduced-motion: reduce) { .skip-link { transition: none; } }

/* ---- Sidebar: navy command rail ---------------------------------------
   The colour tokens are *redefined* here rather than duplicated per widget,
   so the filter panel (accordions, chips, range inputs) inherits the dark
   treatment from the very same rules that theme it on a light canvas. Only
   the handful of values hard-coded for light get an explicit override below.
   Three grid rows — head / body / foot — so only the middle one scrolls and
   Sign out stays on screen however long the filter list grows. */
.sidebar {
  --text-primary: #f2f7fe;
  --text-secondary: #c3d3ea;
  --text-muted: #8ba2c4;
  --glass-bg: rgba(255, 255, 255, 0.06);
  --glass-border: rgba(255, 255, 255, 0.10);
  --glass-border-strong: rgba(255, 255, 255, 0.20);
  --canvas: rgba(255, 255, 255, 0.08);

  width: var(--sidebar-w);
  flex: 0 0 var(--sidebar-w);
  position: sticky; top: 0; align-self: flex-start;
  height: 100dvh;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  color: var(--text-secondary);
  /* Quiet chrome: a desaturated slate-navy with a single neutral highlight at
     the top. The brand-coloured washes that used to sit here competed with the
     charts — the accents now appear only where they carry meaning (the active
     rail, the monogram tiles, the selected chips). */
  background:
    radial-gradient(140% 38% at 50% 0%, rgba(255, 255, 255, 0.045), transparent 72%),
    linear-gradient(180deg, #16203a 0%, #111a2e 52%, #0d1526 100%);
  border-right: 1px solid rgba(255, 255, 255, 0.07);
}

.sidebar__head { padding: 22px 20px 16px; border-bottom: 1px solid rgba(255, 255, 255, 0.07); }
.sidebar__brand { display: block; border-radius: 10px; }
.sidebar__brand img { display: block; width: 164px; max-width: 100%; height: auto; margin: 0 auto; }
.sidebar__brand:focus-visible { outline: 2px solid var(--tudor-blue); outline-offset: 4px; }
.sidebar__eyebrow {
  margin: 11px 0 0; text-align: center;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--tudor-green);
}

.sidebar__body {
  overflow-y: auto; overscroll-behavior: contain;
  padding: 16px 16px 22px;
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.22) transparent;
}
.sidebar__body::-webkit-scrollbar { width: 8px; }
.sidebar__body::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.18); border-radius: 99px; }
.sidebar__body::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.30); }

.sidebar__section-title {
  margin: 2px 4px 9px;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--text-muted);
}
.sidebar__divider { height: 1px; background: var(--glass-border); margin: 18px 0 13px; border: 0; }

/* ---- Sidebar nav ------------------------------------------------------- */
.nav-link {
  position: relative; display: flex; align-items: center; gap: 11px;
  min-height: 46px; padding: 8px 12px 8px 15px; border-radius: 10px;
  color: var(--text-secondary); font-size: 13.5px; font-weight: 600; line-height: 1.3;
  transition: background 160ms ease, color 160ms ease;
}
.nav-link + .nav-link { margin-top: 2px; }
.nav-link:hover { background: rgba(255, 255, 255, 0.07); color: var(--text-primary); text-decoration: none; }
.nav-link:focus-visible { outline: 2px solid var(--nav-accent, var(--tudor-blue)); outline-offset: 2px; }
.nav-link--active { background: rgba(255, 255, 255, 0.10); color: #ffffff; }

/* The active marker is scaled, not resized, so it can never reflow the row. */
.nav-link__rail {
  position: absolute; left: 0; top: 50%; width: 3px; height: 26px; margin-top: -13px;
  border-radius: 0 3px 3px 0; background: var(--nav-accent, var(--tudor-blue));
  transform: scaleY(0); transform-origin: center;
  transition: transform 200ms cubic-bezier(0.22, 1, 0.36, 1);
}
.nav-link:hover .nav-link__rail { transform: scaleY(0.52); }
.nav-link--active .nav-link__rail { transform: scaleY(1); }

/* Monogram tile — the therapeutic-area code in the dashboard's own accent.
   Two dashboards can share an area label, so the accent does the separating. */
.nav-link__tile {
  flex: 0 0 30px; width: 30px; height: 30px; border-radius: 8px;
  display: grid; place-items: center;
  font-size: 10.5px; font-weight: 700; color: var(--nav-accent, var(--tudor-blue));
  background: rgba(255, 255, 255, 0.10);
  background: color-mix(in srgb, var(--nav-accent, #15aff8) 20%, transparent);
  border: 1px solid rgba(255, 255, 255, 0.18);
  border-color: color-mix(in srgb, var(--nav-accent, #15aff8) 42%, transparent);
}
.nav-link--active .nav-link__tile {
  color: var(--tudor-navy);
  background: var(--nav-accent, var(--tudor-blue));
  border-color: var(--nav-accent, var(--tudor-blue));
}
.nav-link__name { flex: 1 1 auto; min-width: 0; }

.nav-link--locked { cursor: not-allowed; color: var(--text-muted); }
.nav-link--locked:hover { background: none; color: var(--text-muted); }
.nav-link__lock { width: 14px; height: 14px; flex: 0 0 14px; opacity: 0.75; }

/* ---- Account footer ---------------------------------------------------- */
.sidebar__foot {
  padding: 13px 16px 15px;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(8, 13, 22, 0.45);
}
.account { display: flex; align-items: center; gap: 10px; padding: 3px 2px 11px; }
.account__avatar {
  flex: 0 0 34px; width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 12px; font-weight: 700; color: var(--tudor-navy);
  background: linear-gradient(135deg, var(--tudor-green), var(--tudor-teal));
}
.account__text { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.account__name {
  font-size: 13px; font-weight: 700; color: var(--text-primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.account__role { font-size: 11px; color: var(--text-muted); }
.btn--signout { min-height: 40px; }

/* Staff-only link to the agent review. Ghost like Sign out but set above it
   and a shade quieter -- it is a place to go, not the action this zone is for,
   and the footer must not read as two equal buttons. */
.sidebar__admin {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 38px; margin-bottom: 8px;
  font-size: 12.5px; color: var(--text-secondary);
}
.sidebar__admin .icon { width: 15px; height: 15px; flex: 0 0 15px; }

/* Ownership line, pinned under Sign out. Hairline-separated so it reads as a
   footer credit and not as a caption on the button above it, and muted so it
   stays subordinate to the one action in this zone. The owner's name is lifted
   by weight and contrast rather than colour, so it still ranks in greyscale.
   --text-muted on this footer is ~7:1, well past AA at this size. */
.sidebar__powered {
  margin: 12px 2px 0; padding-top: 11px;
  border-top: 1px solid rgba(255, 255, 255, 0.07);
  font-size: 11px; line-height: 1.4; letter-spacing: 0.02em;
  text-align: center; color: var(--text-muted);
}
.sidebar__powered span { font-weight: 600; color: var(--text-secondary); }
.sidebar .btn--ghost:hover { background: rgba(255, 255, 255, 0.10); color: #ffffff; }

/* ---- Filter panel on navy: only the values hard-coded for light ---------- */
.sidebar .filter-panel__reset:hover { background: rgba(255, 255, 255, 0.10); color: var(--tudor-cyan); }
.sidebar .filter-acc { background: rgba(255, 255, 255, 0.045); }
.sidebar .filter-acc[open] { background: rgba(255, 255, 255, 0.07); }
.sidebar .filter-acc__count { color: #7fd4ff; background: rgba(21, 175, 248, 0.20); }
.sidebar .filter-acc__count[data-count].is-all { color: var(--text-muted); background: rgba(255, 255, 255, 0.09); }
.sidebar .chip { background: rgba(255, 255, 255, 0.06); }
.sidebar .chip:hover { background: rgba(255, 255, 255, 0.12); }
/* Navy on the brand blue reads ~7:1; white on it fails AA. */
.sidebar .chip:has(input:checked) { color: var(--tudor-navy); }
.sidebar .chip:has(input:focus-visible) { outline-color: #ffffff; }
.sidebar .chip-actions button { color: #7fd4ff; }
.sidebar .range-row input { background: rgba(255, 255, 255, 0.08); }

/* Filter widgets */
.filter-group { margin-bottom: 14px; }
.filter-group > label {
  display: block; font-size: 12.5px; font-weight: 600;
  color: var(--text-secondary); margin-bottom: 6px;
}
.filter-select {
  width: 100%; border: 1px solid var(--glass-border-strong);
  border-radius: var(--radius-sm); background: rgba(255, 255, 255, 0.9);
  color: var(--text-primary); font-family: var(--font-brand);
  padding: 7px 9px; font-size: 13px;
}
.filter-select[multiple] { min-height: 96px; }
.filter-select:focus { outline: 2px solid var(--tudor-blue); outline-offset: 1px; border-color: transparent; }

/* Main region */
.main {
  flex: 1 1 auto; min-width: 0;
  padding: 26px clamp(20px, 3vw, 44px) 64px;
}

/* Top bar */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 18px; margin-bottom: 18px;
}
.topbar__title { margin: 0; font-size: 26px; }
.topbar__title .eyebrow {
  display: block; font-size: 12px; font-weight: 700; letter-spacing: 0.10em;
  text-transform: uppercase; color: var(--tudor-blue); margin-bottom: 3px;
}
.topbar__user { display: flex; align-items: center; gap: 12px; font-size: 13px; color: var(--text-muted); }

/* Pill tab menu (Patients / Providers) */
.tabmenu {
  display: inline-flex; gap: 4px; padding: 4px;
  background: var(--glass-bg); border: 1px solid var(--glass-border);
  border-radius: 999px; box-shadow: var(--shadow-sm); margin-bottom: 18px;
}
.tabmenu a {
  padding: 8px 18px; border-radius: 999px; font-weight: 600; font-size: 14px;
  color: var(--text-secondary); display: inline-flex; align-items: center; gap: 8px;
}
.tabmenu a:hover { color: var(--text-primary); text-decoration: none; }
.tabmenu a.active { background: var(--tudor-blue); color: #fff; box-shadow: var(--shadow-sm); }

/* Sticky section nav */
.section-nav {
  position: sticky; top: 8px; z-index: 40;
  display: flex; flex-wrap: wrap; gap: 4px;
  padding: 7px 8px; margin: 0 0 22px;
  background: rgba(14, 29, 60, 0.96); border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
}
.section-nav a {
  padding: 7px 14px; border-radius: var(--radius-sm); font-size: 13px; font-weight: 600;
  color: #c9d6ea; transition: background 150ms ease, color 150ms ease;
}
.section-nav a:hover { background: rgba(255, 255, 255, 0.10); color: #fff; text-decoration: none; }
.section-nav a.active { background: var(--tudor-blue); color: #fff; }
h2[id], h3[id], section[id] { scroll-margin-top: 78px; }

/* Section headings */
.section { margin: 30px 0 8px; }
.section__title {
  font-size: 20px; margin: 0 0 4px;
  display: flex; align-items: center; gap: 10px;
}
.section__title::before {
  content: ""; width: 4px; height: 22px; border-radius: 2px;
  background: linear-gradient(180deg, var(--tudor-blue), var(--tudor-cyan));
}
.section__subtitle { color: var(--text-muted); font-size: 14px; margin: 0 0 10px; }

/* =========================================================================
   Cards
   ========================================================================= */
.card {
  background: var(--glass-bg); border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-md);
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  padding: 18px 18px 14px; margin-bottom: 20px;
}
.chart-card__head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  margin-bottom: 4px;
}
.chart-card__insight {
  font-size: 13px; color: var(--text-muted); margin: 6px 2px 2px;
  border-left: 3px solid rgba(21, 175, 248, 0.35); padding-left: 10px;
}
.chart-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px;
}
.chart-grid .card { margin-bottom: 0; }
@media (max-width: 1100px) { .chart-grid { grid-template-columns: 1fr; } }

/* KPI tiles */
.kpi-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 16px; margin-bottom: 8px;
}
.kpi {
  background: var(--glass-bg); border: 1px solid var(--glass-border);
  border-left: 3px solid var(--tudor-blue); border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm); padding: 14px 16px;
}
.kpi__label { font-size: 12.5px; color: var(--text-muted); font-weight: 600; margin-bottom: 4px; }
.kpi__value {
  font-size: 28px; font-weight: 700; color: var(--tudor-navy);
  font-variant-numeric: tabular-nums; line-height: 1.1;
}
.kpi__delta { font-size: 12px; margin-top: 3px; font-variant-numeric: tabular-nums; }
.kpi__delta--up { color: #1f9d55; }
.kpi__delta--down { color: #d64545; }

/* =========================================================================
   Buttons
   ========================================================================= */
.btn {
  display: inline-flex; align-items: center; gap: 7px; cursor: pointer;
  font-family: var(--font-brand); font-weight: 600; font-size: 13px;
  padding: 8px 14px; border-radius: var(--radius-sm);
  border: 1px solid var(--tudor-blue); background: rgba(255, 255, 255, 0.9);
  color: var(--tudor-navy); transition: all 150ms ease; text-decoration: none;
}
.btn:hover { background: var(--tudor-blue); color: #fff; text-decoration: none; }
.btn:active { transform: scale(0.98); }
.btn .icon { width: 16px; height: 16px; }
.btn--primary { background: var(--tudor-blue); color: #fff; }
.btn--primary:hover { background: #0f97d8; }
.btn--excel { border-color: var(--glass-border-strong); background: var(--tudor-pale-blue); color: var(--tudor-navy); padding: 6px 11px; font-size: 12.5px; }
.btn--excel:hover { background: var(--tudor-blue); color: #fff; border-color: var(--tudor-blue); }
.btn--ghost {
  border: 1px solid var(--glass-border-strong); background: transparent;
  color: var(--text-muted); width: 100%; justify-content: center;
}
.btn--ghost:hover { background: rgba(14, 29, 60, 0.05); color: var(--text-primary); }

/* Tables */
.table-wrap { overflow-x: auto; border-radius: var(--radius-md); border: 1px solid var(--glass-border); }
table.data { width: 100%; border-collapse: collapse; background: #fff; font-size: 13px; }
table.data th, table.data td { padding: 9px 12px; text-align: left; border-bottom: 1px solid var(--glass-border); }
table.data th { color: var(--text-muted); font-weight: 600; font-size: 12px; text-transform: uppercase; letter-spacing: 0.03em; }
table.data td { font-variant-numeric: tabular-nums; }

/* Empty state */
.empty-state {
  text-align: center; padding: 60px 20px; color: var(--text-muted);
  background: var(--glass-bg); border: 1px dashed var(--glass-border-strong);
  border-radius: var(--radius-lg);
}

/* Messages */
.messages { list-style: none; padding: 0; margin: 0 0 16px; }
.messages li {
  padding: 10px 14px; border-radius: var(--radius-sm); margin-bottom: 8px; font-size: 14px;
  background: rgba(21, 175, 248, 0.10); border: 1px solid rgba(21, 175, 248, 0.3);
}

/* =========================================================================
   Home hub
   ========================================================================= */
.hub-head { margin: 8px 0 26px; }
.hub-head h1 { font-size: 30px; margin: 0 0 6px; }
.hub-head p { color: var(--text-muted); font-size: 15px; margin: 0; max-width: 640px; }
.hub-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 22px; }
.hub-card {
  position: relative; overflow: hidden;
  background: var(--glass-bg); border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-md);
  padding: 22px; transition: transform 180ms ease, box-shadow 180ms ease;
  display: flex; flex-direction: column; gap: 12px; min-height: 176px;
}
.hub-card--live:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); }
.hub-card--locked { opacity: 0.72; }
.hub-card__accent { position: absolute; top: 0; left: 0; right: 0; height: 4px; }
.hub-card__area {
  align-self: flex-start; font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; padding: 4px 10px; border-radius: 999px;
  background: rgba(14, 29, 60, 0.06); color: var(--text-secondary);
}
.hub-card__name { font-size: 18px; font-weight: 700; margin: 0; }
.hub-card__tagline { font-size: 13.5px; color: var(--text-muted); margin: 0; flex: 1 1 auto; }
.hub-card__foot { display: flex; align-items: center; justify-content: space-between; }
.badge {
  font-size: 11px; font-weight: 700; letter-spacing: 0.04em; padding: 3px 9px;
  border-radius: 999px; text-transform: uppercase;
}
.badge--live { background: rgba(131, 200, 66, 0.18); color: #4f7d17; }
.badge--soon { background: rgba(100, 116, 139, 0.14); color: var(--text-muted); }

/* =========================================================================
   Login — split panel: navy brand story (left) + sign-in form (right)
   ========================================================================= */
.auth {
  min-height: 100dvh;
  display: flex;
  padding: clamp(16px, 4vw, 48px);
}
.auth__card {
  /* margin:auto (not align-items:center) so a short viewport scrolls instead
     of clipping the top of the card. */
  margin: auto;
  width: 100%;
  max-width: 980px;
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  overflow: hidden;
  border: 1px solid var(--glass-border);
  border-radius: 22px;
  box-shadow: var(--shadow-lg);
  animation: authIn 420ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
@keyframes authIn {
  from { opacity: 0; transform: translateY(14px); }
}
@media (prefers-reduced-motion: reduce) {
  .auth__card { animation: none; }
}

/* ---- Brand panel: centred logo on a clean navy field, no grid overlay --- */
.auth__brand {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(36px, 4vw, 56px);
  color: #dfe9f7;
  background:
    radial-gradient(120% 90% at 14% 6%, rgba(21, 175, 248, 0.26), transparent 62%),
    radial-gradient(110% 85% at 88% 96%, rgba(131, 200, 66, 0.20), transparent 64%),
    linear-gradient(165deg, #12294f 0%, #0e1d3c 55%, #091528 100%);
}
.auth__brand-inner {
  display: flex; flex-direction: column; align-items: center;
  width: 100%; text-align: center;
}
.auth__logo { width: min(248px, 74%); height: auto; display: block; margin: 0 0 22px; }
.auth__eyebrow {
  margin: 0 0 10px;
  font-size: 12px; font-weight: 700; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--tudor-green);
}
.auth__lede { margin: 0; font-size: 15px; line-height: 1.55; color: #b9cae4; }

/* ---- Form panel ------------------------------------------------------- */
.auth__panel {
  display: flex; flex-direction: column; justify-content: center;
  padding: clamp(32px, 4vw, 52px);
  background: #fff;
}
.auth__title { font-size: clamp(24px, 2.6vw, 30px); margin: 0 0 6px; }
.auth__subtitle { margin: 0 0 26px; font-size: 14.5px; color: var(--text-muted); }

.auth__error {
  display: flex; align-items: flex-start; gap: 10px;
  margin: 0 0 20px; padding: 11px 13px;
  font-size: 13.5px; line-height: 1.5; color: var(--danger-ink);
  background: var(--danger-surface);
  border: 1px solid var(--danger-border);
  border-radius: var(--radius-md);
}
.auth__error-icon { width: 17px; height: 17px; flex: 0 0 17px; margin-top: 2px; }

.auth__field { margin-bottom: 16px; }
.auth__label {
  display: block; margin-bottom: 7px;
  font-size: 11.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-muted);
}
.auth__input {
  width: 100%; min-height: 48px; padding: 12px 14px;
  font-family: var(--font-brand); font-size: 15px; color: var(--text-primary);
  background: var(--canvas-tint);
  border: 1px solid var(--glass-border-strong); border-radius: 10px;
  transition: border-color 160ms ease, box-shadow 160ms ease, background 160ms ease;
}
.auth__input:hover { border-color: rgba(14, 29, 60, 0.28); }
.auth__input:focus {
  outline: none; background: #fff;
  border-color: var(--tudor-blue);
  box-shadow: 0 0 0 3px rgba(21, 175, 248, 0.20);
}
.auth__input[aria-invalid="true"] { border-color: rgba(214, 69, 69, 0.55); }

.auth__pw { position: relative; }
.auth__pw .auth__input { padding-right: 52px; }
.auth__pw-toggle {
  position: absolute; right: 3px; top: 50%; transform: translateY(-50%);
  width: 44px; height: 44px; display: grid; place-items: center;
  border: 0; border-radius: 9px; background: none; cursor: pointer;
  color: var(--text-muted); transition: color 150ms ease, background 150ms ease;
}
.auth__pw-toggle svg { width: 18px; height: 18px; }
.auth__pw-toggle:hover { color: var(--text-primary); background: rgba(14, 29, 60, 0.05); }
.auth__pw-toggle:focus-visible { outline: 2px solid var(--tudor-blue); outline-offset: 1px; }

.auth__hint {
  display: flex; align-items: center; gap: 6px;
  margin: 8px 0 0; font-size: 12px; font-weight: 600; color: #8a5200;
}
.auth__hint[hidden] { display: none; }  /* display:flex would defeat [hidden] */
.auth__hint svg { width: 14px; height: 14px; flex: 0 0 14px; }

/* Neutral guidance under a field. Distinct from .auth__hint, which is amber
   because it only ever says something is wrong (Caps Lock is on) -- colouring
   ordinary instructions the same way spends the warning's signal on text that
   is not warning about anything. */
.auth__note { margin: 8px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--text-muted); }

/* Label and "Forgot password?" on one line. */
.auth__label-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.auth__label-row .auth__label { margin-bottom: 7px; }
.auth__forgot {
  font-size: 12px; font-weight: 600; color: var(--tudor-blue);
  text-decoration: none; white-space: nowrap;
}
.auth__forgot:hover { text-decoration: underline; }
.auth__forgot:focus-visible { outline: 2px solid var(--tudor-blue); outline-offset: 2px; border-radius: 3px; }

/* The dashboards an invitation grants, shown before the password is chosen.
   Not decoration: it is the recipient's one chance to notice they have been
   given a cohort they should not have, while they are still outside it. */
.auth__grants {
  margin: 0 0 20px; padding: 14px 16px;
  background: var(--canvas-tint);
  border: 1px solid var(--glass-border-strong); border-radius: 10px;
}
.auth__grants-label {
  margin: 0 0 9px; font-size: 11px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted);
}
.auth__grants-list { margin: 0; padding: 0; list-style: none; }
.auth__grants-list li {
  display: flex; align-items: center; gap: 9px;
  font-size: 14px; line-height: 1.9; color: var(--text-primary);
}
.auth__grants-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 8px; }

/* The reset/complete pages use .auth__submit on an anchor, which needs the
   underline removed and the text centred the way a button already centres it. */
a.auth__submit { text-decoration: none; }

.auth__submit {
  width: 100%; min-height: 50px; margin-top: 8px;
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  font-family: var(--font-brand); font-size: 15px; font-weight: 700;
  /* Navy on the green→teal gradient reads at ~8:1; white would fail AA. */
  color: var(--tudor-navy);
  border: 0; border-radius: 10px; cursor: pointer;
  background: linear-gradient(135deg, var(--tudor-green) 0%, var(--tudor-teal) 100%);
  box-shadow: 0 8px 22px rgba(16, 207, 155, 0.26);
  transition: filter 160ms ease, box-shadow 160ms ease, transform 120ms ease;
}
.auth__submit-icon { width: 17px; height: 17px; }
.auth__submit:hover { filter: brightness(1.05); box-shadow: 0 12px 28px rgba(16, 207, 155, 0.34); }
.auth__submit:active { transform: translateY(1px); }
.auth__submit:focus-visible { outline: 3px solid var(--tudor-navy); outline-offset: 2px; }
.auth__submit:disabled { opacity: 0.6; cursor: progress; filter: none; box-shadow: none; }
@media (prefers-reduced-motion: reduce) {
  .auth__submit { transition: none; }
}

.auth__help { margin: 22px 0 0; font-size: 13px; line-height: 1.55; color: var(--text-secondary); }
.auth__legal { margin: 12px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--text-muted); }

/* Stack to a single column, with a tighter brand band so the form stays
   above the fold. */
@media (max-width: 860px) {
  .auth__card { grid-template-columns: 1fr; max-width: 440px; }
  .auth__brand { padding: 32px 28px 28px; }
  .auth__logo { width: min(180px, 56%); margin-bottom: 16px; }
  .auth__lede { font-size: 14px; }
}

.login-foot { margin-top: 22px; font-size: 12px; color: var(--text-muted); }

/* Plotly card fit */
.chart-card .plotly-graph-div { width: 100% !important; }

/* =========================================================================
   Modern filter panel (shared by all dashboards) — chip toggles + accordions
   ========================================================================= */
.filter-panel { display: flex; flex-direction: column; }
.filter-panel__head {
  display: flex; align-items: center; justify-content: space-between;
  margin: 2px 2px 8px;
}
.filter-panel__reset {
  font-size: 11.5px; font-weight: 700; letter-spacing: 0.03em; color: var(--text-muted);
  text-transform: uppercase; padding: 3px 8px; border-radius: 6px; transition: all 140ms ease;
}
.filter-panel__reset:hover { background: rgba(14, 29, 60, 0.06); color: var(--tudor-blue); text-decoration: none; }

.filter-form { display: flex; flex-direction: column; gap: 9px; }

.filter-acc {
  border: 1px solid var(--glass-border); border-radius: var(--radius-md);
  background: rgba(255, 255, 255, 0.55); overflow: hidden;
  transition: background 160ms ease, border-color 160ms ease;
}
.filter-acc[open] { background: rgba(255, 255, 255, 0.78); border-color: var(--glass-border-strong); }
.filter-acc__sum {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; user-select: none; -webkit-tap-highlight-color: transparent;
}
.filter-acc__sum::-webkit-details-marker { display: none; }
.filter-acc__sum:hover .filter-acc__label { color: var(--text-primary); }
.filter-acc__label { font-size: 13px; font-weight: 600; color: var(--text-secondary); flex: 1 1 auto; }
.filter-acc__count {
  font-size: 11px; font-weight: 700; color: var(--tudor-blue);
  background: rgba(21, 175, 248, 0.12); padding: 2px 9px; border-radius: 999px;
  font-variant-numeric: tabular-nums; min-width: 34px; text-align: center;
}
.filter-acc__count[data-count].is-all { color: var(--text-muted); background: rgba(14, 29, 60, 0.06); }
.filter-acc__chev { width: 15px; height: 15px; color: var(--text-muted); flex: 0 0 auto; transition: transform 200ms ease; }
.filter-acc[open] .filter-acc__chev { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .filter-acc__chev { transition: none; } }
.filter-acc__body { padding: 2px 12px 12px; }

.chip-row { display: flex; flex-wrap: wrap; gap: 6px; }
.chip {
  position: relative; display: inline-flex; align-items: center; gap: 5px;
  padding: 6px 12px; min-height: 34px; border-radius: 999px;
  border: 1px solid var(--glass-border-strong); background: #fff;
  color: var(--text-secondary); font-size: 12.5px; font-weight: 600; line-height: 1;
  cursor: pointer; transition: background 140ms ease, border-color 140ms ease, color 140ms ease;
}
.chip input { position: absolute; opacity: 0; width: 1px; height: 1px; margin: 0; pointer-events: none; }
.chip__check { width: 13px; height: 13px; margin-left: -2px; opacity: 0; width: 0; transition: opacity 120ms ease, width 120ms ease; }
.chip:hover { border-color: var(--tudor-blue); color: var(--text-primary); }
.chip:has(input:checked) { background: var(--tudor-blue); border-color: var(--tudor-blue); color: #fff; }
.chip:has(input:checked) .chip__check { opacity: 1; width: 13px; }
.chip:has(input:focus-visible) { outline: 2px solid var(--tudor-navy); outline-offset: 2px; }

.chip-actions { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.chip-actions button {
  background: none; border: 0; padding: 0; font: inherit; font-size: 11.5px; font-weight: 700;
  letter-spacing: 0.02em; color: var(--tudor-blue); cursor: pointer;
}
.chip-actions button:hover { text-decoration: underline; }
.chip-actions__sep { color: var(--glass-border-strong); }

/* A filter drawn above the section it governs rather than in the sidebar —
   the NSCLC data explorer's data categories. Deliberately built from the same
   .chip / .chip-row / .chip-actions parts as the sidebar panel: it is the same
   control, moved next to the table it changes, and it should not read as a
   different kind of thing for having been moved. */
.section-filter {
  margin: 0 0 14px; padding: 12px 16px 14px;
  border-radius: var(--radius-md);
  border: 1px solid var(--glass-border);
  background: var(--canvas-tint);
}
.section-filter__head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.section-filter__label {
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-muted);
}

/* Numeric range filter (min/max pair) */
.range-row { display: flex; align-items: flex-end; gap: 8px; }
.range-row label { flex: 1; display: flex; flex-direction: column; gap: 4px; }
.range-row label span {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--text-muted);
}
.range-row input {
  width: 100%; padding: 7px 9px; font: inherit; font-size: 12.5px; font-weight: 600;
  color: var(--text-primary); background: var(--canvas);
  border: 1px solid var(--glass-border-strong); border-radius: var(--radius-sm);
}
.range-row input:focus {
  outline: none; border-color: var(--tudor-blue);
  box-shadow: 0 0 0 3px rgba(21, 175, 248, 0.16);
}
.range-row__dash { color: var(--text-muted); padding-bottom: 8px; }
.range-row__hint {
  margin: 8px 0 0; font-size: 11px; color: var(--text-muted);
}

/* Table cards — sections that are data to read, not a figure */
.chart-card__title {
  margin: 0; font-size: 14.5px; font-weight: 700; color: var(--text-primary);
  letter-spacing: -0.01em;
}
.data-table-wrap { overflow-x: auto; max-height: 460px; overflow-y: auto; }
table.data-table {
  width: 100%; border-collapse: collapse; font-size: 12.5px;
  font-variant-numeric: tabular-nums;
}
table.data-table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--canvas-tint); color: var(--text-secondary);
  font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  text-align: left; padding: 9px 12px; white-space: nowrap;
  border-bottom: 1px solid var(--glass-border-strong);
}
table.data-table tbody td {
  padding: 8px 12px; color: var(--text-primary); white-space: nowrap;
  border-bottom: 1px solid var(--glass-border);
}
table.data-table tbody tr:hover td { background: rgba(21, 175, 248, 0.05); }
.data-table__note { margin: 10px 0 0; font-size: 11.5px; color: var(--text-muted); }

.filter-apply { width: 100%; justify-content: center; margin-top: 4px; }
.filter-apply .icon { width: 15px; height: 15px; }

/* Live filtering: the JS auto-applies on change, so the Apply button is
   hidden (progressive enhancement — it stays visible without JS). */
.filter-form.is-live .filter-apply { display: none; }

/* =========================================================================
   Loading states
   Two waits, two treatments. While a section's charts are still being built
   on the server the body holds card-shaped placeholders; once the markup
   lands, each card keeps its own overlay until Plotly has actually drawn
   into it (nimbus.js clears aria-busy on plotly_afterplot).
   ========================================================================= */
.section-body { min-height: 40px; }

/* One shimmer definition, reused by every placeholder shape. */
.sk {
  display: block; border-radius: 6px;
  background:
    linear-gradient(100deg, rgba(255, 255, 255, 0) 34%, rgba(255, 255, 255, 0.75) 50%, rgba(255, 255, 255, 0) 66%),
    rgba(14, 29, 60, 0.07);
  background-size: 220% 100%, auto;
  background-repeat: no-repeat;
  animation: nimbusShimmer 1.4s ease-in-out infinite;
}
@keyframes nimbusShimmer {
  0%   { background-position: 150% 0, 0 0; }
  100% { background-position: -60% 0, 0 0; }
}

/* Shaped like the chart card it stands in for, so the swap reads as a
   crossfade instead of a jump. */
.chart-skeleton {
  background: var(--glass-bg); border: 1px solid var(--glass-border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-md);
  padding: 18px 18px 14px; margin-bottom: 20px;
}
.chart-skeleton__head { display: flex; align-items: center; justify-content: space-between; gap: 14px; }
.sk--title { width: 42%; height: 15px; }
.sk--btn { width: 124px; height: 30px; border-radius: 8px; }
.chart-skeleton__plot {
  position: relative; height: 288px; margin: 24px 0 6px; padding-left: 32px;
  display: flex; align-items: flex-end;
}
.sk--axis { position: absolute; left: 22px; top: 0; bottom: 0; width: 2px; border-radius: 2px; }
.chart-skeleton__bars {
  flex: 1 1 auto; height: 100%;
  display: flex; align-items: flex-end; gap: 3.2%;
}
.sk--bar { flex: 1 1 0; border-radius: 6px 6px 2px 2px; }
.chart-skeleton__bars .sk--bar:nth-child(1) { height: 52%; }
.chart-skeleton__bars .sk--bar:nth-child(2) { height: 74%; }
.chart-skeleton__bars .sk--bar:nth-child(3) { height: 38%; }
.chart-skeleton__bars .sk--bar:nth-child(4) { height: 88%; }
.chart-skeleton__bars .sk--bar:nth-child(5) { height: 61%; }
.chart-skeleton__bars .sk--bar:nth-child(6) { height: 45%; }
.chart-skeleton__bars .sk--bar:nth-child(7) { height: 70%; }
.sk--caption { width: 58%; height: 11px; margin-top: 18px; }

/* Per-chart render overlay. Translucent rather than opaque so a figure is
   never fully hidden — worst case the reader watches it resolve. */
.chart-card__plot { position: relative; }
.chart-card__loader {
  position: absolute; inset: 0; z-index: 2;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, 0.72);
  backdrop-filter: blur(2px); -webkit-backdrop-filter: blur(2px);
  opacity: 0; visibility: hidden;
  transition: opacity 220ms ease, visibility 0s linear 220ms;
}
.chart-card[aria-busy="true"] .chart-card__loader {
  opacity: 1; visibility: visible; transition-delay: 0s;
}
/* A figure Plotly never drew. The overlay stays up instead of clearing to
   reveal an empty box, which reads as a chart that is meant to be blank. Opaque
   rather than translucent here: there is nothing underneath to see through. */
.chart-card[data-plot-failed] .chart-card__loader {
  opacity: 1; visibility: visible; transition-delay: 0s;
  background: var(--canvas-tint);
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
.chart-card[data-plot-failed] .chart-card__loader-text { color: var(--danger-ink); }
.chart-card__spinner {
  width: 30px; height: 30px; border-radius: 50%;
  border: 3px solid rgba(14, 29, 60, 0.12);
  border-top-color: var(--tudor-blue);
  animation: nimbusSpin 720ms linear infinite;
}
@keyframes nimbusSpin { to { transform: rotate(360deg); } }
.chart-card__loader-text {
  font-size: 12px; font-weight: 600; letter-spacing: 0.02em; color: var(--text-muted);
}

/* Cards settle in sequence; --reveal-delay is staggered by nimbus.js. */
.chart-card:not([aria-busy]) .chart-card__plot {
  animation: nimbusCardIn 300ms ease-out both;
  animation-delay: var(--reveal-delay, 0ms);
}
@keyframes nimbusCardIn { from { opacity: 0.3; transform: translateY(6px); } }

@media (prefers-reduced-motion: reduce) {
  .sk { animation: none; }
  .chart-card__spinner { animation-duration: 2.4s; }
  .chart-card:not([aria-busy]) .chart-card__plot { animation: none; }
  .nav-link__rail { transition: none; }
}
.section-empty {
  padding: 26px 20px; text-align: center; color: var(--text-muted); font-size: 13.5px;
  background: var(--glass-bg); border: 1px dashed var(--glass-border-strong);
  border-radius: var(--radius-lg);
}

/* AI insight strip — appended after a section's cards by nimbus.js. */
.section-insights {
  margin-top: 4px; padding: 14px 18px 12px;
  background: var(--glass-bg); border: 1px solid var(--glass-border);
  border-left: 3px solid rgba(21, 175, 248, 0.45);
  border-radius: var(--radius-lg);
}
.section-insights__head {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 11.5px; font-weight: 600; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text-muted); margin-bottom: 8px;
}
.section-insights__head svg { color: rgba(21, 175, 248, 0.8); }
.section-insights__list { list-style: none; margin: 0; padding: 0; }
.section-insights__item { padding: 5px 0; font-size: 13.5px; }
.section-insights__item + .section-insights__item {
  border-top: 1px solid var(--glass-border);
}
.section-insights__group { margin-top: 10px; }
.section-insights__group:first-of-type { margin-top: 2px; }
.section-insights__audience {
  display: inline-block; font-size: 10.5px; font-weight: 600;
  letter-spacing: 0.04em; text-transform: uppercase;
  color: rgba(21, 175, 248, 0.9);
  border: 1px solid rgba(21, 175, 248, 0.35); border-radius: 999px;
  padding: 1px 8px; margin-bottom: 4px;
}
.section-insights__action {
  display: block; color: var(--text-muted); margin-top: 2px;
}
.section-insights__sources {
  display: block; font-size: 11.5px; color: var(--text-muted); opacity: 0.8;
  margin-top: 2px;
}
.section-insights--loading .sk { height: 12px; margin: 4px 0; }

/* =========================================================================
   Ask Nimbus — floating assistant
   ========================================================================= */
/* The Nimbus mark — the logo's disc redrawn as a chat bubble, instanced from
   the sprite in brand/_ask_nimbus.html. Sized here so every appearance of the
   assistant (button, panel head, each reply) uses the same artwork. */
.nimbus-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.nimbus-mark { flex: 0 0 auto; display: block; }
.nimbus-mark--fab { width: 22px; height: 22px; margin-block: -1px; }
.nimbus-mark--lg { width: 30px; height: 30px; }
.nimbus-mark--avatar { width: 24px; height: 24px; }

.ask-fab {
  position: fixed; right: 24px; bottom: 24px; z-index: 60;
  display: inline-flex; align-items: center; gap: 9px;
  padding: 12px 20px; border: 0; border-radius: 999px; cursor: pointer;
  font-family: var(--font-brand); font-size: 14px; font-weight: 700; color: #fff;
  background: linear-gradient(135deg, var(--tudor-blue), var(--tudor-cyan));
  box-shadow: 0 10px 30px rgba(21, 175, 248, 0.38);
  transition: transform 160ms ease, box-shadow 160ms ease;
}
.ask-fab:hover { transform: translateY(-2px); box-shadow: 0 14px 38px rgba(21, 175, 248, 0.46); }
.ask-fab:active { transform: translateY(0); }

.ask-panel {
  position: fixed; right: 0; top: 0; bottom: 0; z-index: 70;
  width: min(460px, 100vw);
  display: flex; flex-direction: column;
  background: rgba(255, 255, 255, 0.96);
  backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px);
  border-left: 1px solid var(--glass-border-strong);
  box-shadow: -18px 0 48px rgba(14, 29, 60, 0.16);
  animation: askIn 220ms ease;
}
@keyframes askIn { from { transform: translateX(24px); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .ask-panel { animation: none; } }
.ask-panel[hidden] { display: none; }

.ask-panel__head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
  padding: 18px 20px 14px; border-bottom: 1px solid var(--glass-border);
}
.ask-panel__brand { display: flex; align-items: center; gap: 11px; min-width: 0; }
.ask-panel__title { margin: 0; font-size: 17px; }
.ask-panel__scope { margin: 3px 0 0; font-size: 12px; color: var(--text-muted); }
.ask-panel__scope.is-filtered { color: var(--tudor-blue); font-weight: 600; }
.ask-panel__close {
  background: none; border: 0; cursor: pointer; color: var(--text-muted);
  padding: 4px; border-radius: 6px; line-height: 0;
}
.ask-panel__close:hover { background: rgba(14, 29, 60, 0.06); color: var(--text-primary); }

.ask-log { flex: 1 1 auto; overflow-y: auto; padding: 16px 18px; }

.ask-empty { color: var(--text-muted); font-size: 13.5px; }
.ask-empty p { margin: 0 0 14px; }
.ask-suggestions { display: flex; flex-direction: column; gap: 8px; }
.ask-suggestions button {
  text-align: left; font: inherit; font-size: 13px; cursor: pointer;
  padding: 10px 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--glass-border-strong); background: rgba(255, 255, 255, 0.8);
  color: var(--text-secondary); transition: all 140ms ease;
}
.ask-suggestions button:hover {
  border-color: var(--tudor-blue); color: var(--text-primary);
  background: rgba(21, 175, 248, 0.07);
}

.ask-msg { margin-bottom: 14px; font-size: 13.5px; line-height: 1.55; }
.ask-msg--user .ask-msg__body {
  margin-left: auto; max-width: 88%; width: fit-content;
  background: var(--tudor-blue); color: #fff;
  padding: 9px 13px; border-radius: 14px 14px 4px 14px;
}
/* A bot turn is the mark plus a content column. Everything the answer renders
   lives in that column, so re-rendering it cannot take the mark with it. */
.ask-msg--bot { display: flex; align-items: flex-start; gap: 9px; }
.ask-msg__avatar { margin-top: 2px; }
.ask-msg__content { flex: 1 1 auto; min-width: 0; }
.ask-msg--bot .ask-msg__body {
  color: var(--text-primary); white-space: pre-wrap;
  background: rgba(219, 239, 249, 0.5); border: 1px solid var(--glass-border);
  padding: 11px 13px; border-radius: 14px 14px 14px 4px;
}
.ask-msg.is-thinking .ask-msg__body { color: var(--text-muted); font-style: italic; }
.ask-msg.is-thinking .ask-msg__avatar { animation: nimbusThinking 1.5s ease-in-out infinite; }
@keyframes nimbusThinking { 50% { opacity: 0.4; transform: scale(0.9); } }
@media (prefers-reduced-motion: reduce) {
  .ask-msg.is-thinking .ask-msg__avatar { animation: none; }
}

/* An answer rendered as Markdown rather than as preformatted text.
   `pre-wrap` above is what holds the plain-text path's line breaks; here the
   blocks are real elements, so it is dropped and the spacing is theirs. Both
   paths exist (static/brand/js/markdown.js falls back), so the two must not
   share a rule that only suits one of them. */
.ask-msg--bot .ask-msg__body.ask-md { white-space: normal; }
.ask-md > :first-child { margin-top: 0; }
.ask-md > :last-child { margin-bottom: 0; }
.ask-md .md-p { margin: 0 0 9px; }
.ask-md .md-heading {
  margin: 12px 0 6px; font-size: 13.5px; font-weight: 600;
  color: var(--text-primary);
}
.ask-md .md-list { margin: 0 0 9px; padding-inline-start: 1.15em; }
.ask-md .md-list li { margin-bottom: 4px; }
.ask-md .md-list li:last-child { margin-bottom: 0; }
.ask-md .md-list::marker, .ask-md .md-list li::marker { color: var(--tudor-blue); }
/* Weight, not hue: the figure an answer turns on has to read as emphasised to
   somebody who cannot separate the colours, and a second ink here would also
   put a third colour into a bubble that already has a tinted ground. */
.ask-md strong { font-weight: 700; color: inherit; }
.ask-md em { font-style: italic; }
.ask-md code {
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.92em; padding: 1px 4px; border-radius: 4px;
  background: rgba(14, 29, 60, 0.06); overflow-wrap: anywhere;
}
.ask-md .md-quote {
  margin: 0 0 9px; padding: 2px 0 2px 10px;
  border-left: 3px solid var(--tudor-blue); color: var(--text-secondary);
}

/* Tables. The panel is ~380px and a four-column table is not, so the wrapper
   scrolls and the page never does. */
.ask-md .md-table-wrap {
  margin: 0 0 10px; max-width: 100%; overflow-x: auto;
  border: 1px solid var(--glass-border); border-radius: var(--radius-sm);
  background: var(--canvas);
}
.ask-md .md-table {
  border-collapse: collapse; width: 100%; font-size: 12.5px;
  line-height: 1.45;
}
.ask-md .md-table th, .ask-md .md-table td {
  padding: 6px 10px; text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--glass-border); white-space: nowrap;
}
.ask-md .md-table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--tudor-pale-blue); color: var(--text-primary);
  font-weight: 600; border-bottom-color: var(--glass-border-strong);
}
.ask-md .md-table tbody tr:last-child td { border-bottom: 0; }
.ask-md .md-table tbody tr:nth-child(even) { background: var(--canvas-tint); }
/* A column of rates read down the page is the reason a table was used at all;
   ragged decimal points are what makes it unreadable again. */
.ask-md .md-table .is-num {
  text-align: right; font-variant-numeric: tabular-nums;
}

.ask-chart {
  margin-top: 10px; background: #fff; border: 1px solid var(--glass-border);
  border-radius: var(--radius-md); padding: 8px; overflow-x: auto;
}
.ask-chart .plotly-graph-div { width: 100% !important; }

/* "Edit chart" under a proposed chart, beside the publish control. */
.ask-edit {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin-top: 6px;
}
.ask-edit__btn {
  display: inline-flex; align-items: center; gap: 6px;
  /* 44px of hit area on a control that only looks like 30px of one. The chart
     above it is a scroll region on touch, so a near-miss here is a drag. */
  min-height: 44px; padding: 6px 10px; font-size: 12px;
}
.ask-edit__btn:focus-visible {
  outline: 2px solid var(--tudor-blue); outline-offset: 2px;
}
.ask-edit__hint {
  font-size: 11px; color: var(--text-muted); flex: 1 1 140px; min-width: 0;
}

/* Publish-to-dashboard control under an agent chart. */
.ask-save {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin-top: 10px;
}
.ask-save__select {
  flex: 1 1 150px; min-width: 0;
  padding: 7px 10px; border-radius: 8px;
  border: 1px solid var(--glass-border);
  background: var(--canvas); color: var(--text-primary);
  font-size: 12.5px;
}
.ask-save__btn { flex: 0 0 auto; font-size: 12.5px; padding: 7px 13px; }
.ask-save__note {
  flex: 1 0 100%; font-size: 11.5px; color: var(--text-muted);
}

/* Provenance marker on a published agent chart. Deliberately quiet: it labels
   the card, it does not advertise it. */
.ai-badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px 3px 7px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700;
  letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--tudor-navy);
  background: rgba(21, 175, 248, 0.14);
  border: 1px solid rgba(21, 175, 248, 0.38);
}
.ai-badge svg { flex: 0 0 auto; }

/* A chart somebody asked Nimbus to change. Warmer than the generated badge and
   never shown beside it — the two are alternatives, not a pair — so the colour
   is the whole of the distinction and it has to carry on its own. */
.ai-badge--edited {
  color: #6b4700;
  background: rgba(217, 154, 0, 0.15);
  border-color: rgba(217, 154, 0, 0.45);
}

/* How a published agent chart was built, under the chart. Same vocabulary as
   the panel's own step list (.ask-steps) because it is the same content read
   later by somebody else — a reader who has seen one should recognise the
   other. Quiet while closed: it is evidence to be checked, not a claim to be
   made, and it sits below charts that are mostly read without doubt. */
.chart-steps { margin-top: 10px; font-size: 12px; }
.chart-steps__summary {
  cursor: pointer; color: var(--text-muted); font-weight: 600;
  list-style: none;
  /* Comfortably tappable, and clear of the Excel button above it. */
  padding: 7px 0; min-height: 32px;
}
.chart-steps__summary::-webkit-details-marker { display: none; }
.chart-steps__summary::before { content: "▸ "; }
.chart-steps[open] .chart-steps__summary::before { content: "▾ "; }
.chart-steps__summary:focus-visible {
  outline: 2px solid var(--tudor-blue, #15aff8); outline-offset: 3px;
  border-radius: 4px;
}
/* The verdict never rests on colour: each state has its own words, so it
   survives greyscale and a reader who cannot tell the two apart. */
.chart-steps__verdict {
  font-weight: 500; color: var(--text-muted);
}
.chart-steps__verdict--warn { color: #a32a2a; font-weight: 700; }
/* Prose inside the panel: where the card came from, why the view asked for it,
   and what its own run reported. Capped at a readable measure — a full-width
   card is far wider than a sentence wants to be, and this is text somebody is
   reading closely enough to have opened it. */
.chart-steps__origin, .chart-steps__note {
  margin: 8px 0 0; max-width: 74ch; line-height: 1.55;
  color: var(--text-secondary);
}
.chart-steps__origin {
  padding-left: 9px; border-left: 2px solid var(--glass-border);
}
/* A label on its own line rather than a run-in: the sentence after it is often
   long enough to wrap, and a wrapped run-in label reads as one ragged
   paragraph. Weight and colour carry it — never colour alone. */
.chart-steps__label {
  display: block; color: var(--text-muted); font-weight: 700;
  letter-spacing: 0.01em;
}
.chart-steps__list {
  margin: 2px 0 0; padding: 0 0 0 2px; list-style: none;
  border-top: 1px solid var(--glass-border);
}
.chart-steps__origin + .chart-steps__list,
.chart-steps__note + .chart-steps__list { margin-top: 11px; }
.chart-step { padding: 7px 0; border-bottom: 1px dashed var(--glass-border); }
.chart-step:last-child { border-bottom: 0; }
.chart-step__text { color: var(--text-secondary); font-weight: 600; }
.chart-step--failed .chart-step__text { color: #a32a2a; }
/* The SQL a step ran. Scrolls inside itself rather than widening the card. */
.chart-step__detail {
  margin: 5px 0 0; padding: 7px 9px; overflow-x: auto;
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace; font-size: 11px;
  background: rgba(14, 29, 60, 0.045); border-radius: 6px; color: var(--text-secondary);
  white-space: pre-wrap; word-break: break-word;
}

/* Move / delete on a published agent chart. A footer strip rather than head
   chrome: these act on the card, not on what it shows, so they sit below the
   figure and stay quiet until someone goes looking for them. */
.chart-manage {
  margin-top: 12px; padding-top: 11px;
  border-top: 1px solid var(--glass-border);
}
.chart-manage__bar {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  /* Both steps are one row of this height, so asking the question cannot
     shift the card out from under the cursor about to answer it. */
  min-height: 34px;
}
/* `display: flex` above is an author rule and would beat the UA's
   [hidden] { display: none }, leaving both steps on screen at once. */
.chart-manage__bar[hidden] { display: none; }
.chart-manage__label {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.10em;
  text-transform: uppercase; color: var(--text-muted);
}
.chart-manage__select {
  font-family: var(--font-brand); font-size: 12.5px; color: var(--text-primary);
  padding: 6px 9px; border-radius: var(--radius-sm); max-width: 240px;
  border: 1px solid var(--glass-border-strong); background: var(--canvas);
}
.chart-manage__btn {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  font-family: var(--font-brand); font-weight: 600; font-size: 12.5px;
  padding: 6px 11px; border-radius: var(--radius-sm);
  border: 1px solid var(--glass-border-strong); background: transparent;
  color: var(--text-muted); transition: all 150ms ease;
}
.chart-manage__btn:hover { background: rgba(14, 29, 60, 0.05); color: var(--text-primary); }
.chart-manage__btn .icon { width: 14px; height: 14px; }
.chart-manage__btn:disabled { opacity: 0.45; cursor: not-allowed; }
.chart-manage__select:focus-visible,
.chart-manage__btn:focus-visible { outline: 2px solid var(--tudor-blue); outline-offset: 2px; }

/* Pushed to the far end: the section menu and the delete button must not be
   one slip apart. Danger is carried by the word as well as the colour, so it
   still reads as destructive in greyscale. */
.chart-manage__bar > [data-manage-delete] { margin-left: auto; }
.chart-manage__btn--danger { color: var(--danger-ink); border-color: var(--danger-border); }
.chart-manage__btn--danger:hover { background: var(--danger-surface); color: var(--danger-ink); }
.chart-manage__btn--solid {
  background: var(--danger-solid); border-color: var(--danger-solid); color: #ffffff;
}
.chart-manage__btn--solid:hover { background: #8f2727; border-color: #8f2727; color: #ffffff; }

.chart-manage__confirm {
  padding: 0 9px; border-radius: var(--radius-sm); background: var(--danger-surface);
}
.chart-manage__ask { flex: 1 1 auto; font-size: 12.5px; color: var(--danger-ink); }
.chart-manage__note { margin: 7px 2px 0; font-size: 12px; color: var(--text-muted); }
.chart-manage__note:empty { display: none; }

.ask-gap {
  margin-top: 10px; padding: 10px 12px; font-size: 12.5px;
  background: rgba(244, 145, 0, 0.10); border: 1px solid rgba(244, 145, 0, 0.32);
  border-radius: var(--radius-sm); color: #8a5200;
}
.ask-refusal {
  margin-top: 10px; padding: 10px 12px; font-size: 12.5px;
  background: var(--surface-muted, rgba(120, 128, 138, 0.10));
  border: 1px solid rgba(120, 128, 138, 0.30);
  border-radius: var(--radius-sm); color: var(--text-muted);
}
.ask-error {
  padding: 10px 12px; font-size: 13px; color: #a32a2a;
  background: rgba(214, 69, 69, 0.09); border: 1px solid rgba(214, 69, 69, 0.28);
  border-radius: var(--radius-sm);
}

.ask-steps { margin-top: 9px; font-size: 12px; }
.ask-steps summary {
  cursor: pointer; color: var(--text-muted); font-weight: 600;
  list-style: none; padding: 3px 0;
}
.ask-steps summary::-webkit-details-marker { display: none; }
.ask-steps summary::before { content: "▸ "; }
.ask-steps[open] summary::before { content: "▾ "; }
.ask-step { padding: 6px 0; border-bottom: 1px dashed var(--glass-border); }
.ask-step:last-child { border-bottom: 0; }
.ask-step__summary { color: var(--text-secondary); font-weight: 600; }
.ask-step--failed .ask-step__summary { color: #a32a2a; }
.ask-step__detail {
  margin: 4px 0 0; padding: 7px 9px; overflow-x: auto;
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace; font-size: 11px;
  background: rgba(14, 29, 60, 0.045); border-radius: 6px; color: var(--text-secondary);
  white-space: pre-wrap; word-break: break-word;
}
.ask-meta { margin-top: 7px; font-size: 11px; color: var(--text-muted); }

/* Live progress while the tool loop runs. The panel used to show one italic
   "Analysing…" for the whole of a multi-minute run; this shows the run. */
.ask-live {
  display: flex; flex-direction: column; gap: 2px;
  padding: 10px 13px; font-size: 12.5px;
  background: rgba(219, 239, 249, 0.5); border: 1px solid var(--glass-border);
  border-radius: 14px 14px 14px 4px;
}
.ask-live__step {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 3px 0; color: var(--text-muted);
}
.ask-live__step.is-done { color: var(--text-secondary); }
.ask-live__step.is-active { color: var(--text-primary); font-weight: 600; }
.ask-live__step.is-failed { color: var(--danger-ink); }
/* The active row's marker: a dot that pulses. Done rows swap it for a tick, so
   state is carried by shape as well as by colour. */
.ask-live__dot {
  flex: 0 0 auto; width: 14px; height: 14px; margin-top: 3px;
  border-radius: 50%; background: var(--tudor-blue);
  animation: askPulse 1.4s ease-in-out infinite;
}
.ask-live__tick {
  flex: 0 0 auto; width: 14px; height: 14px; margin-top: 3px;
  color: var(--tudor-green);
}
.ask-live__text { min-width: 0; }
@keyframes askPulse { 50% { opacity: 0.35; transform: scale(0.72); } }
@media (prefers-reduced-motion: reduce) {
  .ask-live__dot { animation: none; }
}

/* Verification verdict. Only drawn when something was removed or withheld --
   a clean answer says nothing, because a badge on every answer stops being
   read by the third one. */
.ask-verify {
  display: flex; align-items: flex-start; gap: 9px;
  margin-top: 10px; padding: 10px 12px; font-size: 12.5px;
  border-radius: var(--radius-sm);
  background: rgba(244, 145, 0, 0.10); border: 1px solid rgba(244, 145, 0, 0.32);
  color: #8a5200;
}
.ask-verify--unverified {
  background: var(--danger-surface); border-color: var(--danger-border);
  color: var(--danger-ink);
}
.ask-verify .icon { flex: 0 0 auto; width: 16px; height: 16px; margin-top: 1px; }
.ask-verify__body { min-width: 0; }
.ask-verify__text { margin: 2px 0 0; }
.ask-verify__detail { margin-top: 6px; }
.ask-verify__detail summary {
  cursor: pointer; font-weight: 600; list-style: none; padding: 2px 0;
}
.ask-verify__detail summary::-webkit-details-marker { display: none; }
.ask-verify__detail summary::before { content: "▸ "; }
.ask-verify__detail[open] summary::before { content: "▾ "; }
.ask-verify__removed {
  margin: 4px 0 0; padding: 6px 8px; border-radius: 6px;
  background: rgba(255, 255, 255, 0.55); font-style: italic;
}

/* Disclosure flags: thin bases, raw-table use, a test that failed. Each chip
   carries an icon and words, never colour alone. */
.ask-flags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.ask-flag {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 9px; border-radius: 999px; font-size: 11.5px; font-weight: 600;
  color: #8a5200; background: rgba(244, 145, 0, 0.10);
  border: 1px solid rgba(244, 145, 0, 0.32);
}
.ask-flag .icon { width: 13px; height: 13px; flex: 0 0 auto; }

/* Thumbs on every answer. Quiet until hovered, unmistakable once pressed --
   this is the only control in the panel whose entire job is to be easy enough
   to use that people actually use it. */
.ask-feedback {
  display: flex; flex-wrap: wrap; align-items: center; gap: 7px;
  margin-top: 11px; padding-top: 9px;
  border-top: 1px dashed var(--glass-border);
}
.ask-feedback__label { font-size: 11.5px; color: var(--text-muted); }
.ask-feedback__btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; padding: 0; cursor: pointer;
  border-radius: var(--radius-sm); border: 1px solid transparent;
  background: transparent; color: var(--text-muted);
  transition: background 150ms ease, color 150ms ease, border-color 150ms ease;
}
.ask-feedback__btn .icon { width: 16px; height: 16px; }
.ask-feedback__btn:hover {
  background: rgba(14, 29, 60, 0.05); color: var(--text-primary);
}
.ask-feedback__btn:focus-visible { outline: 2px solid var(--tudor-blue); outline-offset: 2px; }
.ask-feedback__btn--up[aria-pressed="true"] {
  color: #3d6a13; background: rgba(131, 200, 66, 0.16);
  border-color: rgba(131, 200, 66, 0.45);
}
.ask-feedback__btn--down[aria-pressed="true"] {
  color: var(--danger-ink); background: var(--danger-surface);
  border-color: var(--danger-border);
}
.ask-feedback__note { font-size: 11.5px; color: var(--text-muted); }
.ask-feedback__form {
  flex: 1 0 100%; display: flex; gap: 7px; align-items: flex-end; margin-top: 6px;
}
.ask-feedback__form[hidden] { display: none; }
.ask-feedback__text {
  flex: 1 1 auto; resize: none; font-family: var(--font-brand); font-size: 12.5px;
  padding: 8px 10px; border-radius: var(--radius-sm);
  border: 1px solid var(--glass-border-strong); background: #fff;
  color: var(--text-primary);
}
.ask-feedback__text:focus {
  outline: 2px solid var(--tudor-blue); outline-offset: 1px; border-color: transparent;
}
.ask-feedback__send { flex: 0 0 auto; font-size: 12.5px; padding: 7px 13px; }

.ask-form {
  display: flex; gap: 8px; align-items: flex-end;
  padding: 12px 16px 16px; border-top: 1px solid var(--glass-border);
}
.ask-form textarea {
  flex: 1 1 auto; resize: none; font-family: var(--font-brand); font-size: 13.5px;
  padding: 10px 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--glass-border-strong); background: #fff;
  color: var(--text-primary);
}
.ask-form textarea:focus {
  outline: 2px solid var(--tudor-blue); outline-offset: 1px; border-color: transparent;
}
.ask-send:disabled { opacity: 0.55; cursor: not-allowed; }

/* ── Agent review (staff) ──────────────────────────────────────────────────
   A plain reading page: rates, then leads, then the evidence. No cohort rail,
   because it spans every dashboard and has no cohort of its own. */

.rev { max-width: 1180px; margin: 0 auto; padding: 28px 24px 72px; }
.rev__head {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 20px; flex-wrap: wrap; margin-bottom: 22px;
}
.rev__title { margin: 2px 0 0; font-size: 26px; color: var(--tudor-navy); }
.rev__sub { margin: 6px 0 0; max-width: 62ch; font-size: 13.5px; line-height: 1.6; color: var(--text-secondary); }

.rev__controls {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px;
  padding: 14px 16px; margin-bottom: 26px;
  border: 1px solid var(--glass-border-strong); border-radius: var(--radius-md);
  background: rgba(255, 255, 255, 0.82);
}
.rev__field { display: flex; flex-direction: column; gap: 5px; min-width: 170px; flex: 1 1 190px; }
.rev__field label { font-size: 11px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted); }
.rev__field input, .rev__field select {
  min-height: 44px; padding: 8px 11px; font-family: var(--font-brand); font-size: 13.5px;
  border: 1px solid var(--glass-border-strong); border-radius: var(--radius-sm);
  background: #fff; color: var(--text-primary);
}
.rev__field input:focus, .rev__field select:focus {
  outline: 2px solid var(--tudor-blue); outline-offset: 1px; border-color: transparent;
}
.rev__apply { flex: 0 0 auto; min-height: 44px; }

/* The download, beside Apply. Ghost rather than primary: applying the filters
   is the action on this row, and taking a copy away is what you do once you
   are happy with what applying them showed you. */
.rev__export {
  flex: 0 0 auto; min-height: 44px; width: auto;
  display: inline-flex; align-items: center; gap: 8px;
}
.rev__export .icon { width: 16px; height: 16px; flex: 0 0 16px; }
.rev__hint {
  margin: -18px 0 26px; max-width: 78ch;
  font-size: 12px; line-height: 1.55; color: var(--text-muted);
}

.rev__section { margin-bottom: 34px; }
.rev__h2 {
  margin: 0 0 14px; font-size: 12px; font-weight: 700; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--tudor-blue);
}

.rev__cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 14px; }
.rev-card {
  padding: 16px 18px; border-radius: var(--radius-md);
  border: 1px solid var(--glass-border-strong); border-left: 3px solid var(--tudor-blue);
  background: rgba(255, 255, 255, 0.86);
}
/* Warned rather than coloured: the label and the note say what is wrong, the
   tint only draws the eye to them. */
.rev-card--warn { border-left-color: var(--tudor-orange); background: rgba(244, 145, 0, 0.07); }
.rev-card__value { margin: 0; font-size: 28px; font-weight: 700; line-height: 1.1; color: var(--tudor-navy); font-variant-numeric: tabular-nums; }
.rev-card__label { margin: 4px 0 0; font-size: 12.5px; font-weight: 600; color: var(--text-secondary); }
.rev-card__note { margin: 7px 0 0; font-size: 11.5px; line-height: 1.5; color: var(--text-muted); }

.rev__mixes { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; margin-top: 14px; }
.rev-mix {
  padding: 14px 16px; border-radius: var(--radius-md);
  border: 1px solid var(--glass-border); background: rgba(255, 255, 255, 0.72);
}
.rev-mix__title { margin: 0 0 9px; font-size: 12.5px; font-weight: 700; color: var(--tudor-navy); }
.rev-mix__list { list-style: none; margin: 0; padding: 0; }
.rev-mix__list li {
  display: flex; justify-content: space-between; gap: 12px; padding: 5px 0;
  border-bottom: 1px dashed var(--glass-border); font-size: 12.5px;
}
.rev-mix__list li:last-child { border-bottom: 0; }
.rev-mix__name { color: var(--text-secondary); min-width: 0; }
.rev-mix__n { flex: 0 0 auto; font-weight: 700; color: var(--tudor-navy); font-variant-numeric: tabular-nums; }
.rev-mix__empty { margin: 0; font-size: 12.5px; color: var(--text-muted); }

.rev__leads { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 18px; }
.rev-lead {
  padding: 16px 18px; border-radius: var(--radius-md);
  border: 1px solid var(--glass-border-strong); background: rgba(255, 255, 255, 0.86);
  min-width: 0;
}
.rev-lead__title { margin: 0 0 6px; font-size: 14px; color: var(--tudor-navy); }
.rev-lead__note { margin: 0 0 12px; font-size: 12px; line-height: 1.55; color: var(--text-muted); }
.rev-lead__note code { font-size: 11.5px; }

/* Tables scroll inside their own box; the page never scrolls sideways. */
.rev-table { width: 100%; border-collapse: collapse; font-size: 12.5px; display: block; overflow-x: auto; }
.rev-table th, .rev-table td { padding: 7px 9px; text-align: left; border-bottom: 1px solid var(--glass-border); }
.rev-table th { font-size: 11px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--text-muted); white-space: nowrap; }
.rev-num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }

.rev-notes { list-style: none; margin: 0; padding: 0; }
.rev-note { padding: 10px 0; border-bottom: 1px dashed var(--glass-border); }
.rev-note:last-child { border-bottom: 0; }
.rev-note__q { margin: 0; font-size: 12.5px; font-weight: 600; color: var(--text-primary); }
.rev-note__text { margin: 4px 0 0; font-size: 12.5px; line-height: 1.55; color: var(--danger-ink); }
.rev-note__meta { margin: 4px 0 0; font-size: 11px; color: var(--text-muted); }

.rev__filters { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 16px; }
.rev-chip {
  display: inline-flex; align-items: center; min-height: 40px; padding: 0 14px;
  border: 1px solid var(--glass-border-strong); border-radius: 999px;
  background: rgba(255, 255, 255, 0.8); font-size: 12.5px; font-weight: 600;
  color: var(--text-secondary); text-decoration: none;
  transition: background 150ms ease, color 150ms ease, border-color 150ms ease;
}
.rev-chip:hover { border-color: var(--tudor-blue); color: var(--text-primary); text-decoration: none; }
.rev-chip.is-on { background: var(--tudor-blue); border-color: var(--tudor-blue); color: #fff; }
.rev-chip:focus-visible { outline: 2px solid var(--tudor-navy); outline-offset: 2px; }

.rev__cap, .rev__empty {
  margin: 0 0 16px; padding: 11px 14px; border-radius: var(--radius-sm);
  background: rgba(21, 175, 248, 0.08); border: 1px solid rgba(21, 175, 248, 0.28);
  font-size: 12.5px; line-height: 1.55; color: var(--text-secondary);
}

.rev-turns { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 12px; }
.rev-turn {
  padding: 16px 18px; border-radius: var(--radius-md);
  border: 1px solid var(--glass-border-strong); background: rgba(255, 255, 255, 0.88);
}
.rev-turn__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; flex-wrap: wrap; }
.rev-turn__q { margin: 0; font-size: 14.5px; font-weight: 700; line-height: 1.45; color: var(--tudor-navy); max-width: 70ch; }
.rev-turn__marks { display: flex; flex-wrap: wrap; gap: 5px; }
/* Every mark says what it means in words. Colour is a second signal, never
   the only one. */
.rev-mark {
  display: inline-flex; align-items: center; padding: 3px 9px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.02em; white-space: nowrap;
  background: rgba(14, 29, 60, 0.07); color: var(--text-secondary);
}
.rev-mark--ok { background: rgba(29, 122, 60, 0.12); color: #1d7a3c; }
.rev-mark--warn { background: rgba(244, 145, 0, 0.16); color: #8a5200; }
.rev-mark--bad { background: rgba(163, 42, 42, 0.12); color: var(--danger-ink); }

.rev-turn__meta { margin: 8px 0 0; font-size: 11.5px; color: var(--text-muted); }
.rev-turn__a { margin: 10px 0 0; font-size: 13px; line-height: 1.6; color: var(--text-secondary); max-width: 78ch; white-space: pre-wrap; }
.rev-turn__note { margin: 9px 0 0; font-size: 12.5px; line-height: 1.55; color: var(--danger-ink); }

.rev-turn__steps { margin-top: 11px; font-size: 12px; }
.rev-turn__steps summary { cursor: pointer; color: var(--text-muted); font-weight: 600; list-style: none; }
.rev-turn__steps summary::-webkit-details-marker { display: none; }
.rev-turn__steps summary::before { content: "▸ "; }
.rev-turn__steps[open] summary::before { content: "▾ "; }
.rev-turn__steps summary:focus-visible { outline: 2px solid var(--tudor-blue); outline-offset: 2px; }
.rev-step { padding: 7px 0; border-bottom: 1px dashed var(--glass-border); }
.rev-step:last-child { border-bottom: 0; }
.rev-step__summary { margin: 0; font-weight: 600; color: var(--text-secondary); }
.rev-step--failed .rev-step__summary { color: var(--danger-ink); }
.rev-step__detail {
  margin: 5px 0 0; padding: 8px 10px; overflow-x: auto;
  border-radius: var(--radius-sm); background: rgba(14, 29, 60, 0.05);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px;
  line-height: 1.5; white-space: pre;
}

.rev-turn__tools { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 13px; }
.rev-turn__flag { min-height: 44px; font-size: 12.5px; }
.rev-turn__said { font-size: 11.5px; color: var(--text-muted); }

@media (prefers-reduced-motion: reduce) { .rev-chip { transition: none; } }

@media (max-width: 700px) {
  .rev { padding: 20px 16px 56px; }
  .rev__controls { padding: 12px; }
}

/* ── Saved conversations ───────────────────────────────────────────────────
   Below 1024px the rail slides over the thread; at 1024px and up it is simply
   the left column and the panel widens to hold both -- and can be collapsed,
   which hands its 280px to the answer and its charts. */

.ask-panel__tools { display: flex; align-items: center; gap: 2px; flex: 0 0 auto; }
.ask-panel__close {
  min-width: 44px; min-height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
}
.ask-panel__close:focus-visible { outline: 2px solid var(--tudor-blue); outline-offset: 2px; }
.ask-tool {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 44px; padding: 0 10px; border: 0; border-radius: var(--radius-sm);
  background: none; cursor: pointer; font-family: var(--font-brand);
  font-size: 12.5px; font-weight: 600; color: var(--text-secondary);
  transition: background 150ms ease, color 150ms ease;
}
.ask-tool:hover { background: rgba(14, 29, 60, 0.06); color: var(--text-primary); }
.ask-tool:focus-visible { outline: 2px solid var(--tudor-blue); outline-offset: 2px; }
.ask-tool .icon { width: 16px; height: 16px; }
/* The rail's state, on the control that sets it. aria-expanded is already the
   state for a screen reader; this is the same fact for everyone else, so the
   button does not read as inert while the list beside it is open. The tint
   carries it rather than a blue label: --tudor-blue is a light blue and would
   not hold 4.5:1 as text on top of its own 12% wash. */
.ask-tool[aria-expanded="true"] {
  background: rgba(21, 175, 248, 0.12); color: var(--text-primary);
}
/* New conversation, for when the rail that holds the real one is collapsed.
   Icon-only, so it carries an aria-label and a title rather than a word. Shown
   only at the width where collapsing exists -- see the 1024px block. */
.ask-tool--new { display: none; min-width: 44px; padding: 0 12px; }

.ask-panel__body { position: relative; flex: 1 1 auto; display: flex; min-height: 0; }
.ask-main { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; min-height: 0; }

.ask-rail {
  position: absolute; inset: 0 auto 0 0; z-index: 2;
  width: min(300px, 86%);
  display: flex; flex-direction: column;
  background: #fff; border-right: 1px solid var(--glass-border-strong);
  box-shadow: 12px 0 32px rgba(14, 29, 60, 0.14);
  /* visibility, not just transform: an off-screen rail must also be out of the
     tab order and unreadable to a screen reader. */
  visibility: hidden; transform: translateX(-102%);
  transition: transform 220ms ease, visibility 220ms;
}
.ask-panel.is-rail-open .ask-rail { visibility: visible; transform: translateX(0); }
.ask-rail__scrim { position: absolute; inset: 0; z-index: 1; background: rgba(14, 29, 60, 0.42); }
.ask-rail__scrim[hidden] { display: none; }

.ask-rail__head {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 10px 8px 10px 14px; border-bottom: 1px solid var(--glass-border);
}
.ask-rail__title {
  margin: 0; font-size: 11px; font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--text-muted);
}
.ask-rail__new {
  display: inline-flex; align-items: center; gap: 5px;
  min-height: 44px; padding: 0 10px; border: 0; border-radius: var(--radius-sm);
  background: none; cursor: pointer; font-family: var(--font-brand);
  font-size: 12.5px; font-weight: 700; color: var(--tudor-blue);
  transition: background 150ms ease;
}
.ask-rail__new:hover { background: rgba(21, 175, 248, 0.10); }
.ask-rail__new:focus-visible { outline: 2px solid var(--tudor-blue); outline-offset: 2px; }

.ask-rail__list { flex: 1 1 auto; overflow-y: auto; padding: 8px; }
.ask-rail__group {
  margin: 14px 0 5px; padding: 0 4px; font-size: 10.5px; font-weight: 700;
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-muted);
}
.ask-rail__group:first-child { margin-top: 2px; }
.ask-rail__empty, .ask-rail__loading {
  margin: 10px 6px; font-size: 12.5px; line-height: 1.55; color: var(--text-muted);
}

.ask-session {
  display: flex; align-items: center; border-radius: var(--radius-sm);
  transition: background 150ms ease;
}
.ask-session:hover { background: rgba(21, 175, 248, 0.07); }
/* The open thread is marked by a bar and a tint, and by aria-current for
   anyone not seeing either. */
.ask-session.is-current { background: rgba(21, 175, 248, 0.13); box-shadow: inset 3px 0 0 var(--tudor-blue); }
.ask-session__open {
  flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 3px;
  padding: 9px 6px 9px 11px; border: 0; background: none; cursor: pointer;
  text-align: left; font-family: var(--font-brand); color: var(--text-primary);
  border-radius: var(--radius-sm);
}
.ask-session__open:focus-visible { outline: 2px solid var(--tudor-blue); outline-offset: -2px; }
.ask-session__title {
  font-size: 13px; font-weight: 600; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ask-session__meta { font-size: 11px; line-height: 1.4; color: var(--text-muted); }
.ask-session__tools { display: flex; align-items: center; flex: 0 0 auto; }
.ask-session__btn {
  width: 44px; height: 44px; display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: var(--radius-sm); background: none; cursor: pointer;
  color: var(--text-muted); opacity: 0;
  transition: opacity 150ms ease, background 150ms ease, color 150ms ease;
}
/* Revealed on hover and whenever anything inside has focus. An action that
   exists only on hover does not exist to a keyboard or a touch screen — hence
   the hover:none rule below. */
.ask-session:hover .ask-session__btn,
.ask-session:focus-within .ask-session__btn { opacity: 1; }
@media (hover: none) { .ask-session__btn { opacity: 1; } }
.ask-session__btn:hover { background: rgba(14, 29, 60, 0.07); color: var(--text-primary); }
.ask-session__btn:focus-visible {
  opacity: 1; outline: 2px solid var(--tudor-blue); outline-offset: -2px;
}
.ask-session__btn--danger:hover { background: rgba(163, 42, 42, 0.10); color: var(--danger-ink); }
.ask-session__btn .icon { width: 15px; height: 15px; }
.ask-session__rename {
  flex: 1 1 auto; min-width: 0; min-height: 44px; margin: 2px 4px;
  padding: 6px 9px; font-family: var(--font-brand); font-size: 13px;
  border: 1px solid var(--tudor-blue); border-radius: var(--radius-sm);
  background: #fff; color: var(--text-primary);
}
.ask-session__rename:focus { outline: 2px solid var(--tudor-blue); outline-offset: 1px; }

/* Undo: the delete request is held for five seconds, so this is the window in
   which nothing has happened yet. */
.ask-undo {
  position: absolute; left: 16px; right: 16px; bottom: 88px; z-index: 80;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 8px 8px 8px 14px; border-radius: var(--radius-sm);
  background: var(--tudor-navy); color: #fff; font-size: 12.5px;
  box-shadow: 0 12px 30px rgba(14, 29, 60, 0.3);
  animation: askUndoIn 180ms ease;
}
.ask-undo[hidden] { display: none; }
.ask-undo__text { min-width: 0; }
.ask-undo__btn {
  flex: 0 0 auto; min-height: 44px; padding: 0 16px; border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.36); background: rgba(255, 255, 255, 0.14);
  color: #fff; font-family: var(--font-brand); font-size: 12.5px; font-weight: 700;
  cursor: pointer; transition: background 150ms ease;
}
.ask-undo__btn:hover { background: rgba(255, 255, 255, 0.26); }
.ask-undo__btn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
@keyframes askUndoIn { from { transform: translateY(8px); opacity: 0; } }

/* The cohort a reopened thread was answered under, against the one on screen.
   Warning-toned, but it carries an icon and says it in words — the colour is
   never what does the telling. */
.ask-cohort {
  display: flex; gap: 9px; align-items: flex-start;
  margin: 0 0 14px; padding: 11px 13px;
  border: 1px solid rgba(244, 145, 0, 0.45); border-left: 3px solid var(--tudor-orange);
  border-radius: var(--radius-sm); background: rgba(244, 145, 0, 0.09);
  font-size: 12.5px; line-height: 1.5;
}
.ask-cohort__icon { flex: 0 0 auto; width: 16px; height: 16px; margin-top: 1px; color: #8a5200; }
.ask-cohort__body { min-width: 0; }
.ask-cohort__text { margin: 0; color: var(--text-secondary); }
.ask-cohort__btn { margin-top: 9px; font-size: 12.5px; padding: 8px 13px; }

/* A replayed chart whose query no longer runs. */
.ask-stale {
  display: flex; gap: 7px; align-items: flex-start; margin-top: 9px;
  font-size: 11.5px; line-height: 1.45; color: var(--text-muted);
}
.ask-stale .icon { flex: 0 0 auto; width: 14px; height: 14px; margin-top: 1px; }

@media (min-width: 1024px) {
  .ask-panel { width: min(780px, 100vw); }
  .ask-rail {
    position: static; flex: 0 0 280px; width: 280px;
    visibility: visible; transform: none; box-shadow: none;
    /* Collapsing a flex column is a size change, so this is one of the few
       places width has to be the animated property -- there is nothing to
       translate, because the point is that the neighbour takes the space. One
       element, no reflow of anything but its sibling, at the same 220ms as the
       overlay it replaces at this width. */
    overflow: hidden;
    transition: flex-basis 220ms ease, width 220ms ease, visibility 220ms;
  }
  .ask-panel.is-rail-collapsed .ask-rail {
    flex-basis: 0; width: 0; border-right-width: 0;
    /* Not just zero-width: a rail nobody can see must also be out of the tab
       order and unreadable to a screen reader. Transitioned, so it holds until
       the collapse has finished rather than blanking on frame one. */
    visibility: hidden;
  }
  /* The rail took New conversation off screen with it, so the header holds one
     for as long as that is true. Scoped to this width because below it the rail
     is an overlay and its own New is one tap away. */
  .ask-panel.is-rail-collapsed .ask-tool--new { display: inline-flex; }
  .ask-rail__scrim { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .ask-rail, .ask-session, .ask-session__btn, .ask-tool,
  .ask-rail__new, .ask-undo__btn { transition: none; }
  .ask-undo { animation: none; }
}

@media (max-width: 700px) {
  .ask-fab span { display: none; }
  .ask-fab { padding: 14px; right: 16px; bottom: 16px; }
}

/* Stacked shell: the rail becomes a banner. The body keeps its own scroll and
   is capped, so a long filter list can't push the charts off the screen. */
@media (max-width: 900px) {
  .app-shell { flex-direction: column; }
  .sidebar {
    position: static; width: 100%; height: auto; flex-basis: auto;
    grid-template-rows: auto auto auto;
  }
  .sidebar__head {
    display: flex; align-items: center; justify-content: space-between; gap: 18px;
    padding: 14px 18px;
  }
  .sidebar__brand img { width: 118px; margin: 0; }
  .sidebar__eyebrow { margin: 0; }
  .sidebar__body { max-height: 52vh; }
  .sidebar__foot {
    display: flex; flex-wrap: wrap; align-items: center;
    justify-content: space-between; gap: 12px 16px;
  }
  .account { padding: 0; }
  /* Its own line: a third item in the banner row would crowd the account block
     and Sign out at 375px. */
  .sidebar__powered { flex: 1 0 100%; margin: 0; padding-top: 12px; }
  .btn--signout { width: auto; padding-inline: 18px; }
  .main { padding: 18px; }
  /* Touch sizing for the chart controls; on a pointer device they stay compact
     so they do not compete with the figure above them. */
  .chart-manage__btn, .chart-manage__select { min-height: 44px; }
  .chart-manage__bar { min-height: 44px; }
}
