/* ==========================================================================
   Acme Corporation — "Wiley" internal ops assistant
   NC GOTV design system.  Warm chrome + validated data palette.

   Data-series colors are the categorical slots. Validated against the surfaces
   this app ACTUALLY renders on (light #fafbfc from theme.py's chrome override,
   dark #1c1917), not the ones the palette was first authored against:

     adjacent pairs   PASS in both modes
     ALL pairs        FAIL — light magenta/orange dE 12.9 (<15 floor)
                             dark  magenta/aqua   dE  1.6 (deutan)
     contrast         light: aqua/yellow/magenta below 3:1

   So charts.py hard-caps simultaneous categorical hues at THREE (slots 1-3,
   which pass all-pairs in both modes) and folds any tail into one gray
   "Other". Slots 4 and 5 stay defined but must not be used for a 4th series.
   Every chart also ships direct labels + a table view, which is what
   discharges the light-mode contrast WARN.

   Brand chrome (slate ground, safety-orange accent) is deliberately kept OFF
   the data layer so nothing in the UI impersonates a series color.
   ========================================================================== */

:root {
  color-scheme: light;

  /* --- surfaces & ink --- */
  --page:            #f4eee4;
  --surface-1:       #fbf8f3;
  --surface-2:       #f7f2e9;
  --surface-sunk:    #efe8db;
  --text-primary:    #1c1917;
  --text-secondary:  #57534e;
  --text-muted:      #8a8178;
  --gridline:        #e8e0d3;
  --baseline:        #cfc4b4;
  --border:          rgba(28, 25, 23, 0.11);
  --border-strong:   rgba(28, 25, 23, 0.18);
  --shadow-card:     0 1px 2px rgba(61, 44, 30, 0.05), 0 1px 12px rgba(61, 44, 30, 0.04);
  --shadow-pop:      0 4px 24px rgba(61, 44, 30, 0.16);

  /* --- brand chrome (never used for data series) --- */
  --bark-900:        #241a12;
  --bark-800:        #2f2218;
  --bark-700:        #3d2c1e;
  --bark-600:        #55402d;
  --rust:            #9a3412;
  --rust-hover:      #7c2d0f;
  --kraft:           #e7dbc6;
  --cream:           #f6efe2;

  /* --- data: categorical slots, fixed order, never cycled --- */
  --series-1:        #2a78d6;  /* blue    */
  --series-2:        #eb6834;  /* orange  */
  --series-3:        #1baf7a;  /* aqua    */
  --series-4:        #eda100;  /* yellow  */
  --series-5:        #e87ba4;  /* magenta */

  /* --- data: sequential (one hue, light -> dark) --- */
  --seq-100: #cde2fb;  --seq-200: #9ec5f4;  --seq-300: #6da7ec;
  --seq-400: #3987e5;  --seq-500: #256abf;  --seq-600: #184f95;
  --seq-700: #0d366b;

  /* --- data: status (reserved; always paired with icon + label) --- */
  --good:     #0ca30c;
  --warning:  #fab219;
  --serious:  #ec835a;
  --critical: #d03b3b;
  --good-text: #006300;

  --radius:   10px;
  --radius-sm: 6px;
  --sans: system-ui, -apple-system, "Segoe UI", sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) {
    color-scheme: dark;
    --page:           #12100e;
    --surface-1:      #1c1917;
    --surface-2:      #221e1a;
    --surface-sunk:   #17140f;
    --text-primary:   #ffffff;
    --text-secondary: #cfc7bb;
    --text-muted:     #8a8178;
    --gridline:       #2e2a26;
    --baseline:       #3a352f;
    --border:         rgba(255, 255, 255, 0.11);
    --border-strong:  rgba(255, 255, 255, 0.18);
    --shadow-card:    0 1px 2px rgba(0, 0, 0, 0.4);
    --shadow-pop:     0 4px 24px rgba(0, 0, 0, 0.55);
    --kraft:          #2f2218;
    --cream:          #f6efe2;
    --rust:           #c2571f;
    --rust-hover:     #d9662a;

    --series-1: #3987e5;  --series-2: #d95926;  --series-3: #199e70;
    --series-4: #c98500;  --series-5: #d55181;

    --seq-100: #0d366b;  --seq-200: #184f95;  --seq-300: #256abf;
    --seq-400: #3987e5;  --seq-500: #6da7ec;  --seq-600: #9ec5f4;
    --seq-700: #cde2fb;

    --good-text: #0ca30c;
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --page:           #12100e;
  --surface-1:      #1c1917;
  --surface-2:      #221e1a;
  --surface-sunk:   #17140f;
  --text-primary:   #ffffff;
  --text-secondary: #cfc7bb;
  --text-muted:     #8a8178;
  --gridline:       #2e2a26;
  --baseline:       #3a352f;
  --border:         rgba(255, 255, 255, 0.11);
  --border-strong:  rgba(255, 255, 255, 0.18);
  --shadow-card:    0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-pop:     0 4px 24px rgba(0, 0, 0, 0.55);
  --kraft:          #2f2218;
  --rust:           #c2571f;
  --rust-hover:     #d9662a;

  --series-1: #3987e5;  --series-2: #d95926;  --series-3: #199e70;
  --series-4: #c98500;  --series-5: #d55181;

  --seq-100: #0d366b;  --seq-200: #184f95;  --seq-300: #256abf;
  --seq-400: #3987e5;  --seq-500: #6da7ec;  --seq-600: #9ec5f4;
  --seq-700: #cde2fb;

  --good-text: #0ca30c;
}

