/* Corroborate design system, sharing the Reconcile portfolio persona.
   Champagne gold on near-black (dark, the signature look) or warm cream (light),
   Source Serif 4 for display, Inter for text, JetBrains Mono for figures.
   The three event lanes carry their own hues, tuned per theme so they stay legible
   on cream as well as on black. System-font fallbacks keep the page readable if the
   webfonts do not load. */

:root {
  color-scheme: light dark;
  /* light: plain white, with the gold kept for accents only */
  --bg: #ffffff;
  --surface: #ffffff;
  --surface-2: #f6f6f4;
  --ink: #1a1a1c;
  --ink-2: #46464c;
  --ink-3: #7c7c82;
  --line: #e4e4e2;
  --accent: #9c7e45;
  --accent-2: #c9a85e;
  --on-accent: #ffffff;
  /* Lane hues on white: indigo, clay and pine. Deep enough to hold their own against
     paper without the saturation that would fight the gold accent. */
  --macro: #3f5480;
  --micro: #b0304f;
  --markets: #44755b;
  --price: #9a9a96;
  --cap: #6b5f9e;        /* market cap line: distinct from all three lane hues */
  --shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 8px 22px rgba(0, 0, 0, .07);
  --serif: "Source Serif 4", "Source Serif Pro", Charter, Cambria, Georgia, serif;
  --sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --mono: "JetBrains Mono", "SF Mono", ui-monospace, Menlo, Consolas, monospace;
  --radius: 15px;
}

/* dark: the portfolio's signature champagne gold on near-black */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0a0a0d;
    --surface: #0a0a0d;
    --surface-2: #15151b;
    --ink: #f4f4f5;
    --ink-2: #d4d4d8;
    --ink-3: #8a8a92;
    --line: #34343c;
    --accent: #d4b26b;
    --accent-2: #e7ce93;
    --on-accent: #0a0a0d;
    --macro: #6aa9dc;
    --micro: #f0728c;
    --markets: #6bbe86;
    --price: #7a7a88;
    --cap: #a99ae0;
    --shadow: 0 1px 2px rgba(0,0,0,.45), 0 12px 30px rgba(0,0,0,.55);
  }
}

/* explicit dark via the toggle, wins over the system setting */
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #0a0a0d;
  --surface: #0a0a0d;
  --surface-2: #15151b;
  --ink: #f4f4f5;
  --ink-2: #d4d4d8;
  --ink-3: #8a8a92;
  --line: #34343c;
  --accent: #d4b26b;
  --accent-2: #e7ce93;
  --on-accent: #0a0a0d;
  --macro: #6aa9dc;
  --micro: #f0728c;
  --markets: #6bbe86;
  --price: #7a7a88;
  --cap: #a99ae0;
  --shadow: 0 1px 2px rgba(0,0,0,.45), 0 12px 30px rgba(0,0,0,.55);
}
:root[data-theme="light"] { color-scheme: light; }

* { box-sizing: border-box; }

/* The `hidden` attribute works by a UA rule of display:none, which any author rule
   setting display beats. Several panels here are flex containers, so without this
   they ignore `hidden` entirely and never close. */
[hidden] { display: none !important; }

html, body { margin: 0; height: 100%; }
body {
  background: var(--bg); color: var(--ink);
  font-family: var(--sans);
  font-size: 15px; line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  display: flex; flex-direction: column; min-height: 100vh;
  transition: background .2s ease, color .2s ease;
}

/* ---------------------------------------------------------------- topbar */
.topbar {
  padding: 16px 24px; border-bottom: 1px solid var(--line); background: var(--surface);
}
/* Title and controls share a row; the status gets the full width beneath them, which is
   what stops it wrapping at the button edge. */
.topbar-main {
  display: flex; align-items: center; justify-content: space-between; gap: 18px;
}
.brand { display: flex; align-items: center; gap: 14px; min-width: 0; }
.mark {
  width: 10px; height: 38px; border-radius: 3px;
  background: linear-gradient(var(--accent-2), var(--accent));
}
h1 {
  font-family: var(--serif); font-size: 1.42rem; font-weight: 600;
  margin: 0; letter-spacing: -.015em; color: var(--ink);
}
.tagline { margin: 1px 0 0; color: var(--ink-3); font-size: .8rem; }
/* Sits under the tagline it belongs to. Left aligned and on one line: five right-aligned
   monospace lines opposite the title read as an error message rather than a status. */
