/* FinanceHub -- no framework, no build step. Edit and refresh.
   Palette and form live in ../tokens.css, shared with every other app. */

body {
  margin: 0;
  padding: 0 clamp(12px, 4vw, 40px) 60px;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

/* ---- scrolling index tape ----
   Bleeds to the full window width by cancelling the body's side padding. */
.tape {
  display: flex; align-items: center; gap: 12px;
  margin: 0 calc(-1 * clamp(12px, 4vw, 40px));
  padding: 0 clamp(12px, 4vw, 40px);
  background: var(--panel); border-bottom: 1px solid var(--border);
}
.tape[hidden] { display: none; }
.tape-window { flex: 1; overflow: hidden; }
.tape-track { display: flex; width: max-content; animation: tape-scroll 60s linear infinite; }
.tape-half { display: flex; gap: 28px; padding-right: 28px; }

/* Translating by exactly -50% lands the duplicate copy where the first began,
   so the loop has no visible seam. */
@keyframes tape-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* Three ways to stop it: the button, hovering, or tabbing into it.
   WCAG 2.2.2 requires motion lasting over 5s to be pausable. */
.tape.paused .tape-track,
.tape-window:hover .tape-track,
.tape-window:focus-within .tape-track { animation-play-state: paused; }

@media (prefers-reduced-motion: reduce) {
  /* Never animate for people who asked not to be moved. It degrades into an
     ordinary strip they can scroll themselves. */
  .tape-track { animation: none; }
  .tape-window { overflow-x: auto; }
}

.tape-item { display: flex; align-items: baseline; gap: 7px; padding: 9px 0; font-size: 13px; white-space: nowrap; }
.tape-item b { font-weight: 650; letter-spacing: -.01em; }
.tape-item .v { color: var(--muted); font-variant-numeric: tabular-nums; }
.tape-item .d { font-variant-numeric: tabular-nums; font-weight: 600; }

.tape-toggle {
  flex: 0 0 auto; font: inherit; font-size: 11px; letter-spacing: .04em;
  text-transform: uppercase; color: var(--muted); cursor: pointer;
  background: var(--chip); border: 1px solid var(--border);
  border-radius: 6px; padding: 4px 10px;
}
.tape-toggle:hover { color: var(--text); }

header { padding: 28px 0 18px; }
h1 { margin: 0 0 4px; font-size: clamp(22px, 4vw, 30px); letter-spacing: -.02em; }
.sub { color: var(--muted); font-size: 13px; }

.badge {
  display: inline-block; padding: 2px 8px; border-radius: 999px;
  background: #f5a524; color: #241a00; font-size: 11px; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase; margin-left: 8px;
}

/* Same surface as the table and detail cards -- raised panel over the page
   background, hairline border, no coloured edge. Hierarchy comes from size
   and position, and the accent stays reserved for things you can interact
   with or read a value from. */
.panel {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 11px; box-shadow: var(--shadow);
  padding: 12px 15px; margin: 0 0 11px;
}

.note { font-size: 12.5px; line-height: 1.5; color: var(--muted); }
.note strong { color: var(--text); }

.filters .group:last-child { margin-bottom: 0; }
.filters .group-note:last-child { margin-bottom: 0; }

/* Filter rows. A fixed-width label column lines the chip groups up with each
   other, so the structure comes from typography and alignment rather than
   from tinted panels -- and the chips stay the only coloured thing on screen,
   which is what you are actually meant to look at. */
.group { display: flex; align-items: flex-start; gap: 12px; margin-bottom: 8px; }
.group-label {
  flex: 0 0 52px; padding-top: 7px;
  font-size: 10px; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted);
}
.group .chips { flex: 1; margin-bottom: 0; }
.group-note {
  margin: -2px 0 12px 64px; font-size: 11.5px; color: var(--muted);
}

/* The verdict badge is the point: an untested signal must not look like a
   proven one, and a signal that measured badly must look bad. */