/* ==========================  base  ========================== */

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  font-family: var(--sans);
  background: var(--page);
  color: var(--text-primary);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; }

h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -0.01em; }

/* ==========================  app shell  ========================== */

.app { display: grid; grid-template-columns: 232px 1fr; min-height: 100vh; }

.sidebar {
  background: var(--bark-800);
  color: var(--cream);
  padding: 18px 0 24px;
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  overflow-y: auto;
}

.brand { display: flex; gap: 10px; align-items: center; padding: 0 18px 18px; }

.brand-mark {
  width: 34px; height: 34px; border-radius: 8px;
  background: linear-gradient(160deg, #c2571f, #8a3a10);
  display: grid; place-items: center; flex: 0 0 auto;
}
.brand-mark svg { width: 20px; height: 20px; }

.brand-name { font-weight: 650; font-size: 13.5px; line-height: 1.25; }
.brand-sub  { font-size: 11px; color: #bcae99; letter-spacing: 0.02em; }

.nav-label {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.09em;
  color: #9c8d78; padding: 12px 18px 6px; font-weight: 600;
}

.nav a {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 18px; text-decoration: none;
  color: #ded2be; font-size: 13.5px; border-left: 3px solid transparent;
}
.nav a:hover { background: rgba(255,255,255,0.05); color: #fff; }
.nav a.active {
  background: rgba(255,255,255,0.08); color: #fff;
  border-left-color: var(--rust); font-weight: 550;
}
.nav a svg { width: 16px; height: 16px; opacity: 0.85; flex: 0 0 auto; }

.sidebar-foot {
  margin-top: auto; padding: 14px 18px 0; font-size: 11px; color: #9c8d78;
  border-top: 1px solid rgba(255,255,255,0.09);
}

.main { min-width: 0; display: flex; flex-direction: column; }

.topbar {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 26px; background: var(--surface-1);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 20;
}
.topbar h1 { font-size: 17px; }
.topbar .sub { color: var(--text-secondary); font-size: 12.5px; }
.topbar-right { margin-left: auto; display: flex; align-items: center; gap: 10px; }

.content { padding: 22px 26px 60px; max-width: 1500px; }

/* ==========================  bits  ========================== */

.btn {
  font: inherit; font-size: 13px; font-weight: 550;
  padding: 7px 13px; border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong); background: var(--surface-1);
  color: var(--text-primary); cursor: pointer; display: inline-flex;
  align-items: center; gap: 7px; white-space: nowrap;
}
.btn:hover { background: var(--surface-2); }
.btn-primary { background: var(--rust); border-color: var(--rust); color: #fff; }
.btn-primary:hover { background: var(--rust-hover); border-color: var(--rust-hover); }
.btn-sm { padding: 4px 9px; font-size: 12px; }
.btn svg { width: 14px; height: 14px; }

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 9px; border-radius: 999px; font-size: 12px;
  background: var(--surface-sunk); border: 1px solid var(--border);
  color: var(--text-secondary); white-space: nowrap;
}

.pill-source {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; color: var(--text-secondary);
  background: var(--surface-sunk); border: 1px solid var(--border);
  border-radius: 999px; padding: 2px 8px;
}

.card {
  background: var(--surface-1); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-card);
  padding: 16px 18px;
}
.card-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 2px; }
.card-head h3 { font-size: 14.5px; }
.card-head .spacer { margin-left: auto; }
.card-sub { color: var(--text-secondary); font-size: 12.5px; margin: 0 0 12px; }

.grid { display: grid; gap: 16px; }
.g-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.g-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.g-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.g-2-1 { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); }
.g-1-2 { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); }

@media (max-width: 1150px) {
  .g-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .g-3, .g-2, .g-2-1, .g-1-2 { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 780px) {
  .app { grid-template-columns: 1fr; }
  .sidebar { position: static; height: auto; }
  .g-4 { grid-template-columns: minmax(0, 1fr); }
}

/* --- section heading --- */
.section-head { margin: 26px 0 12px; display: flex; align-items: baseline; gap: 10px; }
.section-head:first-child { margin-top: 0; }
.section-head h2 { font-size: 15.5px; }
.section-head p { margin: 0; color: var(--text-secondary); font-size: 12.5px; }

/* --- stat tile --- */
.stat { display: flex; flex-direction: column; gap: 3px; }
.stat-label { font-size: 12.5px; color: var(--text-secondary); }
.stat-value { font-size: 27px; font-weight: 620; letter-spacing: -0.02em; line-height: 1.1; }
.stat-row { display: flex; align-items: flex-end; gap: 10px; }
.stat-delta { font-size: 12px; font-weight: 550; display: inline-flex; align-items: center; gap: 3px; }
.delta-up   { color: var(--good-text); }
.delta-down { color: var(--critical); }
.stat-foot { font-size: 11.5px; color: var(--text-muted); }
.stat-spark { margin-top: 6px; }

/* --- hero figure --- */
.hero-fig {
  font-size: 52px; font-weight: 640; letter-spacing: -0.03em; line-height: 1;
}
.hero-unit { font-size: 20px; font-weight: 550; color: var(--text-secondary); }

/* --- status --- */
.status { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 550; white-space: nowrap; }
.status svg { width: 13px; height: 13px; flex: 0 0 auto; }
.s-good     { color: var(--good-text); }
.s-warning  { color: #8a5b00; }
.s-serious  { color: #9c4218; }
.s-critical { color: var(--critical); }
:root[data-theme="dark"] .s-warning { color: var(--warning); }
:root[data-theme="dark"] .s-serious { color: var(--serious); }
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) .s-warning { color: var(--warning); }
  :root:where(:not([data-theme="light"])) .s-serious { color: var(--serious); }
}

/* --- tables --- */
table.data { width: 100%; border-collapse: collapse; font-size: 13px; }
table.data th {
  text-align: left; font-weight: 600; font-size: 11.5px; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text-muted);
  padding: 6px 10px; border-bottom: 1px solid var(--border-strong); white-space: nowrap;
}
table.data td {
  padding: 7px 10px; border-bottom: 1px solid var(--gridline);
  vertical-align: middle;
}
table.data tbody tr:last-child td { border-bottom: none; }
table.data tbody tr:hover { background: var(--surface-2); }
table.data .num { text-align: right; font-variant-numeric: tabular-nums; }
table.data .sku { color: var(--text-muted); font-size: 11.5px; font-variant-numeric: tabular-nums; }
.table-wrap { overflow-x: auto; }

