/* SignalTimeline — the LOCKED timeline design (SIGNALS.md §9, brief §15-20,
 * MOBILE_PLAN.md §2.8).
 *
 * The visual language is exactly:
 *
 *   Signal ───── 1H ───── 8H ───── 24H ───── 48H
 *   $976.84      $983.68   $975.57   $991.26    $1,004.20
 *                +0.70%    -0.13%    +1.48%     +2.80%
 *
 * Mobile (P8 — wave 1c): the four rows sit inside
 * `div.signal-timeline-track`, which is the `content` of a `div.scroll-x`
 * from components/scroll-x.js. The track's `min-width` is
 * `calc(var(--tl-col-min) * var(--tl-cols))` — `--tl-col-min` is 88 px and
 * `--tl-cols` is set to N+1 from JS so the track is at least 88 px per
 * column. On desktop the available width is at least that minimum, there is
 * no scroll, no edge fade, and the rendering is pixel-identical to T42
 * (LOCKED visual). On phones the track overflows the region, the region
 * scrolls, and the edge fade from `--mask-opaque` is painted on the side
 * with hidden content. The page itself never scrolls horizontally.
 *
 * Hotspot tap targets (P8 — wave 1c): under `(pointer:coarse)` each
 * hotspot's `::after` extends the hit area to at least `var(--hit-min)`
 * tall, covering the price and return rows. Visually the hotspot stays the
 * same; tapping it opens the popover, scrolling the track closes it.
 *
 * One CSS Grid (.signal-timeline-grid, 3 rows x N+1 columns) per timeline.
 * Row 1 carries the labels (Signal + each checkpoint), row 2 the prices,
 * row 3 the returns; an invisible focusable hotspot per checkpoint spans
 * rows 2-3 of its column (keyboard + tooltip). Each label cell except the
 * last is a flex row of its text and a flex:1 .signal-timeline-connector
 * whose border-top is a continuous rule to the next label, so the "-----"
 * is layout, never typed characters.
 *
 * Colour, type, spacing, radius and motion come only from tokens.css:
 * --timeline-surface, --timeline-border, --timeline-connector,
 * --timeline-mono, --muted-pending. No literal colours anywhere here.
 */

/* ---- surface container --------------------------------------------------- */

.signal-timeline {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  background: var(--timeline-surface);
  border: 1px solid var(--timeline-border);
  border-radius: var(--timeline-radius);
  padding: var(--timeline-pad);
  font-family: var(--timeline-mono);
  font-size: var(--timeline-fs);
  line-height: var(--timeline-lh);
  color: var(--ink);
  position: relative;
  /* LOCKED desktop: the surface hugs the track (which hugs the grid at
     760 px on every breakpoint where the grid's fixed width fits).
     `max-width: 100%` is what makes a phone's narrow panel clamp the
     surface to the panel; the track inside then scrolls inside the
     `div.scroll-x` region added by the component. */
  width: fit-content;
  max-width: 100%;
  min-width: 0;
  box-sizing: border-box;
}

/* ---- the track (scroll-x content slot) ---------------------------------- */

/* The track is what scroll-x wraps. Its min-width is the brief's formula
   (88 px per column, where `--tl-cols` is set to N+1 from JS). On desktop
   the track hugs its content (the grid, at 760 px); on a phone the track
   is at least `--tl-col-min * --tl-cols` and the scroll-x region scrolls
   horizontally. */
.signal-timeline-track {
  width: max-content;
  min-width: calc(var(--tl-col-min) * var(--tl-cols, 4));
}

/* ---- the one grid ---------------------------------------------------------
 * Columns are set inline by the component (one per point). The four row
 * wrappers are display:contents so every cell is a direct grid item pinned
 * to its column; rows are explicit so the hotspot can span price + return.
 * Column gap is zero: the connector rule inside each label cell runs all the
 * way to the next label, and the value cells carry their own end padding. */