.chip.trig .pos, .chip.trig .neg { font-weight: 700; font-variant-numeric: tabular-nums; }
.chip.trig .untested { color: var(--muted); font-style: italic; font-size: 11px; }
.chip[aria-pressed="true"] .untested { color: rgba(255, 255, 255, .8); }

/* Row marker for a company with a signal today. */
.sig {
  display: inline-block; width: 5px; height: 5px; border-radius: 50%;
  background: var(--accent); margin-right: 6px; vertical-align: middle;
}

.sig-item { padding: 8px 0; border-bottom: 1px solid var(--border); }
.sig-item:last-child { border-bottom: 0; padding-bottom: 0; }
.sig-item p { margin: 5px 0 0; font-size: 12px; color: var(--muted); line-height: 1.45; }

/* Imminent earnings. Neutral by design -- it is context for reading a signal,
   not a signal of its own. */
.flag {
  display: inline-block; padding: 1px 7px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--chip);
  font-size: 10.5px; letter-spacing: .02em; color: var(--text);
  vertical-align: 1px;
}
.sig-rec { border-left: 2px solid var(--border); padding-left: 9px; }

/* ---- clickable sector filters ---- */
.chips { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 12px; }
.chip {
  display: flex; align-items: baseline; gap: 7px; cursor: pointer;
  font: inherit; font-size: 12.5px; padding: 6px 11px;
  color: var(--text); background: var(--panel);
  border: 1px solid var(--border); border-radius: 999px;
}
.chip:hover { border-color: var(--accent); }
.chip[aria-pressed="true"] {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
/* Inside a selected chip the red/green counts would clash with the fill. */
.chip[aria-pressed="true"] .n,
.chip[aria-pressed="true"] .pos,
.chip[aria-pressed="true"] .neg { color: rgba(255, 255, 255, .8); }
.chip .n { color: var(--muted); font-variant-numeric: tabular-nums; }
.chip .pos, .chip .neg { font-variant-numeric: tabular-nums; font-weight: 600; }

.controls { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-bottom: 14px; }
select, input {
  font: inherit; font-size: 13px; padding: 7px 10px; color: var(--text);
  background: var(--panel); border: 1px solid var(--border); border-radius: 7px;
}
input { min-width: 180px; }

.layout { display: grid; grid-template-columns: minmax(0, 1.65fr) minmax(0, 1fr); gap: 18px; align-items: start; }

.card {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 11px; box-shadow: var(--shadow); overflow: hidden;
}

/* The table gets its own scroll box rather than growing the whole page.
   Without this the page height is driven by the row count, so the detail
   panel's sticky positioning is useless -- you cannot reach the bottom of it
   without first scrolling past every company. Now both columns scroll
   independently and the "show more" button stays pinned below the table. */
.scroll {
  overflow: auto;
  /* --panes-top is measured in app.js: the chrome above the table changes
     height as the sector chips wrap, so any fixed offset is wrong at most
     window widths. The 76px leaves room for the "show more" bar. */
  max-height: calc(100vh - var(--panes-top, 330px) - 76px);
  min-height: 300px;                 /* never collapse to a sliver on short windows */
  overscroll-behavior: contain;      /* don't chain into the page when it bottoms out */
}
table { border-collapse: collapse; width: 100%; font-variant-numeric: tabular-nums; }
th, td { padding: 9px 11px; text-align: right; white-space: nowrap; border-bottom: 1px solid var(--border); }
th:first-child, td:first-child, th:nth-child(2), td:nth-child(2) { text-align: left; }
th {
  position: sticky; top: 0; background: var(--panel); z-index: 1;
  font-size: 11px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--muted); cursor: pointer; user-select: none;
}
th:hover { color: var(--text); }
th.sorted::after { content: " \25BE"; }
th.sorted.asc::after { content: " \25B4"; }
tbody tr { cursor: pointer; }
tbody tr:hover { background: var(--chip); }
tbody tr.active { background: color-mix(in srgb, var(--accent) 13%, transparent); }
tbody tr:last-child td { border-bottom: 0; }