/* --- legend --- */
.legend { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; font-size: 12.5px; color: var(--text-secondary); }
.legend-item { display: inline-flex; align-items: center; gap: 6px; }
.legend-swatch { width: 11px; height: 11px; border-radius: 3px; flex: 0 0 auto; }
.legend-line { width: 14px; height: 2px; border-radius: 2px; flex: 0 0 auto; }
.legend-line.dashed { background: none !important; border-top: 2px dashed currentColor; height: 0; }

/* --- chart plumbing --- */
.chart { position: relative; }
.chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.stat-spark svg { display: block; height: auto; }
.chart-foot { display: flex; align-items: center; gap: 12px; margin-top: 10px; flex-wrap: wrap; }
.chart-foot .spacer { margin-left: auto; }

.viz-tooltip {
  position: fixed; pointer-events: none; z-index: 60; opacity: 0;
  transition: opacity 90ms linear;
  background: var(--surface-1); border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-pop);
  padding: 8px 10px; font-size: 12px; min-width: 128px; max-width: 260px;
}
.viz-tooltip.on { opacity: 1; }
.viz-tt-title { font-size: 11.5px; color: var(--text-secondary); margin-bottom: 5px; }
.viz-tt-row { display: flex; align-items: center; gap: 7px; margin-top: 3px; }
.viz-tt-key { width: 12px; height: 2px; border-radius: 2px; flex: 0 0 auto; }
.viz-tt-val { font-weight: 620; font-variant-numeric: tabular-nums; }
.viz-tt-name { color: var(--text-secondary); margin-left: auto; font-size: 11.5px; }

.table-view { display: none; margin-top: 10px; }
.table-view.on { display: block; }
.chart-hidden { display: none; }

.axis-label { font-size: 11px; fill: var(--text-muted); font-variant-numeric: tabular-nums; }
.axis-title { font-size: 11px; fill: var(--text-muted); }
.mark-label { font-size: 11.5px; fill: var(--text-primary); font-weight: 550; font-variant-numeric: tabular-nums; }
.mark-label-sec { font-size: 11px; fill: var(--text-secondary); font-variant-numeric: tabular-nums; }

/* --- meter --- */
.meter { height: 7px; border-radius: 4px; background: var(--surface-sunk); overflow: hidden; }
.meter-fill { height: 100%; border-radius: 4px; }

/* --- filter row --- */
.filters {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 12px; background: var(--surface-1);
  border: 1px solid var(--border); border-radius: var(--radius);
  margin-bottom: 18px;
}
.filters .lbl { font-size: 12px; color: var(--text-muted); }
select, input[type="text"], input[type="search"] {
  font: inherit; font-size: 13px; padding: 6px 9px; border-radius: var(--radius-sm);
  border: 1px solid var(--border-strong); background: var(--surface-1);
  color: var(--text-primary);
}

/* --- callout / boundary note --- */
.note {
  border-left: 3px solid var(--rust); background: var(--surface-2);
  padding: 12px 14px; border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: 13px; color: var(--text-secondary);
}
.note strong { color: var(--text-primary); }

.mock-banner {
  background: var(--kraft); color: var(--bark-700);
  border-bottom: 1px solid var(--border);
  font-size: 12px; padding: 6px 26px; display: flex; gap: 8px; align-items: center;
}
:root[data-theme="dark"] .mock-banner { color: var(--cream); }
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) .mock-banner { color: var(--cream); }
}
.mock-banner svg { width: 13px; height: 13px; flex: 0 0 auto; }

/* ==========================  chat (Wiley)  ========================== */

.chat-wrap { display: grid; grid-template-columns: minmax(0,1fr) 300px; gap: 16px; align-items: start; }
@media (max-width: 1150px) { .chat-wrap { grid-template-columns: minmax(0,1fr); } }

.thread { display: flex; flex-direction: column; gap: 16px; }