.signal-timeline-grid {
  display: grid;
  grid-template-rows: auto auto auto;
  row-gap: 0;
  column-gap: 0;
  width: var(--timeline-grid-w);
  min-width: max-content;
  align-items: center;
}

.signal-timeline-labels,
.signal-timeline-hotspots,
.signal-timeline-prices,
.signal-timeline-returns {
  display: contents;
}

/* ---- label row + connector rule ---------------------------------------- */

.signal-timeline-label {
  grid-row: 1;
  display: flex;
  align-items: center;
  min-width: 0;
  white-space: nowrap;
  font-weight: var(--fw-medium);
  color: var(--muted);
  text-align: start;
}

/* The connector: a flex:1 element whose top border is the rule. It starts a
   little after this label's text and ends a little before the next label,
   vertically centred on the label line. The last label has none. */
.signal-timeline-connector {
  flex: 1 1 auto;
  min-width: var(--timeline-connector-min);
  height: 0;
  border-top: 1px solid var(--timeline-connector);
  margin-inline: var(--space-2);
  pointer-events: none;
}

/* ---- prices row --------------------------------------------------------- */

.signal-timeline-price {
  grid-row: 2;
  padding-top: var(--timeline-price-gap);
  padding-inline-end: var(--timeline-col-gap);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  text-align: start;
}

.signal-timeline-failed-price {
  color: var(--muted-pending);
}

/* ---- returns row -------------------------------------------------------- */

.signal-timeline-return {
  grid-row: 3;
  padding-top: var(--timeline-return-gap);
  padding-inline-end: var(--timeline-col-gap);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  text-align: start;
}

.signal-timeline-return-val.pos { color: var(--pos); font-weight: var(--fw-medium); }
.signal-timeline-return-val.neg { color: var(--neg); font-weight: var(--fw-medium); }

.signal-timeline-pending {
  color: var(--muted-pending);
}

.signal-timeline-failed {
  color: var(--muted-pending);
  font-style: italic;
}

/* ---- hotspots (focusable buttons over price + return) ------------------ */

.signal-timeline-hotspot-cell {
  grid-row: 2 / span 2;
  align-self: stretch;
  position: relative;
  z-index: 1;
  display: flex;
  pointer-events: none;
}

.signal-timeline-hotspot {
  pointer-events: auto;
  appearance: none;
  border: 0;
  background: transparent;
  padding: 0;
  margin-inline-start: calc(-1 * var(--space-1));
  margin-inline-end: var(--space-3);
  margin-block-end: calc(-1 * var(--space-1));
  flex: 1 1 auto;
  cursor: pointer;
  border-radius: var(--radius-sm);
  outline: none;
}

.signal-timeline-hotspot:hover,
.signal-timeline-hotspot:focus {
  box-shadow: inset 0 0 0 1px var(--timeline-connector);
}

.signal-timeline-hotspot:focus-visible {
  outline: 2px solid var(--focus-ring);
  outline-offset: 0;
}

/* On coarse pointers (phones, tablets) the hotspot keeps its 18 px visual
   but its tap target extends to at least `var(--hit-min)` tall and the full
   column width, covering the price and return rows. Only the ::after
   pseudo-element grows (Pattern 1 from MOBILE_PLAN §2.9); the button
   itself keeps its fine-pointer size so the desktop visual and the
   price/return row spacing never change. The pseudo-element takes
   pointer events so a tap anywhere in the column opens the popover;
   scrolling the track closes it (the popover listens for scroll on any
   ancestor). */
@media (pointer: coarse) {
  .signal-timeline-hotspot {
    position: relative;
  }
  .signal-timeline-hotspot::after {
    content: "";
    position: absolute;
    inset: 0;
    width: max(100%, var(--hit-min));
    height: max(100%, var(--hit-min));
    pointer-events: auto;
  }
}

/* ---- legend line under the timeline ------------------------------------ */