.status {
  color: var(--ink-3); font-size: .72rem; text-align: left;
  font-family: var(--mono); line-height: 1.4; margin: 8px 0 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.topbar-right { display: flex; align-items: center; gap: 14px; }

.theme-toggle, .howbtn {
  display: inline-flex; align-items: center; gap: 7px;
  font: inherit; font-size: .82rem; font-weight: 600; line-height: 1;
  padding: 9px 14px; border-radius: 10px;
  border: 1px solid var(--line); background: transparent; color: var(--ink);
  cursor: pointer; white-space: nowrap;
  transition: background .15s, border-color .15s, color .15s;
}
.howbtn:hover { background: var(--surface-2); border-color: var(--ink-3); }
/* Foot of the methodology panel, outside .how-grid so it does not inherit the card
   treatment that rule gives every direct child. */
.how-close { display: flex; justify-content: flex-end; margin: 22px 0 0; }
.howbtn[aria-expanded="true"] { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

/* The toggle is inverted on purpose: it shows the mode you would switch to rather
   than the one you are in. Because --ink and --bg swap between themes, one rule
   gives a light button on a dark page and a dark button on a light one. */
.theme-toggle {
  background: var(--ink); color: var(--bg); border-color: var(--ink);
}
.theme-toggle:hover { background: var(--ink-2); border-color: var(--ink-2); }
.tt-icon { font-size: .95rem; line-height: 1; }

/* ---------------------------------------------------------------- methodology */
.how { border-bottom: 1px solid var(--line); background: var(--surface-2); padding: 24px; }
.how-title {
  font-family: var(--serif); font-size: 1.05rem; font-weight: 600;
  margin: 0 0 16px; letter-spacing: .01em; color: var(--ink);
}
.how-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(272px, 1fr)); gap: 20px 28px; }
.how-grid > div {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 16px 18px;
}
.how-grid h3 {
  margin: 0 0 7px; font-size: .68rem; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; color: var(--accent);
}
.how-grid p, .how-grid li { margin: 0 0 5px; font-size: .84rem; color: var(--ink-2); line-height: 1.55; }
.how-grid ul { margin: 0; padding-left: 17px; }
.how-grid li b { color: var(--ink); font-weight: 600; }

/* Process flow diagrams. Inline SVG so the fills can read the theme tokens directly;
   a linked image would need two copies and would drift from the palette. */
.how-full { grid-column: 1 / -1; }
.how-full h3 {
  margin: 0 0 6px; font-size: .68rem; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; color: var(--accent);
}
.pfd-note { margin: 0 0 10px; font-size: .8rem; color: var(--ink-3); line-height: 1.5; }
.pfd-note + .pfd { margin-bottom: 4px; }
.pfd {
  width: 100%; height: auto; display: block; margin: 4px 0 12px;
  /* Wide diagrams scroll inside their own box rather than stretching the page. */
  min-width: 640px;
}
.how-full > .pfd { min-width: 0; }
.pfd line { stroke: var(--ink-3); stroke-width: 1.4; }
.pfd-box rect {
  fill: var(--surface); stroke: var(--line); stroke-width: 1.2;
}
.pfd-store rect { fill: var(--surface-2); stroke: var(--accent); }
.pfd-model rect { fill: var(--surface-2); stroke: var(--macro); }
.pfd-side rect { stroke-dasharray: 4 3; }
.pfd-h {
  fill: var(--accent); font-family: var(--sans); font-size: 11px; font-weight: 700;
  letter-spacing: .08em;
}
.pfd-model .pfd-h { fill: var(--macro); }
.pfd-t { fill: var(--ink); font-family: var(--sans); font-size: 11.5px; font-weight: 600; }
.pfd-s { fill: var(--ink-2); font-family: var(--sans); font-size: 11px; }

/* The diagrams need horizontal room; below that they scroll rather than shrink to
   the point where the labels stop being readable. */
@media (max-width: 900px) {
  .how-full { overflow-x: auto; }
  .pfd { min-width: 900px; }
}