.msg { display: flex; gap: 11px; }
.msg-avatar {
  width: 28px; height: 28px; border-radius: 7px; flex: 0 0 auto;
  display: grid; place-items: center; font-size: 11.5px; font-weight: 650;
}
.msg-avatar.user { background: var(--surface-sunk); color: var(--text-secondary); border: 1px solid var(--border); }
.msg-avatar.bot  { background: linear-gradient(160deg, #c2571f, #8a3a10); color: #fff; }
.msg-avatar svg { width: 15px; height: 15px; }
.msg-body { min-width: 0; flex: 1; }
.msg-who { font-size: 11.5px; color: var(--text-muted); margin-bottom: 4px; font-weight: 550; }
.msg.user .bubble {
  background: var(--surface-sunk); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 9px 12px; font-size: 13.5px;
  display: inline-block; max-width: 68ch;
}
.msg.bot .bubble { font-size: 13.5px; }
.msg.bot .bubble p { margin: 0 0 9px; }
.msg.bot .bubble p:last-child { margin-bottom: 0; }
.msg.bot .bubble ul { margin: 0 0 9px; padding-left: 18px; }
.msg.bot .bubble li { margin-bottom: 3px; }

.bot-card {
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-1); padding: 14px 16px; margin: 10px 0;
  box-shadow: var(--shadow-card);
}
.bot-card-head { font-size: 12.5px; color: var(--text-secondary); margin-bottom: 10px; display: flex; align-items: center; gap: 8px; }
.bot-card-head .spacer { margin-left: auto; }

.sources { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 9px; align-items: center; }
.sources .lbl { font-size: 11px; color: var(--text-muted); }

.composer {
  display: flex; gap: 9px; align-items: flex-end; margin-top: 18px;
  background: var(--surface-1); border: 1px solid var(--border-strong);
  border-radius: var(--radius); padding: 10px 12px; box-shadow: var(--shadow-card);
}
.composer textarea {
  flex: 1; border: none; background: none; resize: none; font: inherit;
  font-size: 13.5px; color: var(--text-primary); outline: none; min-height: 40px;
}
.composer textarea::placeholder { color: var(--text-muted); }

.suggest { display: flex; flex-direction: column; gap: 7px; }
.suggest button {
  text-align: left; font: inherit; font-size: 12.5px; cursor: pointer;
  padding: 8px 10px; border-radius: var(--radius-sm);
  border: 1px solid var(--border); background: var(--surface-1);
  color: var(--text-secondary); line-height: 1.35;
}
.suggest button:hover { background: var(--surface-2); color: var(--text-primary); border-color: var(--border-strong); }

/* ==========================  print  ========================== */

@media print {
  .sidebar, .topbar, .mock-banner, .filters, .composer, .suggest { display: none !important; }
  .app { display: block; }
  .content { padding: 0; }
  .card { break-inside: avoid; box-shadow: none; }
  body { background: #fff; }
}

.stat-label{text-transform:uppercase;letter-spacing:.06em;font-size:11px;
 font-weight:600;color:var(--text-secondary)}
table.data thead th{cursor:pointer;user-select:none}
table.data thead th:hover{color:var(--text-primary)}
.sort-arrow{color:var(--rust);font-size:10px}
.tbl-filter{margin:0 0 8px;display:flex;gap:8px;align-items:center}
/* The export sits to the right of the filter and stays out of the way until
   wanted -- it is a convenience, not the point of the table. */
.tbl-csv{margin-left:auto;flex:0 0 auto;opacity:.75}
.tbl-csv:hover{opacity:1}
.tbl-filter input{width:min(320px,100%);box-sizing:border-box;font:inherit;
 font-size:12.5px;padding:7px 10px;border-radius:var(--radius-sm);
 border:1px solid var(--border-strong);background:var(--surface-1);
 color:var(--text-primary)}
td a{color:var(--text-primary)}
td a:hover{color:var(--rust)}

/* Narrow windows (a half-screen snap, a phone): the sidebar becomes a
   slide-in drawer behind a hamburger, instead of a full-viewport wall of nav
   the reader must scroll past to reach any content. */
.navbtn{display:none;width:34px;height:34px;border:1px solid var(--border-strong);
 border-radius:var(--radius-sm);background:var(--surface-1);
 color:var(--text-primary);cursor:pointer;place-items:center;flex:0 0 auto}
.navbtn svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:2;
 stroke-linecap:round}
.nav-scrim{display:none}

/* Soft navigation. Nothing is shown for the first 150ms -- these pages answer
   in about 35ms, and an indicator that appears and vanishes reads as exactly
   the flicker this replaced. Past that it is a dimmed content pane and a
   progress cursor, so a genuinely slow click is visibly a click and not a
   dead one. */
body.navloading{cursor:progress}
body.navloading .content{opacity:.55;transition:opacity .12s ease}

@media (max-width:900px){
  .app{grid-template-columns:1fr}
  .sidebar{position:fixed;top:0;bottom:0;left:0;width:min(300px,84vw);
   height:100vh;overflow-y:auto;z-index:80;
   transform:translateX(-102%);transition:transform .16s ease;
   box-shadow:var(--shadow-pop)}
  body.nav-open .sidebar{transform:none}
  .navbtn{display:grid}
  .nav-scrim{position:fixed;inset:0;background:rgba(10,8,6,.5);z-index:79}
  body.nav-open .nav-scrim{display:block}
  .topbar{flex-wrap:wrap;gap:8px}
  .grid.g-3,.grid.g-4{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:560px){
  .grid.g-2,.grid.g-3,.grid.g-4,.grid.g-2-1,.grid.g-1-2{
   grid-template-columns:minmax(0,1fr)}
  .content{padding:14px}
}
.barlist{display:flex;flex-direction:column;gap:9px;margin-top:4px}
.barlist .row{display:grid;grid-template-columns:minmax(88px,34%) 1fr auto;
 gap:10px;align-items:center}
.barlist .nm{font-size:12.5px;color:var(--text-secondary);overflow:hidden;
 text-overflow:ellipsis;white-space:nowrap}
.barlist .vl{font-size:12.5px;font-variant-numeric:tabular-nums;
 color:var(--text-primary);font-weight:550}
.caveat{margin-top:12px;font-size:12.5px;color:var(--text-secondary);
 border-left:3px solid var(--warning);background:var(--surface-2);
 padding:9px 12px;border-radius:0 var(--radius-sm) var(--radius-sm) 0}
.caveat b{color:var(--text-primary)}
.empty{color:var(--text-muted);font-size:12.5px;padding:6px 0}
.freshness{font-size:11.5px;color:var(--text-muted);display:flex;gap:14px;
 align-items:center;margin-right:4px}
.freshness b{color:var(--text-secondary);font-weight:550}
.hero-card{display:flex;flex-direction:column;justify-content:center;gap:2px}
.hero-card .stat-label{margin-bottom:2px}
.brief-slot:empty{display:none}
.brief-load{color:var(--text-muted);font-size:12.5px}
.brief h4{margin:14px 0 4px;font-size:13px;color:var(--text-primary)}
.brief .tag{display:inline-block;font-size:11px;color:var(--text-secondary);
 background:var(--surface-sunk);border-radius:999px;padding:2px 9px;margin:0 6px 6px 0}

.wiley-launcher{position:fixed;right:22px;bottom:22px;z-index:70;display:flex;
 align-items:center;gap:9px;padding:11px 16px 11px 12px;border:none;
 border-radius:999px;cursor:pointer;font:inherit;font-size:13.5px;
 font-weight:560;color:#fff;box-shadow:var(--shadow-pop)}
.wiley-launcher:hover{filter:brightness(1.06)}
.wiley-launcher .av{width:22px;height:22px;border-radius:50%;
 background:rgba(255,255,255,.22);display:grid;place-items:center;
 font-size:12px;font-weight:700}
.wiley-launcher.hidden{display:none}

/* Size is a pair of custom properties so a drag can set it without touching
   the anchor: the panel grows from its top-left and stays pinned bottom-right. */
.wiley-panel{position:fixed;right:22px;bottom:22px;z-index:71;
 width:var(--wiley-w,392px);height:var(--wiley-h,620px);
 max-width:calc(100vw - 44px);max-height:calc(100vh - 44px);
 display:none;flex-direction:column;
 background:var(--surface-1);border:1px solid var(--border-strong);
 border-radius:var(--radius);box-shadow:var(--shadow-pop);overflow:hidden}
.wiley-panel.on{display:flex}
.wiley-panel.expanded{right:24px;left:24px;top:24px;bottom:24px;width:auto;
 height:auto}
/* The grip. Top-left because that is the only corner that grows the panel
   away from the corner it is anchored to. */
.wiley-grip{position:absolute;left:0;top:0;width:20px;height:20px;
 cursor:nwse-resize;z-index:2;touch-action:none}
.wiley-grip::before{content:"";position:absolute;left:6px;top:6px;width:8px;
 height:8px;border-left:2px solid var(--text-muted);border-top:2px solid var(--text-muted);
 border-radius:2px 0 0 0;opacity:.5}
.wiley-grip:hover::before{opacity:1}
.wiley-panel.expanded .wiley-grip{display:none}
.wiley-panel.resizing{user-select:none}
@media (max-width:520px){.wiley-grip{display:none}}

.wiley-head{display:flex;align-items:center;gap:9px;padding:11px 12px;
 border-bottom:1px solid var(--border);background:var(--surface-2);flex:0 0 auto}
.wiley-head .who{font-size:13px;font-weight:600;color:var(--text-primary)}
.wiley-head .sub{font-size:11.5px;color:var(--text-muted)}
.wiley-head .spacer{margin-left:auto}
.wiley-ico{width:28px;height:28px;border-radius:var(--radius-sm);border:none;
 background:transparent;color:var(--text-secondary);cursor:pointer;
 display:grid;place-items:center;padding:0}
.wiley-ico:hover{background:var(--surface-sunk);color:var(--text-primary)}
.wiley-ico svg{width:15px;height:15px;fill:none;stroke:currentColor;
 stroke-width:2;stroke-linecap:round;stroke-linejoin:round}

.wiley-body{flex:1 1 auto;overflow-y:auto;padding:14px 12px;min-height:0}
.wiley-foot{flex:0 0 auto;padding:10px 12px;border-top:1px solid var(--border);
 background:var(--surface-1)}
.wiley-panel .composer{margin:0}
.wiley-panel .composer textarea{min-height:44px;max-height:120px}

/* The standalone page: the SAME workspace the expanded panel renders -- a
   dedicated window is not a lesser surface, it is the same surface without
   the window buttons (expand/pop-out/close mean nothing in a tab of one's
   own). The grid rules below therefore target both. */
.wiley-standalone{height:100vh;display:grid;grid-template-rows:auto 1fr auto;
 grid-template-columns:var(--wiley-hist-w,300px) 1fr}

@media (max-width:520px){
  .wiley-panel{right:0;left:0;bottom:0;top:0;width:auto;height:auto;
   border-radius:0;border:none}
  .wiley-launcher{right:14px;bottom:14px}
}

/* Past conversations. In the corner panel this is a SIDE pane (see the
   .histopen rules below); these are the shared looks -- the rows, the filter,
   the grouping -- that every surface renders identically. */
.wiley-sessions{flex:0 0 auto;max-height:240px;overflow-y:auto;
 border-bottom:1px solid var(--border);background:var(--surface-2)}
.wiley-sessions[hidden]{display:none}
.wiley-sessions .row{display:flex;align-items:center;gap:6px;padding:7px 12px;
 border-bottom:1px solid var(--border)}
.wiley-sessions .row:last-child{border-bottom:none}
.wiley-sessions .nm{flex:1;min-width:0;font-size:12.5px;color:var(--text-primary);
 background:none;border:none;text-align:left;cursor:pointer;padding:0;font:inherit;
 overflow:hidden;line-height:1.35}
.wiley-sessions .nm:hover{color:var(--rust)}
.wiley-sessions .nm.on{font-weight:620}
.wiley-sessions .act{width:22px;height:22px;border:none;background:transparent;
 color:var(--text-muted);cursor:pointer;display:grid;place-items:center;padding:0;
 border-radius:4px;flex:0 0 auto}
.wiley-sessions .act:hover{background:var(--surface-sunk);color:var(--text-primary)}
.wiley-sessions .act svg{width:13px;height:13px;fill:none;stroke:currentColor;
 stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.wiley-sessions .none{padding:12px;font-size:12.5px;color:var(--text-muted)}
.wiley-anon{padding:8px 12px;font-size:11.5px;color:var(--text-muted);
 border-bottom:1px solid var(--border);background:var(--surface-2)}
.wiley-anon a{color:var(--rust)}
.wiley-sessions .grp{padding:9px 12px 4px;font-size:10.5px;font-weight:650;
 letter-spacing:.06em;text-transform:uppercase;color:var(--text-muted)}
.wiley-sessions .when{font-size:10.5px;color:var(--text-muted);display:block}
.wiley-sfilter{padding:8px 10px;border-bottom:1px solid var(--border)}
.wiley-sfilter input{width:100%;box-sizing:border-box;font:inherit;font-size:12.5px;
 padding:7px 10px;border-radius:var(--radius-sm);border:1px solid var(--border-strong);
 background:var(--surface-1);color:var(--text-primary)}
.wiley-shead{display:flex;align-items:center;gap:8px;padding:10px 12px 6px}
.wiley-shead .t{font-size:12.5px;font-weight:650;color:var(--text-primary);flex:1}
.wiley-shead .btn{font-size:11.5px;padding:3px 9px}
/* A pane that overlays the thread needs a way out that is not "find the
   button you opened it with". In a workspace the pane IS the layout, so there
   is nothing to shut and the control is hidden rather than forked away. */
.wiley-panel.expanded .wiley-shut,.wiley-standalone .wiley-shut{display:none}

/* THE CORNER PANEL'S HISTORY IS A SIDE PANE, NOT A DROPDOWN.
   It used to slide down under the header and cover the top of the
   conversation -- you opened your past chats by burying the present one, and
   the two surfaces taught two different shapes for one feature. Past
   conversations now sit beside the thread, on the left, exactly where the
   expanded workspace puts them.

   At the default 392px it OVERLAYS, because a panel that narrow split in two
   is not a chat. Dragged wide enough to hold both (.histwide, measured in JS
   from the size the reader actually chose with the grip -- not a media query,
   which asks about the window) it becomes a REAL column and the conversation
   sits beside it: the full-screen layout, at whatever size you have made the
   panel. Grid either way, not absolute positioning, so nothing has to know how
   tall the header is. */
.wiley-panel.histopen:not(.expanded){display:grid;grid-template-rows:auto 1fr auto;
 grid-template-columns:min(258px,74%) 1fr}
.wiley-panel.histopen:not(.expanded) .wiley-head{grid-column:1/-1}
.wiley-panel.histopen:not(.expanded) .wiley-sessions:not([hidden]){grid-column:1;
 grid-row:2/4;max-height:none;border-bottom:none;
 border-right:1px solid var(--border-strong);display:flex;flex-direction:column;
 overflow-y:auto;z-index:2;box-shadow:6px 0 18px rgba(0,0,0,.22);
 animation:wileyslide .14s ease-out}
.wiley-panel.histopen:not(.expanded) .wiley-body{grid-column:1/-1;grid-row:2}
.wiley-panel.histopen:not(.expanded) .wiley-foot{grid-column:1/-1;grid-row:3}
@keyframes wileyslide{from{transform:translateX(-9%);opacity:.35}
 to{transform:none;opacity:1}}

/* THE SPLITTER between the pane and the conversation.
   A SIBLING of the pane, never a child: the pane scrolls, and a handle inside
   a scrolling box scrolls away with the list. It is placed on the same grid
   line, pulled half its width left, so the hit area straddles the border the
   eye is aiming at rather than sitting beside it. Invisible until hovered,
   because a permanent bar between two panes is chrome nobody asked for.

   It exists only where the pane IS a column -- while it floats over the
   conversation there is no boundary to drag, and on a phone there is no
   column at all. Written as `.wiley-sessions:not([hidden]) + .wiley-hsplit`
   so a pane that is not on screen cannot leave a handle behind. */
.wiley-hsplit{display:none;grid-column:1;grid-row:2/4;justify-self:end;
 width:9px;margin-right:-5px;z-index:4;cursor:col-resize;touch-action:none;
 background:transparent}
.wiley-hsplit::before{content:"";position:absolute;left:3px;top:50%;
 width:3px;height:34px;margin-top:-17px;border-radius:2px;
 background:var(--text-muted);opacity:0}
.wiley-hsplit{position:relative}
.wiley-hsplit:hover::before,.wiley-hsplit.dragging::before{opacity:.55}
.wiley-hsplit:hover,.wiley-hsplit.dragging{background:rgba(127,127,127,.14)}
.wiley-panel.expanded .wiley-sessions:not([hidden]) + .wiley-hsplit,
.wiley-standalone .wiley-sessions:not([hidden]) + .wiley-hsplit,
.wiley-panel.histopen.histwide:not(.expanded) .wiley-sessions:not([hidden])
 + .wiley-hsplit{display:block}
/* A collapsed sidebar has no boundary either. More classes than the rule
   above, so it wins without an !important. */
.wiley-panel.expanded.nosb .wiley-sessions:not([hidden]) + .wiley-hsplit,
.wiley-standalone.nosb .wiley-sessions:not([hidden]) + .wiley-hsplit{display:none}
.wiley-standalone.resizing{user-select:none}
/* Wide enough for both: the pane stops floating over the thread and starts
   holding a column open beside it -- the same shape as .expanded, which is
   what a reader who has dragged the panel this big is asking for. */
.wiley-panel.histopen.histwide:not(.expanded){
 grid-template-columns:var(--wiley-hist-w,300px) 1fr}
.wiley-panel.histopen.histwide:not(.expanded) .wiley-sessions:not([hidden]){
 z-index:auto;box-shadow:none;animation:none;
 border-right:1px solid var(--border)}
.wiley-panel.histopen.histwide:not(.expanded) .wiley-body{grid-column:2}
.wiley-panel.histopen.histwide:not(.expanded) .wiley-foot{grid-column:2}

/* EXPANDED: the workspace layout -- header across the top, past conversations
   as a real left pane, chat on the right. The same DOM as the corner panel;
   only the geometry changes, so there is still exactly one implementation. */
.wiley-panel.expanded{display:grid;grid-template-rows:auto 1fr auto;
 grid-template-columns:var(--wiley-hist-w,300px) 1fr}
.wiley-panel.expanded .wiley-head,
.wiley-standalone .wiley-head{grid-column:1/-1;color:#fff;border-bottom:none}
.wiley-panel.expanded .wiley-head .who,
.wiley-panel.expanded .wiley-head .sub,
.wiley-standalone .wiley-head .who,
.wiley-standalone .wiley-head .sub{color:#fff}
.wiley-panel.expanded .wiley-head .sub,
.wiley-standalone .wiley-head .sub{opacity:.8}
.wiley-panel.expanded .wiley-ico,
.wiley-standalone .wiley-ico{color:rgba(255,255,255,.85)}
.wiley-panel.expanded .wiley-ico:hover,
.wiley-standalone .wiley-ico:hover{background:rgba(255,255,255,.18);color:#fff}
.wiley-panel.expanded .wiley-sessions,
.wiley-standalone .wiley-sessions{grid-column:1;grid-row:2/4;max-height:none;
 border-bottom:none;border-right:1px solid var(--border);display:flex;
 flex-direction:column;overflow-y:auto}
.wiley-panel.expanded .wiley-body,
.wiley-standalone .wiley-body{grid-column:2;grid-row:2;padding:22px 8%}
.wiley-panel.expanded .wiley-foot,
.wiley-standalone .wiley-foot{grid-column:2;grid-row:3;padding:12px 8%}
.wiley-panel.expanded.nosb,
.wiley-standalone.nosb{grid-template-columns:1fr}
.wiley-panel.expanded.nosb .wiley-sessions,
.wiley-standalone.nosb .wiley-sessions{display:none}
.wiley-panel.expanded.nosb .wiley-body,
.wiley-panel.expanded.nosb .wiley-foot,
.wiley-standalone.nosb .wiley-body,
.wiley-standalone.nosb .wiley-foot{grid-column:1}
@media (max-width:760px){
  .wiley-panel.expanded .wiley-sessions:not([hidden]) + .wiley-hsplit,
  .wiley-standalone .wiley-sessions:not([hidden]) + .wiley-hsplit,
  .wiley-panel.histopen.histwide:not(.expanded) .wiley-sessions:not([hidden])
   + .wiley-hsplit{display:none}
  .wiley-panel.expanded,.wiley-standalone{grid-template-columns:1fr}
  .wiley-panel.expanded .wiley-sessions,
  .wiley-standalone .wiley-sessions{display:none}
  .wiley-panel.expanded .wiley-body,
  .wiley-panel.expanded .wiley-foot,
  .wiley-standalone .wiley-body,
  .wiley-standalone .wiley-foot{grid-column:1}
}

/* The activity trail: one row per tool call, its specifics and its result,
   folding into a "What I did" summary once the answer lands. */
.wiley-steps .step{display:flex;align-items:baseline;gap:7px;font-size:12px;
 color:var(--text-secondary);padding:2px 0}
.wiley-steps .sp{width:7px;height:7px;border-radius:50%;flex:0 0 auto;
 background:var(--rust);animation:wileypulse 1s ease-in-out infinite;
 position:relative;top:-1px}
.wiley-steps .step.done .sp{animation:none;background:var(--good)}
.wiley-steps .res{color:var(--text-muted)}
.wiley-steps-done{margin:2px 0 8px}
.wiley-steps-done summary{cursor:pointer;font-size:11.5px}
.wiley-steps-done .wiley-steps{margin-top:4px}
@keyframes wileypulse{0%,100%{opacity:.35}50%{opacity:1}}

/* Source attribution -- the block under every answer. */
.wiley-src{margin-top:12px;padding-top:10px;border-top:1px solid var(--border)}
.wiley-src .lbl{font-size:11px;text-transform:uppercase;letter-spacing:.05em;
 color:var(--text-muted);font-weight:600;display:block;margin-bottom:6px}
.wiley-src .row{display:flex;flex-wrap:wrap;gap:6px;align-items:center}
.wiley-src .pill-doc,.wiley-src .pill-tbl{display:inline-flex;align-items:center;
 gap:5px;font-size:11.5px;padding:3px 9px;border-radius:999px;
 border:1px solid var(--border-strong);color:var(--text-secondary);
 background:var(--surface-2);max-width:100%}
.wiley-src .pill-doc b,.wiley-src .pill-tbl b{color:var(--text-primary);
 font-weight:560;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.wiley-src .pill-tbl{font-family:ui-monospace,SFMono-Regular,Menlo,monospace}
.wiley-src .none{font-size:11.5px;color:var(--text-muted)}

.geobar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:0 0 10px}
.geocount{font-size:12.5px;color:var(--text-secondary)}
/* Muted, not alarming: an approximate pin is still useful, it just must not
   be mistaken for a surveyed one. Text, so it survives a colourblind reader
   and a black-and-white print. */
.approx-tag{font-size:10.5px;text-transform:uppercase;letter-spacing:.04em;
 color:var(--text-muted);border:1px solid var(--line);border-radius:3px;
 padding:0 4px;margin-left:5px;white-space:nowrap}
.geolegend{display:flex;gap:12px;margin-left:auto;flex-wrap:wrap}
/* position:relative + z-index:0 traps Leaflet's internal stacking contexts
   (its panes run z-index 200-1000) INSIDE this box. Without it the tile pane
   painted over everything the app layers above the page -- the sticky topbar
   (z 20), chart tooltips (z 60) and the Wiley panel (z 71) all lost to a map
   that thought it owned the viewport. */
.geoplot{border-radius:var(--radius-sm);overflow:hidden;border:1px solid var(--border);
 background:var(--surface-2);position:relative;z-index:0}
/* Fullscreen map: the card takes the viewport. z-index 65 sits above the
   topbar (20) and tooltips (60) but BELOW the Wiley launcher and panel
   (70/71) -- the assistant stays reachable over a fullscreen map. */
.geowrap.geofull{position:fixed;inset:12px;z-index:65;margin:0;
 display:flex;flex-direction:column;overflow:hidden;
 box-shadow:var(--shadow-pop)}
.geowrap.geofull .geoplot{flex:1 1 auto;height:auto !important;min-height:0}
.geowrap.geofull .geolist{flex:1 1 auto;overflow-y:auto;min-height:0}
body.geofull-open{overflow:hidden}
.geonote{font-size:12.5px;color:var(--text-secondary);margin:10px 0 0}
.geotable tbody tr{cursor:pointer}
.geotable tbody tr:hover{background:var(--surface-2)}
.segmented{display:inline-flex;border:1px solid var(--border-strong);
 border-radius:var(--radius-sm);overflow:hidden}
.segmented button{font:inherit;font-size:12.5px;padding:5px 12px;border:none;
 background:var(--surface-1);color:var(--text-secondary);cursor:pointer}
.segmented button.on{background:var(--accent-soft,var(--surface-2));
 color:var(--text-primary);font-weight:600}
/* The legend doubles as the filter, so its chips are buttons. A dropped state
   stays legible -- struck through and dimmed, not deleted -- because the count
   it carries is still part of the picture. */
.geo-state{font:inherit;font-size:12.5px;font-weight:550;cursor:pointer;
 background:var(--surface-1);border:1px solid var(--border);border-radius:999px;
 padding:2px 9px;line-height:1.45}
.geo-state:hover{filter:brightness(1.08)}
.geo-state.off{opacity:.4;text-decoration:line-through}
.geofind{font:inherit;font-size:12.5px;padding:5px 10px;border-radius:var(--radius-sm);
 border:1px solid var(--border-strong);background:var(--surface-1);
 color:var(--text-primary);width:170px;max-width:40vw}
.geoshown{color:var(--text-muted)}
/* The in-map control stack: Leaflet's own .leaflet-bar chrome, so the buttons
   we add sit under the zoom control and look like they came with it. */
.geo-ctl a{font-size:13px;font-weight:600;text-decoration:none;
 display:block;text-align:center;line-height:26px}
.geo-ctl a.on{background:var(--accent-soft,#e8e8e8);color:#000}
.leaflet-tooltip.geo-label{font:inherit;font-size:11px;padding:1px 5px;
 background:rgba(255,255,255,.92);color:#222;border:none;box-shadow:none}
.geohint{font-size:11.5px;color:var(--text-muted);margin:6px 0 0}
.leaflet-popup-content{font:inherit;font-size:12.5px;margin:10px 12px}
.leaflet-popup-content b{display:block;font-size:13.5px;margin-bottom:2px}
.leaflet-popup-content .pv{color:var(--text-secondary)}
.leaflet-container{font:inherit;background:var(--surface-2)}