.tick { font-weight: 650; }
.co { color: var(--muted); font-size: 13px; max-width: 210px; overflow: hidden; text-overflow: ellipsis; }
.pos { color: var(--pos); }
.neg { color: var(--neg); }
.na { color: var(--muted); font-size: 12px; font-style: italic; }

.pill {
  display: inline-block; min-width: 46px; padding: 2px 8px; border-radius: 6px;
  font-weight: 650; font-size: 13px; text-align: center;
}
.pill.hi { background: color-mix(in srgb, var(--pos) 20%, transparent); color: var(--pos); }
.pill.lo { background: color-mix(in srgb, var(--neg) 20%, transparent); color: var(--neg); }
.pill.mid { background: var(--chip); color: var(--muted); }

/* ---- "show more" pager ---- */
.more:empty { display: none; }
.more { padding: 11px; border-top: 1px solid var(--border); text-align: center; }
.more button {
  font: inherit; font-size: 13px; cursor: pointer; padding: 7px 16px;
  color: var(--text); background: var(--chip);
  border: 1px solid var(--border); border-radius: 7px;
}
.more button:hover { border-color: var(--accent); color: var(--accent); }
.more .n { color: var(--muted); }

/* ---- detail panel ---- */
#detail {
  padding: 18px; position: sticky; top: 14px;   /* top must match STICKY_TOP in app.js */
  /* --detail-h is measured in app.js on load, resize AND scroll. A fixed
     100vh is wrong here: at the top of the page this pane starts ~330px down,
     so its final third would sit below the fold with no way to scroll to it. */
  max-height: var(--detail-h, calc(100vh - 28px));
  overflow-y: auto;
  /* Deliberately NOT overscroll-behavior:contain. Reaching the end of this
     pane should carry on into the page, rather than dead-ending and forcing
     you to move the cursor somewhere else to keep going. */
}

/* Single column on narrow screens: nested scroll boxes inside a page that is
   already scrolling is miserable on a phone, so let both panes size naturally. */
@media (max-width: 900px) {
  .layout { grid-template-columns: 1fr; }
  .scroll { max-height: 70vh; }
  #detail { position: static; max-height: none; overflow-y: visible; }
}
#detail h2 { margin: 0 0 2px; font-size: 19px; }
#detail .co2 { color: var(--muted); font-size: 13px; margin-bottom: 14px; }
.empty { color: var(--muted); font-size: 14px; text-align: center; padding: 40px 10px; }

/* ---- price chart ---- */
.spark { width: 100%; height: 58px; display: block; }
.spark-wrap { position: relative; height: 58px; cursor: crosshair; }
.spark-wrap:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }

/* .spark-tip sets display:flex, which would beat the UA's [hidden] rule --
   this is more specific, so hidden really means hidden. */
.spark-wrap [hidden] { display: none; }

.spark-cross {
  position: absolute; top: 0; bottom: 0; width: 1px;
  background: var(--muted); opacity: .45;
  transform: translateX(-.5px); pointer-events: none;
}
.spark-dot {
  position: absolute; width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent); border: 2px solid var(--panel);
  transform: translate(-50%, -50%); pointer-events: none;
}
.spark-tip {
  position: absolute; top: -4px; z-index: 3; pointer-events: none;
  display: flex; gap: 8px; align-items: baseline; white-space: nowrap;
  padding: 3px 8px; font-size: 11px;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 6px; box-shadow: var(--shadow);
}
.spark-tip[data-side="right"] { transform: translateX(7px); }
.spark-tip[data-side="left"]  { transform: translateX(-100%) translateX(-7px); }
.spark-tip b { font-size: 12px; font-variant-numeric: tabular-nums; }
.spark-tip span { color: var(--muted); font-variant-numeric: tabular-nums; }
.spark-tip .pos, .spark-tip .neg { font-weight: 600; }