/* ---------------------------------------------------------------- toolbar */
.toolbar {
  display: flex; gap: 16px; align-items: center; flex-wrap: wrap;
  padding: 13px 24px; border-bottom: 1px solid var(--line); background: var(--surface);
}
.ranges { display: inline-flex; gap: 4px; }

/* Window stepping. Sits beside the ranges because it changes the same thing they do:
   which slice of time is on screen. */
.pan { display: inline-flex; gap: 4px; }
.pan button {
  font: inherit; font-size: .78rem; font-weight: 600; line-height: 1;
  padding: 8px 11px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--line); background: var(--surface-2); color: var(--ink);
}
.pan button:hover:not(:disabled) { border-color: var(--ink-3); }
.pan button:disabled { opacity: .38; cursor: default; }
#timeline { cursor: grab; }
#timeline.dragging { cursor: grabbing; }

.ranges button {
  font: inherit; font-size: .78rem; font-weight: 600;
  background: transparent; color: var(--ink-3);
  border: 1px solid var(--line); padding: 7px 12px; border-radius: 9px; cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.ranges button:hover { color: var(--ink); border-color: var(--ink-3); }
.ranges button.active { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }

.cats { display: inline-flex; gap: 14px; }
.chip {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: .8rem; font-weight: 500; color: var(--ink-2); cursor: pointer; user-select: none;
}
.chip input { accent-color: var(--accent); margin: 0; }
.chip::before { content: ""; width: 9px; height: 9px; border-radius: 50%; flex: none; }
.chip.macro::before { background: var(--macro); }
.chip.micro::before { background: var(--micro); }
.chip.markets::before { background: var(--markets); }
.chip.rating::before { background: var(--accent); }
.chip.rating:has(input:disabled) { opacity: .4; cursor: default; }

.search, .ticker {
  font: inherit; font-size: .84rem;
  background: var(--surface-2); border: 1px solid var(--line); color: var(--ink);
  padding: 9px 12px; border-radius: 10px;
}
.search { flex: 1; min-width: 170px; }
/* Sized against the actual names: 300px shows 98% of them whole, where 250px showed
   90% and 360px would show all at the cost of crowding the toolbar. The remainder
   ellipsis, and the symbol they start with is never the part that gets cut. The
   uppercase transform is gone, since the field now carries a name as well as a symbol
   and the symbol is uppercased where it is parsed. */
.tickerwrap { position: relative; }
.ticker { width: 300px; font-family: var(--mono); text-overflow: ellipsis; }
.ticker-menu {
  position: absolute; top: calc(100% + 4px); left: 0; width: 300px;
  max-height: 320px; overflow-y: auto; z-index: 40;
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0,0,0,.22); padding: 4px;
}
.ticker-opt {
  display: block; width: 100%; text-align: left; cursor: pointer;
  font: inherit; font-size: .8rem; color: var(--ink-2); background: transparent;
  border: none; border-radius: 7px; padding: 7px 9px; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.ticker-opt:hover, .ticker-opt.active { background: var(--surface-2); color: var(--ink); }
.ticker-opt b { color: var(--ink); font-family: var(--mono); }
.ticker-opt em { color: var(--ink-3); font-style: normal; }

.ticker::placeholder { font-family: var(--sans); }
.search:focus, .ticker:focus, .chatform input:focus {
  outline: none; border-color: var(--accent);
}

/* bubble size: dot radius is a reading preference, not a fixed property of the data */
.sizer { display: inline-flex; align-items: center; gap: 9px; font-size: .78rem; color: var(--ink-3); }
.sizer input[type="range"] { width: 96px; accent-color: var(--accent); cursor: pointer; }
.sizer output { font-family: var(--mono); font-size: .74rem; color: var(--ink-2); min-width: 2.4em; }

/* Tag filter. A dropdown rather than more chips in the bar: the vocabulary is fifteen
   entries and grows, so it needs a container that does not consume the toolbar. */
.tagpick { position: relative; }
.tagbtn {
  font: inherit; font-size: .8rem; font-weight: 600;
  background: transparent; color: var(--ink-2);
  border: 1px solid var(--line); padding: 9px 14px; border-radius: 10px; cursor: pointer;
  white-space: nowrap;
}
.tagbtn:hover { color: var(--ink); border-color: var(--ink-3); }
.tagbtn.on { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.tagmenu {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 40;
  min-width: 250px; max-height: 340px; overflow-y: auto;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: 12px; box-shadow: var(--shadow); padding: 6px;
}
.tagrow {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 9px;
  padding: 7px 9px; border-radius: 8px; cursor: pointer;
  font-size: .82rem; color: var(--ink-2);
}
.tagrow:hover { background: var(--surface-2); color: var(--ink); }
.tagrow input { accent-color: var(--accent); margin: 0; }
.tagrow em {
  font-style: normal; font-family: var(--mono); font-size: .68rem; color: var(--ink-3);
}

.refresh {
  font: inherit; font-size: .82rem; font-weight: 600;
  background: transparent; color: var(--ink); border: 1px solid var(--line);
  padding: 9px 15px; border-radius: 10px; cursor: pointer;
  transition: background .15s, border-color .15s;
}
.refresh:hover { background: var(--surface-2); border-color: var(--ink-3); }

/* coverage names: one click filters, clicking the active one clears */
.targets { display: inline-flex; gap: 5px; flex-wrap: wrap; }
.targets button {
  font: inherit; font-family: var(--mono); font-size: .72rem; font-weight: 500;
  background: transparent; color: var(--ink-3);
  border: 1px solid var(--line); padding: 6px 9px; border-radius: 8px; cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.targets button:hover { color: var(--ink); border-color: var(--ink-3); }
.targets button.active { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.targets-clear { font-family: var(--sans) !important; }

/* ---------------------------------------------------------------- layout */
.grid { flex: 1; display: grid; grid-template-columns: 1fr; min-height: 0; }
/* The note column exists only while a name is selected, so the chart keeps the full
   width the rest of the time. */
.grid.with-brief { grid-template-columns: minmax(0, 1fr) var(--brief-w, 420px); }
.left { display: flex; flex-direction: column; min-width: 0; min-height: 0; }
.timeline-wrap {
  /* A floor, not a target: the wrap takes the height its grid row gives it. Kept low
     enough to fit a short viewport, since a floor taller than the space available is
     what pushes the date axis off screen. */
  flex: 1; min-height: 240px;
  overflow-x: auto; overflow-y: hidden; padding: 10px 0; background: var(--bg);
}
#timeline { display: block; width: 100%; height: 100%; min-height: 0; }

/* Scrubber. Short on purpose: it is an index to the record, not a second chart. */
.brush-wrap {
  flex: none; height: 62px; padding: 8px 0 4px;
  background: var(--bg); border-bottom: 1px solid var(--line);
}
#brush { display: block; width: 100%; height: 100%; touch-action: none; cursor: crosshair; }
.brush-mask { fill: var(--bg); opacity: .62; pointer-events: none; }
.brush-window {
  fill: var(--accent); opacity: .13;
  stroke: var(--accent); stroke-width: 1; cursor: grab;
}
.brush-handle { fill: var(--accent); opacity: .85; cursor: ew-resize; rx: 2; }


/* ---------------------------------------------------------------- detail */
.detail {
  position: relative; margin: 0; padding: 20px 24px;
  border-top: 1px solid var(--line); background: var(--surface);
  max-height: 44%; overflow-y: auto;
}
.detail .close {
  position: absolute; top: 12px; right: 14px;
  background: none; border: none; color: var(--ink-3); font-size: 22px; cursor: pointer; line-height: 1;
}
.detail .close:hover { color: var(--ink); }
.detail h3 { font-family: var(--serif); font-size: 1.08rem; font-weight: 600; margin: 0 0 8px; }
.detail .meta { color: var(--ink-3); font-size: .78rem; margin-bottom: 10px; font-family: var(--mono); }
.detail p { color: var(--ink-2); font-size: .9rem; margin: 0 0 12px; }
.detail .badge {
  display: inline-block; padding: 2px 9px; border-radius: 999px;
  font-size: .68rem; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  margin-right: 8px; font-family: var(--sans);
}
.detail a { color: var(--accent); font-weight: 600; font-size: .86rem; }

/* ---------------------------------------------------------------- ticker note
   Sits in its own column beside the chart, so the note and the dots it describes
   are visible at once. The grid opens a second column only when a name is selected. */
.brief {
  position: relative;
  border-left: 1px solid var(--line); background: var(--surface);
  display: flex; flex-direction: column; min-height: 0; min-width: 0;
}
/* Drag the left edge to resize the note and, with it, the chart. A thin strip that
   widens its hit area on hover so it is easy to grab without being visible clutter. */
.brief-resize {
  position: absolute; left: -3px; top: 0; bottom: 0; width: 7px;
  cursor: col-resize; z-index: 5;
}
.brief-resize::before {
  content: ""; position: absolute; left: 2px; top: 0; bottom: 0; width: 2px;
  background: var(--line); transition: background .15s;
}
.brief-resize:hover::before, .brief.resizing .brief-resize::before { background: var(--accent); }
.brief-head {
  display: flex; align-items: center; gap: 10px; flex: none;
  padding: 12px 18px; border-bottom: 1px solid var(--line); background: var(--surface-2);
}
.brief-head strong { font-family: var(--mono); font-size: .95rem; color: var(--ink); flex: 1; }
.brief-stance {
  font-size: .66rem; font-weight: 800; letter-spacing: .09em;
  padding: 4px 10px; border-radius: 999px; background: var(--accent); color: var(--on-accent);
  white-space: nowrap;
}
.brief-asof { font-family: var(--mono); font-size: .66rem; color: var(--ink-3); white-space: nowrap; line-height: 1.3; }
.brief-asof.saved { color: var(--micro); }
.brief-asof .reset { display: block; opacity: .8; }
.brief-stance.saved { background: var(--micro); }
.brief-copy, .brief-refresh {
  font: inherit; font-size: .68rem; font-weight: 600;
  background: transparent; color: var(--ink-3);
  border: 1px solid var(--line); padding: 4px 9px; border-radius: 7px; cursor: pointer;
}
.brief-copy:hover, .brief-refresh:hover { color: var(--ink); border-color: var(--ink-3); }
.brief-close {
  background: transparent; border: none; color: var(--ink-3);
  font-size: 1.4rem; line-height: 1; cursor: pointer; padding: 0 2px;
}
.brief-close:hover { color: var(--ink); }
.brief-body {
  padding: 16px 18px; overflow-y: auto; font-size: .84rem; color: var(--ink-2);
  white-space: pre-wrap; line-height: 1.62; flex: 1; min-height: 0;
}
.brief-body strong { color: var(--ink); font-weight: 600; }

/* The note takes several seconds: four market-data calls, six database queries, then
   the model writing. A static line reads as a stall, so the dots show it is alive. */
.brief-loading { display: flex; align-items: center; gap: 11px; color: var(--ink-3); font-size: .82rem; }
.dots { display: inline-flex; gap: 5px; flex: none; }
.dots i {
  display: block; width: 7px; height: 7px; border-radius: 50%;
  background: var(--accent); opacity: .25;
  animation: dot-pulse 1.25s ease-in-out infinite;
}
.dots i:nth-child(2) { animation-delay: .16s; }
.dots i:nth-child(3) { animation-delay: .32s; }
@keyframes dot-pulse {
  0%, 75%, 100% { opacity: .22; transform: translateY(0); }
  35%           { opacity: 1;   transform: translateY(-4px); }
}
/* Respect a reader who has asked the system for less motion. */
@media (prefers-reduced-motion: reduce) {
  .dots i { animation: none; opacity: .6; }
}
.brief-body { white-space: normal; }
/* Set apart by weight, colour and the space above it. No rule: the note already sits in
   a bordered panel, and a line per section made it read as a table. */
.note-h {
  font-size: .62rem; font-weight: 800; letter-spacing: .12em; text-transform: uppercase;
  color: var(--accent); margin: 20px 0 7px;
}
.note-h:first-child, .note-name + .note-h { margin-top: 0; }
/* Leads the note, so it is set larger than the body and in full ink rather than accent,
   which is reserved for the section headings. */
.note-name {
  font-size: .95rem; font-weight: 700; color: var(--ink-1);
  margin: 0 0 12px; line-height: 1.25;
}
.note-p { margin: 0 0 6px; }
.note-range {
  margin: 2px 0 14px; font-size: .74rem; color: var(--ink-3);
  font-family: var(--mono);
}
.note-generate {
  display: inline-flex; align-items: center; gap: 7px;
  font: inherit; font-size: .84rem; font-weight: 600; line-height: 1;
  padding: 10px 16px; border-radius: 10px; cursor: pointer;
  border: 1px solid var(--accent); background: var(--accent); color: var(--on-accent);
  transition: filter .15s;
}
.note-generate:hover { filter: brightness(1.06); }
.brief-refresh.stale {
  border-color: var(--accent); color: var(--accent); font-weight: 700;
}

/* Conditional distribution, shown under a FRED event. Deliberately plain: the numbers
   carry the argument and a thin sample is marked rather than styled away. */
.cond { margin: 14px 0 0; padding-top: 12px; border-top: 1px solid var(--line); }
.cond-h {
  font-size: .66rem; font-weight: 800; letter-spacing: .11em; text-transform: uppercase;
  color: var(--accent); margin-bottom: 7px;
}
.cond-sub {
  font-size: .62rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-3); margin: 12px 0 5px;
}
.cond-lead { margin: 0 0 8px; font-size: .8rem; color: var(--ink-2); }
.cond-load { font-size: .8rem; color: var(--ink-3); }
.cond-t { width: 100%; border-collapse: collapse; font-size: .78rem; font-family: var(--mono); }
.cond-t th {
  text-align: left; font-weight: 600; color: var(--ink-3); font-size: .68rem;
  text-transform: uppercase; letter-spacing: .06em; padding: 0 8px 4px 0;
  border-bottom: 1px solid var(--line);
}
.cond-t td { padding: 4px 8px 4px 0; border-bottom: 1px solid var(--line); color: var(--ink); }
.cond-t td.q { color: var(--ink-3); }
.cond-t tr.thin td { opacity: .55; }
.cond-note { margin: 9px 0 0; font-size: .72rem; color: var(--ink-3); line-height: 1.5; }

.brief-body br { display: none; }
.brief-foot {
  flex: none; margin: 0; padding: 10px 18px; border-top: 1px solid var(--line);
  background: var(--surface-2); color: var(--ink-3); font-size: .68rem; line-height: 1.45;
}

/* ---------------------------------------------------------------- assistant */
.ask-fab {
  position: fixed; right: 24px; bottom: 78px; z-index: 60;
  width: 62px; height: 62px; border-radius: 50%; border: none;
  background: var(--accent); color: var(--on-accent); cursor: pointer;
  box-shadow: 0 8px 24px rgba(0,0,0,.28); display: grid; place-items: center;
  transition: transform .15s, filter .15s;
}
.ask-fab:hover { filter: brightness(1.07); transform: translateY(-2px); }
.ask-fab:focus-visible { outline: 3px solid var(--accent-2); outline-offset: 2px; }
.ask-fab-tip {
  position: absolute; right: 74px; top: 50%; transform: translateY(-50%);
  white-space: nowrap; background: var(--ink); color: var(--bg);
  font-size: .78rem; font-weight: 600; padding: 6px 11px; border-radius: 8px;
  opacity: 0; pointer-events: none; transition: opacity .15s; box-shadow: var(--shadow);
}
.ask-fab:hover .ask-fab-tip, .ask-fab:focus-visible .ask-fab-tip { opacity: 1; }

.ask-panel {
  position: fixed; right: 24px; bottom: 100px; z-index: 61;
  width: 404px; max-width: calc(100vw - 32px);
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line); border-radius: 16px;
  box-shadow: 0 16px 48px rgba(0,0,0,.30); overflow: hidden;
}
.ask-panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 13px 16px; background: var(--accent); color: var(--on-accent);
}
.ask-panel-head strong { font-family: var(--serif); font-size: 1rem; }
.ask-panel-close {
  background: transparent; border: none; color: var(--on-accent);
  font-size: 1.5rem; line-height: 1; cursor: pointer; padding: 0 4px;
}
.ask-panel-body { padding: 14px 16px 16px; max-height: 62vh; display: flex; flex-direction: column; min-height: 0; }
.ask-panel-body .hint { margin: 0 0 10px; color: var(--ink-3); font-size: .76rem; }
.ask-examples { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0; }
.ask-examples button {
  font: inherit; font-size: .72rem; font-weight: 500;
  border: 1px solid var(--line); background: var(--surface-2); color: var(--ink-2);
  padding: 5px 10px; border-radius: 999px; cursor: pointer;
}
.ask-examples button:hover { border-color: var(--accent); color: var(--ink); }

.messages { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 12px; min-height: 0; max-height: 34vh; }
.msg { padding: 11px 13px; border-radius: 12px; font-size: .86rem; white-space: pre-wrap; line-height: 1.55; }
.msg.user { background: var(--accent); color: var(--on-accent); align-self: flex-end; max-width: 88%; font-weight: 500; }
.msg.bot { background: var(--surface-2); border: 1px solid var(--line); color: var(--ink-2); }
.msg .cites { margin-top: 10px; display: flex; flex-wrap: wrap; gap: 6px; }
.msg .cite {
  font: inherit; font-size: .7rem; font-weight: 600; text-align: left;
  color: var(--accent); background: transparent;
  border: 1px solid var(--line); border-radius: 8px; padding: 3px 8px; cursor: pointer;
}
.msg .cite:hover { border-color: var(--accent); background: var(--bg); }

.chatform { display: flex; gap: 8px; padding-top: 10px; border-top: 1px solid var(--line); }
.chatform input {
  flex: 1; font: inherit; font-size: .86rem;
  background: var(--surface-2); border: 1px solid var(--line); color: var(--ink);
  padding: 10px 12px; border-radius: 10px;
}
.chatform button {
  font: inherit; font-size: .84rem; font-weight: 700;
  background: var(--accent); color: var(--on-accent);
  border: 1px solid var(--accent); padding: 10px 17px; border-radius: 10px; cursor: pointer;
}
.chatform button:hover { background: var(--accent-2); border-color: var(--accent-2); color: var(--ink); }

/* ---------------------------------------------------------------- svg + tooltip */
.tooltip {
  position: fixed; pointer-events: none; z-index: 20;
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  padding: 9px 11px; font-size: .78rem; max-width: 300px; box-shadow: var(--shadow); color: var(--ink-2);
}
.tooltip .t-title { font-weight: 600; margin-bottom: 3px; color: var(--ink); }
.tooltip .t-meta { color: var(--ink-3); font-family: var(--mono); font-size: .72rem; }

.dot { cursor: pointer; transition: r .12s ease; }
.dot:hover { stroke: var(--ink); stroke-width: 1.5; }
text.axis, .axis text { fill: var(--ink-2); font-size: 11px; font-family: var(--mono); font-weight: 700; }
line.axis, .axis line, .lane-sep { stroke: var(--line); }
.lane-label {
  fill: var(--ink-2); font-size: 10px; font-weight: 800;
  text-transform: uppercase; letter-spacing: .1em; font-family: var(--sans);
}
.range-label { font-weight: 800; fill: var(--accent); }
.price-label { fill: var(--ink-3); font-size: 10.5px; font-family: var(--mono); font-weight: 700; }
.price-caption { font-weight: 400; }
/* Sits behind an end-of-line label so it stays readable over the series it names. */
.price-label-bg { fill: var(--bg); opacity: .95; }

@media (max-width: 900px) {
  .grid { grid-template-columns: 1fr; }
  .chat { border-top: 1px solid var(--line); max-height: 48vh; }
  .left { border-right: none; }
  .status { max-width: 24ch; }
}

/* ---------------------------------------------------------------- phones
   Two defects below 720px, both from laying rows out side by side and letting the
   loser shrink instead of wrap.

   The header put .brand and .topbar-right on one flex row. .brand carries
   min-width: 0, so on a 375px screen it collapsed to near nothing while its h1 kept
   painting at full width, which put "Corroborate" underneath the buttons. Stacking
   removes the competition rather than trimming the title to fit.

   The range row is eight presets in an inline-flex that never wraps, so 5Y sat 46px
   past the right edge and dragged a horizontal scrollbar onto every view. Wrapping
   costs one row and keeps all eight reachable. */
@media (max-width: 720px) {
  .topbar { padding: 12px 16px; }
  .topbar-main {
    flex-direction: column; align-items: stretch;
    justify-content: flex-start; gap: 11px;
  }
  .topbar-right { flex-wrap: wrap; gap: 8px; }
  h1 { font-size: 1.24rem; }
  .status { max-width: none; }

  .toolbar { padding: 12px 16px; gap: 11px; }
  /* Wrapping keeps 5Y reachable, but at desktop padding the eight presets need 396px
     and put 5Y alone on a second row, which cost 96px of a screen that only has 844.
     Trimming the horizontal padding fits all eight on one row down to 360px. The touch
     rule below holds the height at 40px, so they are no harder to hit for being narrower. */
  .ranges { flex-wrap: wrap; gap: 4px; }
  .ranges button { padding: 7px 8px; font-size: .75rem; }

  /* Fixed pixel widths that no longer fit once 32px of padding comes off a 360px
     screen. The menu has to track the field or it stops lining up under it. */
  .tickerwrap { flex: 1 1 100%; }
  .ticker, .ticker-menu { width: 100%; }
  /* Not 100%, which pushed Refresh onto a row of its own for the sake of 81px. But not
     a bare flex: 1 either: that let the field share a row with the rating chip and the
     tag button and collapse to 31px. The 200px floor forces a break away from those two
     while still leaving room for Refresh alongside, so the field lands around 266px. */
  .search { flex: 1 1 200px; min-width: 200px; }
  .tagmenu { min-width: 0; width: max(250px, 100%); }

  .how { padding: 20px 16px; }
}

/* Touch targets. Measured at 29x30 for the pan arrows and 13x13 for the checkboxes,
   against a ~40px finger. The query is an OR: phone widths catch handsets, coarse
   pointer catches tablets and touchscreen laptops that are wider than 720px. Width
   alone would miss those; pointer alone cannot be verified in a headless probe,
   which reports every pointer as fine. */
@media (max-width: 720px), (pointer: coarse) {
  .ranges button, .pan button, .tagbtn, .refresh, .howbtn, .theme-toggle { min-height: 40px; }
  .pan button { min-width: 40px; }
  .chip { min-height: 38px; }
  .chip input { width: 17px; height: 17px; }
}

/* Guided tour. A dim layer, a highlight ring cut around the current target, and a small
   popover with the step text. Pointer events pass only to the controls, never the dim. */
.tour { position: fixed; inset: 0; z-index: 200; pointer-events: none; }
.tour[hidden] { display: none; }
/* The dim is drawn by the ring's own box-shadow spotlight, so this layer is removed to
   keep the page fully interactive; kept as an empty rule in case it is referenced. */
.tour-dim { display: none; }
.tour-pop, .tour-pop * { pointer-events: auto; }
.tour-ring {
  position: fixed; border-radius: 12px; pointer-events: none;
  box-shadow: 0 0 0 3px var(--accent), 0 0 0 9999px rgba(0,0,0,.55);
  transition: all .2s ease;
}
.tour-pop {
  position: fixed; width: 300px; max-width: calc(100vw - 32px);
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: 12px;
  box-shadow: 0 16px 40px rgba(0,0,0,.32); padding: 16px 18px; z-index: 201;
  transition: top .2s ease, left .2s ease;
}
.tour-count { font-size: .68rem; letter-spacing: .1em; text-transform: uppercase; color: var(--accent); font-weight: 700; }
.tour-title { margin: 5px 0 6px; font-size: 1rem; color: var(--ink); }
.tour-text { margin: 0 0 14px; font-size: .86rem; line-height: 1.5; color: var(--ink-2); }
.tour-actions { display: flex; align-items: center; justify-content: space-between; }
.tour-nav { display: inline-flex; gap: 8px; }
.tour-pop button {
  font: inherit; font-size: .82rem; font-weight: 600; cursor: pointer;
  padding: 7px 14px; border-radius: 8px; border: 1px solid var(--line);
  background: transparent; color: var(--ink-2);
}
.tour-skip:hover, .tour-back:hover { border-color: var(--ink-3); color: var(--ink); }
.tour-next { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.tour-next:hover { filter: brightness(1.06); }
.tour-back:disabled { opacity: .4; cursor: default; }