.signal-timeline-legend {
  position: sticky;
  left: 0;
  padding-top: var(--space-2);
  border-top: 1px solid var(--timeline-border);
  text-align: center;
  font-family: var(--font-sans);
}

/* ---- tooltip content (rendered into the Popover bubble) ------------------
 *
 * The Popover primitive (components/popover.css) owns the bubble itself
 * (position, background, border, shadow, max-width, padding). The rules
 * below style only the body content the SignalTimeline emits — the title,
 * the label/value rows and the trailing note. They are scoped under
 * `.popover` so the SignalTimeline never bleeds into other bubbles, and
 * they deliberately omit `position: fixed`, `display: none` /
 * `display: block`, `pointer-events: none`, `min-width` / `max-width`,
 * `background`, `border`, `border-radius`, `box-shadow` and `padding` —
 * the Popover owns all of those. Desktop hover renders the exact same
 * shape and tone as the T42 tooltip on origin/main; on touch the bubble
 * is the Popover, not this file.
 *
 * These rules also exist as a sanity guard: signal-timeline.js renders
 * the body with class="signal-tooltip" (and its children with
 * `signal-tooltip-title`, `signal-tooltip-row`, `signal-tooltip-label`,
 * `signal-tooltip-value`, `signal-tooltip-note`) so the visual is
 * preserved even if a future caller drops the body somewhere other than
 * a Popover.
 */

/* The bubble that carries a timeline tooltip keeps the LOCKED desktop box of
   the old .signal-tooltip exactly: its padding, surface, border, width band
   and the inherited (normal) line-height — the Popover only positions it. */
.popover:has(> .signal-tooltip) {
  min-width: min(240px, calc(100vw - 16px));
  max-width: min(320px, calc(100vw - 16px));
  padding: var(--space-3);
  background: var(--chart-tooltip-bg);
  border-color: var(--panel-border);
  font-size: var(--fs-small);
  line-height: 1.45; /* the body's, which the old fixed tooltip inherited */
}
.popover .signal-tooltip {
  font-family: var(--font-sans);
  font-size: var(--fs-small);
  color: var(--ink);
  line-height: 1.45;
}

.popover .signal-tooltip-title {
  font-family: var(--font-mono);
  font-size: var(--fs-label);
  font-weight: var(--fw-semibold);
  color: var(--muted);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  margin-bottom: var(--space-2);
}

.popover .signal-tooltip-row {
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-1) 0;
}

.popover .signal-tooltip-label {
  color: var(--muted);
}

.popover .signal-tooltip-value {
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.popover .signal-tooltip-note {
  margin-top: var(--space-2);
  padding-top: var(--space-2);
  border-top: 1px solid var(--panel-border);
  color: var(--muted);
  font-size: var(--fs-label);
}

/* ---- narrow screens ------------------------------------------------------
 * On a phone the track is the scrolling region and the grid keeps its
 * column-floor (`--tl-col-min`) per column. The grid's content keeps the
 * surface's LOCKED desktop width on a desktop panel and shrinks to its
 * columns' max-content on a phone panel — the scroll-x then scrolls the
 * track inside the surface, never the page. The breakpoint is the F1
 * phone-side token set (767.98 px, paired with the lg desktop token). */
@media (max-width: 767.98px) {
  .signal-timeline-grid {
    width: max-content;
  }
}

/* The strip scrolls sideways only. The hotspot buttons are taller than their
   grid rows (they always overflowed a little on desktop, harmlessly, before
   there was a scroll box). Inside the scroll-x that overflow made the region
   scroll vertically, so focusing a hotspot shifted the labels up. The padding
   gives the overflow room inside the region; the equal negative margin keeps
   the page layout — and the LOCKED desktop pixels — exactly as before. */
.signal-timeline > .scroll-x {
  overflow-y: hidden;
  padding-bottom: var(--space-2);
  margin-bottom: calc(-1 * var(--space-2));
}