.spark-cap {
  display: flex; justify-content: space-between; gap: 10px;
  font-size: 11px; color: var(--muted); margin: 5px 0 15px;
  font-variant-numeric: tabular-nums;
}

.why { border: 1px solid var(--border); border-radius: 8px; padding: 11px 13px; margin-bottom: 12px; }
.why h3 { margin: 0 0 7px; font-size: 12px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.kv { display: flex; justify-content: space-between; gap: 12px; font-size: 13px; padding: 2px 0; }
.kv span:last-child { font-variant-numeric: tabular-nums; font-weight: 600; }
.why p { margin: 7px 0 0; font-size: 12px; color: var(--muted); line-height: 1.45; }

/* Component-score bars in the breakdown panel. */
/* display:block is load-bearing -- this is a <span> inside <summary>, and an
   inline element ignores height/width entirely. */
.bar { display: block; height: 4px; background: var(--chip); border-radius: 3px; margin: 3px 0 8px; overflow: hidden; }
.bar i { display: block; height: 100%; background: var(--accent); border-radius: 3px; }

/* ---- collapsible sections ----
   Native <details>, so keyboard and screen-reader support come for free. */
summary { cursor: pointer; list-style: none; }
summary::-webkit-details-marker { display: none; }

/* One dimension of the score. The label, number and bar stay visible when
   shut -- the point is a simple view that still shows the MIX, with the
   measurements available on demand rather than removed. */
.breakdown { padding-bottom: 4px; }
.dim { border-top: 1px solid var(--border); }
.dim:first-of-type { border-top: 0; }
.dim > summary { padding: 7px 0 3px; }
.dim-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; font-size: 13px; }
.dim-name { display: flex; align-items: baseline; gap: 6px; }
.dim-name::before {
  content: "\25B8"; display: inline-block; font-size: 10px;
  color: var(--muted); transition: transform .15s ease;
}
.dim[open] .dim-name::before { transform: rotate(90deg); }
.dim > summary:hover .dim-name,
.dim[open] .dim-name { color: var(--accent); }
.dim-score { font-variant-numeric: tabular-nums; font-weight: 650; }
.dim-body {
  padding: 4px 0 8px 13px; margin: 2px 0 9px 3px;
  border-left: 2px solid var(--border);
}
.dim-body p:last-child { margin-bottom: 0; }

details.why > summary {
  display: flex; align-items: center; gap: 7px;
  font-size: 12px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--muted);
}
details.why > summary::before {
  content: "\25B8"; display: inline-block; font-size: 10px;
  transition: transform .15s ease;
}
details.why[open] > summary { margin-bottom: 8px; }
details.why[open] > summary::before { transform: rotate(90deg); }
details.why > summary:hover { color: var(--text); }
details.why > summary .n { text-transform: none; letter-spacing: 0; opacity: .75; }

@media (prefers-reduced-motion: reduce) {
  .dim-name::before, details.why > summary::before { transition: none; }
}

.news { list-style: none; margin: 0; padding: 0; }
.news li { padding: 9px 0; border-bottom: 1px solid var(--border); font-size: 13px; display: flex; gap: 9px; }
.news li:last-child { border-bottom: 0; }
.news .dot { flex: 0 0 6px; height: 6px; border-radius: 50%; margin-top: 7px; background: var(--muted); }
.news .dot.p { background: var(--pos); }
.news .dot.n { background: var(--neg); }
.news .meta { color: var(--muted); font-size: 11px; margin-top: 2px; }
.news a { color: inherit; text-decoration: none; }
.news a:hover { color: var(--accent); text-decoration: underline; }

footer { margin-top: 26px; color: var(--muted); font-size: 12px; line-height: 1.6; }
