/* View-specific layout. */

/* ---------- Home ---------- */

.view h1.dashboard-title { font-size: 28px; margin-bottom: 18px; }

/* Dashboard top strip: the insider-flow box (1/3) beside the stat tiles (2/3). */
.dashboard-top {
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: 16px;
  align-items: stretch;
  margin-bottom: 16px; /* same as the grid gap, so the row below lines up */
}
.dashboard-top .home-hero { margin-bottom: 0; }

@media (max-width: 820px) {
  .dashboard-top { grid-template-columns: 1fr; }
}

.home-hero {
  display: grid;
  grid-template-columns: 1fr 1fr; /* 2×2 — leaves room for each tile's chart + period toggle */
  gap: 16px; /* matches the dashboard-top column gap so all card gaps are equal */
  margin-bottom: 8px;
}
@media (max-width: 520px) {
  .home-hero { grid-template-columns: 1fr; }
}

/* ---------- Metric tile (headline number + trend chart) ---------- */

.metric-tile {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 17px 19px;
}
.metric-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.metric-head .stat-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 16.5px;
  font-weight: 700;
  color: var(--ink);
}
.metric-controls { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
/* Compact 4-way period toggle that fits the tile header. */
.metric-period { padding: 2px; flex-shrink: 0; }
.metric-period button { padding: 2px 6px; font-size: 11px; line-height: 1.4; }
.metric-tile .stat-value { margin-top: 0; }
.metric-chart { margin-top: auto; padding-top: 6px; }
.metric-axis {
  display: flex;
  justify-content: space-between;
  gap: 4px;
  font-size: 10.5px;
  color: var(--ink-2);
  padding-top: 5px;
  min-height: 1em;
}
.metric-axis span { white-space: nowrap; }

/* Bar/line chart-type toggle — sits left of a period selector. */
.chart-mode { padding: 2px; flex-shrink: 0; }
.chart-mode button { padding: 2px 6px; line-height: 1; display: flex; }
.big-controls .chart-mode button { padding: 4px 8px; }

/* Responsive HTML column chart. */
.mini-bars {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  width: 100%;
  position: relative;
}
.mini-bar-wrap {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: flex-end;
  height: 100%;
  border-radius: 3px 3px 0 0;
  position: relative;
}
.mini-bar {
  width: 100%;
  background: var(--bar-color);
  border-radius: 3px 3px 0 0;
  transition: filter 0.12s;
}
.mini-bar.is-empty { background: transparent; }
.mini-bar-wrap { cursor: crosshair; }
.mini-bar-wrap:hover .mini-bar:not(.is-empty) { filter: brightness(1.15) saturate(1.1); }
/* Dashboard metric tiles: a bar is a link into the Database for that bucket. */
.metric-chart .mini-bar-wrap { cursor: pointer; }

/* Line-chart mode: an SVG line + area sits behind the (now invisible) hover
   columns, which keep the exact same layout so hover/tooltip targeting is
   unchanged between bar and line mode. */
.trend-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* ---------- Biggest-trades volume chart ---------- */

.big-card { padding: 19px 22px; }
/* Title + filters now live inside the card, so drop the section-head's outer
   top margin and let the card's own padding provide the breathing room. */
.big-head { margin: 0 0 16px; }
.big-controls { flex-wrap: wrap; gap: 8px; align-items: center; }
.big-controls .seg button { padding: 4px 12px; font-size: 12.5px; }
.big-controls .feed-select { font-size: 12.5px; }

/* Periods abbreviated to one letter each. Without a floor the chips would be as
   wide as their glyph, and D W M Q Y would step unevenly across the row. */
.seg-initials button { min-width: 30px; text-align: center; }
.big-controls .seg-initials button { padding: 4px 6px; }

.vol-bars { gap: 3px; align-items: flex-end; }
.vol-bars .mini-bar { border-radius: 3px 3px 0 0; transition: filter 0.12s; }
.vol-bar-wrap {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  align-items: flex-end;
  height: 100%;
  border-radius: 3px 3px 0 0;
  cursor: pointer;
  position: relative;
}
.vol-bar-wrap:hover .mini-bar,
.vol-bar-wrap:focus-visible .mini-bar { filter: brightness(1.18) saturate(1.1); }
.vol-bar-wrap:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* Line mode: a fixed-size circular dot per trade (never distorted by the
   chart's non-uniform scale, unlike an SVG circle would be), sitting on the
   connecting trend line drawn by .trend-svg. */
.vol-dot {
  position: absolute;
  left: 50%;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  transform: translate(-50%, 50%);
  box-shadow: 0 0 0 2px var(--surface);
  transition: transform 0.12s;
}
.vol-bar-wrap:hover .vol-dot,
.vol-bar-wrap:focus-visible .vol-dot { transform: translate(-50%, 50%) scale(1.35); }

/* Interactive hover card for a bar: the exact trade + a link to open it. */
.trade-pop[hidden] { display: none; } /* author display would otherwise beat [hidden] */
.trade-pop {
  position: fixed;
  z-index: 65;
  width: 340px;
  max-width: calc(100vw - 16px);
  padding: 12px 14px;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  box-shadow: var(--shadow-pop);
}
.tp-head { display: flex; align-items: flex-start; gap: 10px; }
.tp-head .ticker-chip { flex: none; width: 38px; height: 38px; font-size: 10px; }
.tp-head-main { min-width: 0; flex: 1; }
.tp-name {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 8px;
  font-weight: 650;
  font-size: 14px;
  line-height: 1.3;
}
.tp-name .badge { flex: none; }
.tp-sub { font-size: 12.5px; color: var(--ink-2); line-height: 1.35; }
.tp-stats {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  margin: 12px 0;
  padding: 10px 0;
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}
.tp-stats > div { display: flex; flex-direction: column; gap: 2px; }
.tp-k { font-size: 11px; color: var(--ink-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.tp-v { font-size: 14px; font-weight: 650; }
.tp-link {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
}
.vol-empty {
  display: grid;
  place-items: center;
  color: var(--ink-muted);
  font-size: 13.5px;
}

.vol-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--hairline);
  font-size: 12px;
}
.vol-cap { color: var(--ink-muted); font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; }
.vol-legend { display: flex; gap: 16px; }

/* Cursor tooltip for chart bars — value on top, period date beneath. */
.chart-tip[hidden] { display: none; } /* author display:flex would otherwise beat [hidden] */
.chart-tip {
  position: fixed;
  z-index: 70;
  pointer-events: none;
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 6px 9px;
  border-radius: 8px;
  background: var(--ink);
  color: var(--page);
  box-shadow: var(--shadow-pop);
  white-space: nowrap;
}
.chart-tip-val { font-size: 12.5px; font-weight: 700; }
/* The second panel's reading, when a chart has one. Same weight as the first —
   neither measure is a footnote to the other — but set apart so the two are not
   read as one phrase. */
.chart-tip-val2 {
  margin-top: 1px;
  padding-top: 3px;
  border-top: 1px solid rgba(255, 255, 255, 0.16);
  font-size: 12.5px;
  font-weight: 700;
}
.chart-tip-date { font-size: 11px; opacity: 0.7; }

/* Info dot — the "what is this" affordance that sits to the left of a chart,
   table, or indicator title. Recessive at rest; full ink on hover/focus. */
.info-dot {
  appearance: none;
  -webkit-appearance: none;
  margin: 0 5px 0 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink-muted);
  line-height: 0;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
  border-radius: 50%;
  cursor: help;
  transition: color 0.15s ease;
}
.info-dot:hover { color: var(--ink); }
.info-dot:focus { outline: none; }
.info-dot:focus-visible {
  color: var(--ink);
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.info-dot svg { display: block; }

/* Its floating explanation — a wrapping panel (not the single-line cursor tip),
   anchored under or above the dot by wireInfoTips and clamped to the viewport. */
.info-tip[hidden] { display: none; }
.info-tip {
  position: fixed;
  z-index: 75;
  max-width: 300px;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--ink);
  color: var(--page);
  box-shadow: var(--shadow-pop);
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.5;
  pointer-events: none;
}

/* ---------- Graph view (buys vs sells over time) ---------- */

.graph-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; align-items: stretch; }
@media (max-width: 1000px) { .graph-grid { grid-template-columns: 1fr; } }

.graph-card { padding: 18px 20px; }
.graph-card-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
  margin-bottom: 16px;
}
.graph-card-titles { flex: 1 1 160px; min-width: 0; }
.graph-card-title { font-size: 15px; font-weight: 700; color: var(--ink); }
/* Bar/line toggle + period selector, always clustered at the row's right edge
   (wraps below the title on narrow cards rather than crowding it). */
.graph-card-controls { display: flex; align-items: center; gap: 6px; flex-shrink: 0; margin-left: auto; }
.graph-mode { padding: 2px; flex-shrink: 0; }
.graph-mode button { padding: 2px 6px; line-height: 1; display: flex; }
.graph-period { padding: 2px; flex-shrink: 0; }
.graph-period button { padding: 3px 9px; font-size: 12px; line-height: 1.4; }

/* Approximate date axis under the buy/sell charts — evenly-spaced bucket labels
   spread edge-to-edge, matching the dashboard tiles' .metric-axis. */
.graph-axis {
  display: flex;
  justify-content: space-between;
  gap: 4px;
  font-size: 11px;
  color: var(--ink-2);
  padding-top: 6px;
  min-height: 1em;
}
.graph-axis span { white-space: nowrap; }

.graph-card-foot {
  display: flex;
  justify-content: flex-end;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--hairline);
}
.graph-legend { display: flex; gap: 16px; font-size: 12px; font-weight: 600; }
.flow-legend-item.median { color: var(--ink-2); }
.flow-legend-item.median::before {
  height: 0;
  border-top: 2px dashed var(--accent);
  background: none;
  border-radius: 0;
}

/* Diverging column chart: buys rise (green) above a zero baseline, sells fall
   (red) below it, on one shared scale. */
.dv-chart {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: 2px;
  width: 100%;
}
.dv-wrap {
  flex: 1 1 0;
  min-width: 0;
  position: relative;
  height: 100%;
  cursor: crosshair;
}
.dv-up, .dv-down {
  position: absolute;
  left: 0;
  width: 100%;
  transition: filter 0.12s;
}
.dv-up { border-radius: 3px 3px 0 0; }
.dv-down { border-radius: 0 0 3px 3px; }
.dv-wrap:hover .dv-up,
.dv-wrap:hover .dv-down { filter: brightness(1.15) saturate(1.1); }
.dv-zero {
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--ink-muted);
  opacity: 0.5;
  z-index: 1;
  pointer-events: none;
}

/* Horizontal reference line (e.g. a median) over a mini-bars chart. */
.mini-guide {
  position: absolute;
  left: 0;
  right: 0;
  height: 0;
  border-top: 2px dashed var(--accent);
  z-index: 2;
  pointer-events: none;
}
.mini-guide-label {
  position: absolute;
  right: 0;
  top: -8px;
  padding: 0 4px;
  font-size: 10px;
  font-weight: 600;
  color: var(--accent);
  background: var(--surface);
  border-radius: 3px;
}

/* Insider-sentiment card: full width beneath the 3-up grid. */
.sentiment-card { margin-top: 16px; }
.sentiment-period button { padding: 3px 11px; }

/* The stacked plots — sentiment, and optionally the index price under it. The
   hover overlay is their sibling, not a child of either, so one crosshair reads
   across both. Every layer spans the full width and aligns to the same x, so the
   same date sits under the crosshair in both panels and the line reaches the edge. */
.sentiment-panels {
  position: relative;
  width: 100%;
}

/* The rolling buy-share line, with two horizontal threshold guides. */
.sentiment-chart {
  position: relative;
  width: 100%;
  overflow: hidden;
}

/* Right-hand % axis for the sentiment plot — the same treatment the price panel
   gives its dollar levels, so the two panels read as one scale-per-side stack.
   The labels float over the plot on an opaque chip (below), so the line can run
   edge to edge behind them instead of stopping short of a reserved gutter. */
.sent-grid-lines {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
}
.sent-grid {
  position: absolute;
  left: 0;
  right: 0;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 5px;
}
.sent-grid > i {
  flex: 1;
  height: 0;
  border-top: 1px dashed var(--hairline);
}
.sent-grid-label {
  flex: none;
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--surface);
  box-shadow: 0 0 0 3px var(--surface);
  color: var(--ink-muted);
  font-size: 10px;
  font-weight: 700;
  line-height: 1.4;
}

/* The S&P 500 proxy: its own baseline and its own scale, stacked beneath. The
   rule between the panels is the visual promise that they do not share a y-axis. */
.spx-panel {
  position: relative;
  width: 100%;
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--hairline);
  overflow: hidden;
}
/* Horizontal price levels, so the line reads as dollars and not as a shape. */
.spx-grid-lines {
  position: absolute;
  left: 0;
  right: 0;
  top: 8px;
  bottom: 0;
  /* Above the price line: the dashed guides and their labels read as the scale,
     so the line passes behind the opaque labels instead of striking through them. */
  z-index: 1;
  pointer-events: none;
}
.spx-grid {
  position: absolute;
  left: 0;
  right: 0;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  gap: 5px;
}
.spx-grid > i {
  flex: 1;
  height: 0;
  border-top: 1px dashed var(--hairline);
}
.spx-grid-label {
  flex: none;
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--surface);
  box-shadow: 0 0 0 3px var(--surface);
  color: var(--ink-muted);
  font-size: 10px;
  font-weight: 700;
  line-height: 1.4;
}
.spx-name {
  position: absolute;
  top: 8px;
  left: 0;
  color: var(--muted-tone);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
/* Evenly-spaced date ticks under the line. */
.sentiment-axis {
  position: relative;
  height: 16px;
  margin-top: 6px;
  border-top: 1px solid var(--hairline);
  padding-top: 5px;
}
.sentiment-tick {
  position: absolute;
  top: 5px;
  font-size: 11px;
  font-weight: 500;
  color: var(--ink-muted);
  white-space: nowrap;
}
.sentiment-cols {
  position: absolute;
  inset: 0;
  display: flex;
  z-index: 3;
}
.sentiment-cols .mini-bar-wrap {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  height: 100%;
  cursor: crosshair;
}
/* One crosshair down the full stack, so the eye can carry a date from the
   sentiment line to the price line without leaving the sample it is reading. */
.sentiment-cols .mini-bar-wrap:hover::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  background: var(--ink-muted);
  opacity: 0.5;
}
/* Threshold reference lines (bullish / very bullish). */
.sentiment-guide {
  position: absolute;
  left: 0;
  right: 0;
  height: 0;
  z-index: 2;
  pointer-events: none;
}
/* Threshold guides sit off the green sentiment line's hue and off each other, so
   the two levels stay legible where the line hovers around them. */
.sentiment-guide.bullish { border-top: 2px dashed var(--muted-mark); opacity: 0.9; }
.sentiment-guide.very { border-top: 2px solid var(--highlight-mark); }
.sentiment-guide-label {
  position: absolute;
  left: 0;
  top: -8px;
  padding: 0 4px;
  font-size: 10px;
  font-weight: 700;
  color: var(--highlight);
  background: var(--surface);
  border-radius: 3px;
}
.sentiment-guide.bullish .sentiment-guide-label { color: var(--muted-tone); }

/* The "Overlay S&P 500" switch, sitting left of the period selector. */
.overlay-toggle {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 3px 11px 3px 8px;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  background: none;
  color: var(--ink-muted);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}
.overlay-toggle:hover { border-color: var(--ink-muted); color: var(--ink-2); }
.overlay-switch {
  position: relative;
  width: 24px;
  height: 14px;
  flex: none;
  border-radius: 999px;
  background: var(--hairline);
  transition: background 0.15s ease;
}
.overlay-switch::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 2px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--surface);
  box-shadow: 0 1px 2px rgba(9, 9, 11, 0.25);
  transition: transform 0.15s ease;
}
.overlay-toggle[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); }
.overlay-toggle[aria-pressed="true"] .overlay-switch { background: var(--cta); }
.overlay-toggle[aria-pressed="true"] .overlay-switch::after { transform: translateX(10px); }
@media (prefers-reduced-motion: reduce) {
  .overlay-switch, .overlay-switch::after { transition: none; }
}

/* Sentiment legend swatches: a line-coloured chip + two threshold styles. */
.flow-legend-item.line { color: var(--buy); }
.flow-legend-item.line::before { background: var(--buy-mark); }
.flow-legend-item.index { color: var(--muted-tone); }
.flow-legend-item.index::before { background: var(--muted-tone); }
.flow-legend-item.bullish { color: var(--muted-tone); }
.flow-legend-item.bullish::before {
  height: 0;
  width: 14px;
  border-top: 2px dashed var(--muted-mark);
  background: none;
  border-radius: 0;
}
.flow-legend-item.very-bullish { color: var(--highlight); }
.flow-legend-item.very-bullish::before {
  height: 0;
  width: 14px;
  border-top: 2px solid var(--highlight-mark);
  background: none;
  border-radius: 0;
}

/* ---------- Bullish / bearish company ranking tables ---------- */

.ranking-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 16px;
  margin-top: 16px;
}
@media (max-width: 1000px) { .ranking-grid { grid-template-columns: 1fr; } }

.ranking-card { padding: 0; overflow: hidden; }

/* Caption bar spanning the table, tinted by sentiment side. */
.ranking-cap {
  padding: 11px 16px;
  text-align: center;
  font-size: 13px;
  font-weight: 700;
  color: var(--ink);
  border-bottom: 1px solid var(--hairline);
}
.ranking-cap span { font-weight: 500; color: var(--ink-muted); }
.ranking-cap.bull { background: var(--buy-wash); }
.ranking-cap.bear { background: var(--sell-wash); }

/* Scroll region — vertical for up to 40 rows, horizontal on narrow screens. */
.ranking-scroll { max-height: 520px; overflow: auto; }

.ranking-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}
.ranking-table th,
.ranking-table td {
  padding: 8px 14px;
  text-align: left;
  white-space: nowrap;
}
.ranking-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface-2);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--ink-muted);
  border-bottom: 1px solid var(--hairline);
}
.ranking-table tbody tr { border-bottom: 1px solid var(--hairline); }
.ranking-table tbody tr:last-child { border-bottom: 0; }
.ranking-table tbody tr:hover { background: var(--surface-2); }

.ranking-table .rk-num { text-align: right; }
.rk-ticker a { font-weight: 700; color: var(--accent); text-decoration: none; }
.rk-ticker a:hover { text-decoration: underline; }
.rk-delta.up { color: var(--buy); font-weight: 700; }
.rk-delta.down { color: var(--sell); font-weight: 700; }
.rk-cap { color: var(--ink-2); }
.rk-date { color: var(--ink-muted); }
.rk-empty { text-align: center; color: var(--ink-muted); padding: 22px 14px; }

/* ---------- Insider-flow box ---------- */

.flow-box {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 18px;
}
.flow-head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}
.flow-title {
  font-size: 16.5px;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--ink);
}
/* Compact segmented control so all four periods fit the narrow box. */
.flow-period button { padding: 4px 9px; font-size: 12px; }

.flow-range {
  font-size: 12.5px;
  color: var(--ink-2);
  margin: -2px 0 12px;
}
.flow-figs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
.flow-fig { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.flow-fig-label {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-2);
}
.flow-fig-value {
  font-size: 25px;
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.15;
}
.flow-fig.buy .flow-fig-value { color: var(--buy); }
.flow-fig.sell .flow-fig-value { color: var(--sell); }
.flow-fig-sub { font-size: 12px; color: var(--ink-muted); }

.flow-sentiment { display: flex; flex-direction: column; gap: 8px; }
.flow-sent-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.flow-sent-title {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink-2);
}
.flow-sent-verdict {
  font-size: 12px;
  font-weight: 700;
  padding: 2px 9px;
  border-radius: 999px;
}
.flow-sent-verdict.buy { color: var(--buy); background: var(--buy-wash); }
.flow-sent-verdict.sell { color: var(--sell); background: var(--sell-wash); }
.flow-sent-verdict.flat { color: var(--ink-2); background: var(--surface-2); }

/* Diverging 100% bar: buys (green) vs sells (red), 2px surface gap between. */
.flow-bar {
  display: flex;
  gap: 2px;
  height: 10px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
}
.flow-bar-buy { background: var(--buy-mark); }
.flow-bar-sell { background: var(--sell-mark); }
.flow-bar-buy:first-child { border-radius: 999px 0 0 999px; }
.flow-bar-sell:last-child { border-radius: 0 999px 999px 0; }

.flow-legend {
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  font-weight: 600;
}
.flow-legend-item { display: inline-flex; align-items: center; gap: 6px; }
.flow-legend-item::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 2px;
}
.flow-legend-item.buy { color: var(--buy); }
.flow-legend-item.buy::before { background: var(--buy-mark); }
.flow-legend-item.sell { color: var(--sell); }
.flow-legend-item.sell::before { background: var(--sell-mark); }

/* ---------- Sector sentiment: 100%-stacked buy/sell bar per sector ---------- */

.sector-card { margin-top: 16px; }
.graph-card-sub { color: var(--ink-muted); font-weight: 500; }

/* Name | track | buy% | trade count. The last two columns are fixed so the
   tracks all start and end on the same pixel — otherwise the bars aren't
   comparable, which is the only reason to stack them. */
.sector-head,
.sector-row {
  display: grid;
  grid-template-columns: minmax(96px, 168px) 1fr 46px 44px;
  align-items: center;
  gap: 14px;
}
.sector-head {
  padding-bottom: 8px;
  border-bottom: 1px solid var(--hairline);
  color: var(--ink-muted);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.sector-rows { display: flex; flex-direction: column; }
.sector-row { padding: 9px 0; cursor: crosshair; }
.sector-row + .sector-row { border-top: 1px solid var(--hairline); }

.sector-name {
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The 2px gap is the card surface showing through, so the two segments read as
   two quantities rather than one bar with a colour change. A sector with no buys
   has no buy segment at all, and therefore no gap — nothing separates nothing. */
.sector-track {
  display: flex;
  gap: 2px;
  width: 100%;
  height: 14px;
  border-radius: 4px;
  overflow: hidden;
}
.sector-seg { height: 100%; transition: filter 0.12s; }
.sector-row:hover .sector-seg { filter: brightness(1.15) saturate(1.1); }

/* Values wear text tokens, not the series colour: the bar beside them already
   carries the identity, and a green number would claim a precision the 4-trade
   sample doesn't have. */
.sector-pct,
.sector-n {
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.sector-n { color: var(--ink-muted); font-weight: 600; }
.sector-empty { color: var(--ink-muted); font-size: 13px; margin: 0; padding: 12px 0; }

@media (max-width: 640px) {
  .sector-head, .sector-row { grid-template-columns: minmax(80px, 1fr) 2fr 40px 36px; gap: 10px; }
}

/* Forced-colours users lose the green/red distinction entirely, so the segments
   are re-cut as outline vs solid — the buy% column still carries the number. */
@media (forced-colors: active) {
  .sector-seg.buy { background: Highlight !important; }
  .sector-seg.sell { background: Canvas !important; border: 1px solid CanvasText; }
}

/* ---------- Sentiment by market cap: buy & sell share per cap tier ---------- */

.cap-card { margin-top: 16px; }

/* Tier | buy column | sell column. The two value columns are equal-width so a
   glance across a row compares two shares of two different totals without the
   layout implying either one is the larger quantity. */
.cap-head,
.cap-row {
  display: grid;
  grid-template-columns: minmax(96px, 190px) 1fr 1fr;
  align-items: center;
  gap: 18px;
}
.cap-head {
  padding-bottom: 8px;
  border-bottom: 1px solid var(--hairline);
  color: var(--ink-muted);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
/* Each column's total rides in its head, so every % on screen has its denominator. */
.cap-head em {
  color: var(--ink);
  font-style: normal;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0;
  text-transform: none;
}
.cap-rows { display: flex; flex-direction: column; }
.cap-row { padding: 11px 0; }
.cap-row + .cap-row { border-top: 1px solid var(--hairline); }

.cap-name { color: var(--ink); font-size: 12.5px; font-weight: 600; }
.cap-note { color: var(--ink-muted); font-size: 11px; font-weight: 500; white-space: nowrap; }
/* A tier the universe classifies nobody into is dimmed whole: the row is context,
   not a measurement, and must never draw the eye the way a real 0% does. */
.cap-row.is-absent .cap-name { color: var(--ink-muted); font-weight: 500; }

.cap-cell { display: flex; align-items: center; gap: 10px; cursor: crosshair; }
.cap-cell.cap-empty { color: var(--ink-muted); cursor: default; font-size: 13px; }

/* The rail is drawn even at 0%. An empty rail is the visual form of a measured
   zero, and it is what separates "insiders bought nothing here" from "—". */
.cap-track {
  flex: 1 1 0;
  min-width: 0;
  height: 14px;
  border-radius: 4px;
  background: var(--hairline);
  overflow: hidden;
}
.cap-fill { display: block; height: 100%; border-radius: 4px; transition: filter 0.12s; }
.cap-cell:hover .cap-fill { filter: brightness(1.15) saturate(1.1); }

/* Values wear text tokens, not the series colour — the bar carries the identity. */
.cap-pct {
  min-width: 42px;
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.cap-row.is-absent .cap-pct { color: var(--ink-muted); }

.cap-foot { align-items: flex-start; flex-wrap: wrap; gap: 8px 16px; }
.cap-source { color: var(--ink-muted); font-size: 11px; line-height: 1.45; max-width: 62ch; }

@media (max-width: 640px) {
  /* Two bar columns won't fit beside the label. Stack them, and let each cell name
     its own side, since the column head that used to do that is gone. */
  .cap-head { display: none; }
  .cap-row { grid-template-columns: 1fr; gap: 6px; }
  .cap-cell::before {
    content: attr(data-side);
    min-width: 38px;
    color: var(--ink-muted);
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
  }
}

@media (forced-colors: active) {
  .cap-fill.buy { background: Highlight !important; }
  .cap-fill.sell { background: CanvasText !important; }
  .cap-track { border: 1px solid CanvasText; }
}

/* ---------- Insider Fear & Greed gauge ---------- */

.fg-card { margin-top: 16px; }
.fg-chart { display: flex; justify-content: center; padding: 4px 0 2px; }

.gauge {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  max-width: 340px;
}
.gauge-svg { display: block; width: 100%; height: auto; overflow: visible; }

/* The whole ramp stays on screen as the scale; the live zone is lifted to full
   strength while the rest recede, so the reading has a second channel besides the
   needle. Colour is never the only cue — the number and label sit in the well. */
.gauge-seg { opacity: 0.4; transition: opacity 0.18s ease; }
.gauge-seg.is-active { opacity: 1; }
.gauge.is-empty .gauge-seg { opacity: 0.28; }

.gauge-needle {
  stroke: var(--ink);
  stroke-width: 3;
  stroke-linecap: round;
}
.gauge-hub { fill: var(--ink); stroke: var(--surface); stroke-width: 2; }
.gauge-end { fill: var(--ink-muted); font-size: 11px; font-weight: 600; }

.gauge-readout {
  /* Below the dial, not in the well — the needle sweeps the well and would cross the
     text. A small negative margin tucks the number up against the baseline so the
     score still reads as part of the gauge. */
  margin-top: -18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  text-align: center;
  pointer-events: none;
}
.gauge-score {
  font-size: 42px;
  font-weight: 800;
  line-height: 1;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.gauge.is-empty .gauge-score { color: var(--ink-muted); }
.gauge-label { font-size: 13.5px; font-weight: 600; color: var(--ink-2); }
.gauge-sub { font-size: 11px; color: var(--ink-muted); }

.fg-foot { align-items: flex-start; flex-wrap: wrap; gap: 8px 16px; }
.gauge-legend { display: flex; flex-wrap: wrap; gap: 6px 14px; }
.gauge-key {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--ink-2);
}
.gauge-key i {
  width: 10px; height: 10px;
  border-radius: 3px;
  flex: none;
  display: inline-block;
}
.gauge-key em { color: var(--ink-muted); font-style: normal; font-variant-numeric: tabular-nums; }
.gauge-key.is-active { color: var(--ink); font-weight: 600; }
.gauge-key.is-active i { box-shadow: 0 0 0 2px var(--surface), 0 0 0 3px var(--ink-muted); }

@media (forced-colors: active) {
  /* Zone fills collapse to system colours, so the whole scale would read alike —
     the needle, the number and each legend label carry the value instead. */
  .gauge-seg { opacity: 1 !important; }
  .gauge-needle { stroke: CanvasText !important; }
  .gauge-hub { fill: CanvasText !important; stroke: Canvas !important; }
  .gauge-key.is-active i { box-shadow: 0 0 0 2px Canvas, 0 0 0 3px CanvasText; }
}

.flow-net {
  margin-top: auto;
  padding-top: 12px;
  border-top: 1px solid var(--hairline);
  font-size: 13px;
  color: var(--ink-2);
}
.flow-net strong { font-size: 14px; margin-left: 4px; }

/* ---------- Trade details ---------- */

.back-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink-2);
  margin-bottom: 14px;
}
.back-link:hover { color: var(--ink); }

.detail-hero {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
  padding: 20px;
  margin-bottom: 16px;
}
.detail-hero .ticker-chip { width: 54px; height: 54px; font-size: 13px; }
.detail-hero-main { flex: 1; min-width: 200px; }
.detail-hero-main h1 { margin-bottom: 2px; }
.detail-hero-sub { color: var(--ink-2); font-size: 14px; }
.detail-hero-actions { display: flex; gap: 8px; flex-wrap: wrap; }

.detail-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  align-items: start;
}
@media (max-width: 820px) {
  .detail-cols { grid-template-columns: 1fr; }
}

.panel-title {
  font-size: 14px;
  font-weight: 650;
  padding: 14px 16px 0;
}
.panel-note { font-size: 12.5px; color: var(--ink-muted); padding: 0 16px; margin-top: 2px; }

.perf-summary {
  display: flex;
  gap: 20px;
  padding: 14px 16px 6px;
  flex-wrap: wrap;
}

.spark-block { padding: 6px 16px 14px; }

/* ---------- Watchlist ---------- */

/* Title on the left, the "clear all new" action on the right when it's present. */
.watch-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.watch-clear-new { flex-shrink: 0; margin-top: 4px; }

.watch-grid { display: flex; flex-direction: column; gap: 14px; }

.watch-item-head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--hairline);
}
.watch-item-head .grow { flex: 1; min-width: 0; }
.watch-item-head h3 { font-size: 15px; }
.watch-item-head .muted { font-size: 13px; }

/* The head is the disclosure control for the filings below it. Collapsed, there
   is nothing under the rule, so it would draw a line along the card's own edge. */
.watch-block .watch-item-head { cursor: pointer; }
.watch-item-head:has(+ [data-watch-trades][hidden]) { border-bottom-color: transparent; }
.watch-disclose {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--ink-2);
  cursor: pointer;
}
.watch-disclose:hover { background: var(--muted-wash); color: var(--ink); }
.watch-disclose svg { transition: transform 0.16s ease; }
.watch-disclose[aria-expanded="true"] svg { transform: rotate(180deg); }

/* New activity: a watched entity that has filed since the user's last visit. The
   card gets an accent edge, its name a small count pill, and each new filing below
   a tinted rail — all cleared the moment the list is viewed (marks advance). */
.watch-block.has-new { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent-wash); }
/* Per-entity "mark seen" — an accent check in the block head, beside the star. */
.watch-clear-item {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--accent);
  cursor: pointer;
}
.watch-clear-item:hover { background: var(--accent-wash); }
.new-pill {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--cta);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  vertical-align: middle;
  white-space: nowrap;
}
/* Transition lives on the base card so the tint eases away when .is-new is dropped
   (clicking a new filing acknowledges it). */
.watch-block .trade-card { transition: background-color 0.25s ease, border-color 0.25s ease; }
.watch-block .trade-card.is-new { border-left: 3px solid var(--accent); background: var(--accent-wash); }
.watch-block .trade-card.is-new .trade-row:hover { background: var(--accent-wash); }

/* ---------- Alerts ---------- */

.alert-layout {
  display: grid;
  grid-template-columns: minmax(280px, 380px) 1fr;
  gap: 16px;
  align-items: start;
}
@media (max-width: 820px) {
  .alert-layout { grid-template-columns: 1fr; }
}

.alert-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--hairline);
}
.alert-item:last-child { border-bottom: 0; }
.alert-item.is-off { opacity: 0.55; }
.alert-item-main { flex: 1; min-width: 0; }
.alert-item-title { font-weight: 600; font-size: 14px; }
.alert-item-sub { font-size: 12.5px; color: var(--ink-2); }
.alert-del {
  border: 0;
  background: none;
  color: var(--ink-muted);
  padding: 6px;
  border-radius: 8px;
  line-height: 0;
}
.alert-del:hover { color: var(--sell); background: var(--sell-wash); }

/* ---------- Profile ---------- */

.profile-head {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 20px;
  margin-bottom: 16px;
}
.profile-head .avatar { width: 56px; height: 56px; font-size: 19px; }
.profile-head-main { flex: 1; min-width: 0; }

/* The account box glows in the colour of the user's plan, and carries a matching
   tag on the right. All tints are translucent so one rule reads on both themes;
   only the tag's text colour is nudged brighter for dark mode below. */
.profile-head[data-tier="silver"] {
  border-color: rgba(148, 163, 184, 0.45);
  background: linear-gradient(120deg, rgba(148, 163, 184, 0.15), transparent 62%);
  box-shadow: 0 0 0 1px rgba(148, 163, 184, 0.12), 0 10px 34px -10px rgba(148, 163, 184, 0.5);
}
.profile-head[data-tier="gold"] {
  border-color: rgba(234, 179, 8, 0.5);
  background: linear-gradient(120deg, rgba(234, 179, 8, 0.17), transparent 62%);
  box-shadow: 0 0 0 1px rgba(234, 179, 8, 0.16), 0 10px 36px -8px rgba(234, 179, 8, 0.55);
}
.profile-head[data-tier="diamond"] {
  border-color: rgba(56, 189, 248, 0.5);
  background: linear-gradient(120deg, rgba(56, 189, 248, 0.17), transparent 62%);
  box-shadow: 0 0 0 1px rgba(56, 189, 248, 0.16), 0 10px 36px -8px rgba(56, 189, 248, 0.55);
}

.plan-tag {
  flex: none;
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 11px;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.plan-tag svg { width: 13px; height: 13px; }
.plan-tag-silver  { background: rgba(148, 163, 184, 0.18); border-color: rgba(148, 163, 184, 0.4); color: #64748b; }
.plan-tag-gold    { background: rgba(234, 179, 8, 0.16);   border-color: rgba(234, 179, 8, 0.45);  color: #b45309; }
.plan-tag-diamond { background: rgba(56, 189, 248, 0.16);  border-color: rgba(56, 189, 248, 0.45); color: #0369a1; }
:root[data-theme="dark"] .plan-tag-silver  { color: #cbd5e1; }
:root[data-theme="dark"] .plan-tag-gold    { color: #fcd34d; }
:root[data-theme="dark"] .plan-tag-diamond { color: #7dd3fc; }

/* Editable profile picture: a circular button with a camera overlay on hover. */
.avatar-edit {
  position: relative;
  border: 0;
  padding: 0;
  cursor: pointer;
  overflow: hidden;
}
.avatar-photo { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; display: block; }
.avatar-cam {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.5);
  color: #fff;
  opacity: 0;
  transition: opacity 0.15s;
}
.avatar-edit:hover .avatar-cam,
.avatar-edit:focus-visible .avatar-cam { opacity: 1; }
.avatar-cam svg { width: 22px; height: 22px; }

.profile-photo-actions { display: flex; gap: 14px; margin-top: 8px; }
.link-btn {
  border: 0;
  background: none;
  padding: 0;
  color: var(--accent);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.link-btn:hover { text-decoration: underline; }
.link-danger { color: var(--sell); }

.pref-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--hairline);
}
.pref-row:last-child { border-bottom: 0; }

/* Heading that labels a group of settings cards ("General", "Data"). The top
   margin is what separates one group from the previous card. */
.pref-group {
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 24px 2px 8px;
}
.pref-group:first-of-type { margin-top: 0; }
.pref-row .grow { flex: 1; }
.pref-row .pref-label { font-weight: 600; font-size: 14px; }
.pref-row .pref-sub { font-size: 12.5px; color: var(--ink-2); }

/* ---- Subscription / billing card ---- */
.sub-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 16px;
  position: relative;
  overflow: hidden;
}
/* A faint brand bloom behind the badge, so the card reads as the "upgrade" spot
   without shouting. Purely decorative and non-interactive. */
.sub-card::before {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(130% 150% at 0% 0%, var(--accent-wash), transparent 62%);
  pointer-events: none;
}
.sub-badge {
  position: relative;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  border-radius: 12px;
  background: linear-gradient(135deg, var(--cta), var(--accent-strong));
  color: #fff;
  box-shadow: 0 2px 10px rgba(220, 38, 38, 0.25);
}
.sub-badge svg { width: 21px; height: 21px; }
.sub-card .grow { position: relative; min-width: 0; }
.sub-title { font-weight: 700; font-size: 15px; }
.sub-card .pref-sub { font-size: 12.5px; color: var(--ink-2); margin-top: 2px; line-height: 1.45; }
.sub-cta { position: relative; flex: none; }
.sub-cta svg { width: 15px; height: 15px; }
.sub-cta[disabled] { opacity: 0.5; cursor: not-allowed; }
.sub-cta[disabled]:hover { background: var(--cta); border-color: var(--cta); }

@media (max-width: 560px) {
  .sub-card { flex-wrap: wrap; }
  .sub-cta { width: 100%; justify-content: center; margin-top: 4px; }
}

.about-note {
  margin-top: 20px;
  padding: 14px 16px;
  font-size: 12.5px;
  color: var(--ink-muted);
  line-height: 1.6;
}

/* ---- Subscription / plans page ----
   The tier cards are deliberately self-contained dark objects in both themes:
   they're a premium showcase, and the gold/diamond identities read the same on a
   light or dark page. Only the page chrome (title, sub, footnote) uses tokens. */

.sp-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 18px;
  align-items: center;
  max-width: 1000px;
  margin: 22px auto 0;
}

.sp-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 26px 24px;
  border-radius: 18px;
  border: 1px solid rgba(255, 255, 255, 0.09);
  background: linear-gradient(180deg, #17171b 0%, #101013 100%);
  color: #f4f4f5;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  transition: transform 0.18s ease, box-shadow 0.25s ease, border-color 0.25s ease;
}

/* Hover lights each card up in its own tier colour — silver (Basic), gold
   (Premium), diamond blue (Ultra). The featured card keeps its raised transform
   (overridden below) so it lifts a touch further instead of dropping back. */
.sp-silver:hover {
  border-color: rgba(212, 212, 216, 0.55);
  box-shadow:
    0 0 0 1px rgba(212, 212, 216, 0.28),
    0 18px 48px rgba(212, 212, 216, 0.22);
  transform: translateY(-6px);
}
.sp-gold:hover {
  border-color: rgba(245, 158, 11, 0.75);
  box-shadow:
    0 0 0 1px rgba(245, 158, 11, 0.4),
    0 22px 60px rgba(245, 158, 11, 0.4);
}
.sp-diamond:hover {
  border-color: rgba(56, 189, 248, 0.75);
  box-shadow:
    0 0 0 1px rgba(56, 189, 248, 0.38),
    0 22px 56px rgba(56, 189, 248, 0.38);
  transform: translateY(-6px);
}

/* Per-tier accent (R,G,B) driving the "current plan" glow, badge and button, so
   the plan you're on lights up in its own colour instead of a fixed green. */
.sp-silver  { --cur: 212, 212, 216; --cur-ink: #e4e4e7; }
.sp-gold    { --cur: 245, 158, 11;  --cur-ink: #fde3a7; }
.sp-diamond { --cur: 56, 189, 248;  --cur-ink: #bfe6fb; }

/* Tier identities — glow + border tint. */
.sp-gold {
  border-color: rgba(245, 158, 11, 0.45);
  background:
    radial-gradient(120% 80% at 50% -10%, rgba(245, 158, 11, 0.22), transparent 60%),
    linear-gradient(180deg, #1c1710 0%, #100d08 100%);
  box-shadow: 0 18px 48px rgba(180, 120, 10, 0.28);
}
.sp-diamond {
  border-color: rgba(56, 189, 248, 0.42);
  background:
    radial-gradient(120% 80% at 50% -10%, rgba(56, 189, 248, 0.20), transparent 60%),
    linear-gradient(180deg, #0e1720 0%, #0a1016 100%);
  box-shadow: 0 14px 40px rgba(14, 120, 180, 0.25);
}

/* The recommended plan sits higher and larger. */
.sp-featured {
  transform: translateY(-14px) scale(1.035);
  z-index: 2;
}
.sp-featured:hover { transform: translateY(-20px) scale(1.035); }

/* Ribbon — a pill straddling the top edge. */
.sp-ribbon {
  position: absolute;
  top: -14px;
  left: 50%;
  transform: translateX(-50%);
  padding: 6px 16px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.06em;
  white-space: nowrap;
  color: #1a1205;
  background: linear-gradient(135deg, #fbbf24, #d97706);
  box-shadow: 0 4px 14px rgba(217, 119, 6, 0.5);
}
.sp-ribbon-diamond {
  color: #04121c;
  background: linear-gradient(135deg, #7dd3fc, #0ea5e9);
  box-shadow: 0 4px 14px rgba(14, 165, 233, 0.5);
}

.sp-tier {
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: 0.12em;
  color: #a1a1aa;
  margin-bottom: 8px;
}
.sp-gold .sp-tier { color: #f59e0b; }
.sp-diamond .sp-tier { color: #38bdf8; }

.sp-name {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 21px;
  font-weight: 700;
  color: #fff;
}
.sp-current-tag {
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--cur-ink, #d1fae5);
  background: rgba(var(--cur, 16, 185, 129), 0.18);
  border: 1px solid rgba(var(--cur, 16, 185, 129), 0.5);
}

.sp-price { display: flex; align-items: baseline; gap: 7px; margin-top: 14px; }
.sp-amount { font-size: 40px; font-weight: 800; line-height: 1; color: #fff; letter-spacing: -0.02em; }
.sp-period { font-size: 14px; color: #a1a1aa; }
.sp-subnote { margin-top: 7px; font-size: 12.5px; color: #a1a1aa; }

.sp-features {
  list-style: none;
  margin: 20px 0 22px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex: 1;
}
.sp-features li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 13.5px;
  line-height: 1.4;
  color: #d4d4d8;
}
.sp-check { width: 17px; height: 17px; flex: none; margin-top: 1px; color: #a1a1aa; }
.sp-gold .sp-check { color: #f59e0b; }
.sp-diamond .sp-check { color: #38bdf8; }
.sp-silver .sp-check { color: #d4d4d8; }

/* Action buttons — one per tier, plus the current/coming-soon states. */
.sp-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  padding: 13px 18px;
  border: 0;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  text-decoration: none;
}
.sp-action svg { width: 17px; height: 17px; }
.sp-btn-silver {
  color: #f4f4f5;
  background: linear-gradient(180deg, #3f3f46, #27272a);
  border: 1px solid rgba(255, 255, 255, 0.12);
}
.sp-btn-silver:hover { background: linear-gradient(180deg, #52525b, #3f3f46); }
.sp-btn-gold {
  color: #1a1205;
  background: linear-gradient(135deg, #fbbf24, #d97706);
  box-shadow: 0 6px 18px rgba(217, 119, 6, 0.4);
}
.sp-btn-gold:hover { filter: brightness(1.06); }
.sp-btn-diamond {
  color: #04121c;
  background: linear-gradient(135deg, #7dd3fc, #0ea5e9);
  box-shadow: 0 6px 18px rgba(14, 165, 233, 0.4);
}
.sp-btn-diamond:hover { filter: brightness(1.06); }
.sp-action[disabled] { opacity: 0.55; cursor: not-allowed; box-shadow: none; }

.sp-current-btn {
  width: 100%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 13px 18px;
  border-radius: 12px;
  font-size: 14px;
  font-weight: 700;
  color: var(--cur-ink, #d1fae5);
  background: rgba(var(--cur, 16, 185, 129), 0.14);
  border: 1px solid rgba(var(--cur, 16, 185, 129), 0.45);
  cursor: default;
}
.sp-current-btn svg { width: 17px; height: 17px; }

/* Current-plan card glows in its own tier colour, wrapping the corners. */
.sp-is-current {
  border-color: rgba(var(--cur, 16, 185, 129), 0.6);
  box-shadow:
    0 0 0 1px rgba(var(--cur, 16, 185, 129), 0.4),
    0 0 30px rgba(var(--cur, 16, 185, 129), 0.3),
    0 18px 48px rgba(var(--cur, 16, 185, 129), 0.22);
}

/* Free-tier email capture (Basic card). */
.sp-free-form { display: flex; flex-direction: column; gap: 10px; }
.sp-email {
  width: 100%;
  padding: 12px 14px;
  border-radius: 11px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(0, 0, 0, 0.25);
  color: #f4f4f5;
  font-size: 13.5px;
}
.sp-email::placeholder { color: #71717a; }
.sp-email:focus { outline: none; border-color: rgba(255, 255, 255, 0.35); }

.sp-foot {
  text-align: center;
  margin: 26px auto 0;
  font-size: 12.5px;
  color: var(--ink-muted);
}
.sp-foot a { color: var(--accent); font-weight: 600; }

/* "Cancel subscription" reads as a peer of the "Manage billing" link, but it's a
   real <button> (it opens a dialog, not a URL). Muted until hovered so it never
   competes with the plan cards; warms to red on hover to signal what it does. */
.sp-cancel-link {
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  font-weight: 600;
  color: var(--ink-muted);
  cursor: pointer;
  transition: color 0.15s ease;
}
.sp-cancel-link:hover,
.sp-cancel-link:focus-visible { color: var(--sell-mark, #f87171); }
/* Manage billing and Renew are constructive, not destructive — they warm to the
   accent on hover rather than the cancel link's red. */
.sp-cancel-link[data-manage-billing]:hover,
.sp-cancel-link[data-manage-billing]:focus-visible,
.sp-cancel-link[data-renew-sub]:hover,
.sp-cancel-link[data-renew-sub]:focus-visible { color: var(--accent); }

/* The line under the footer that names when a cancelled plan's access ends. */
.sp-foot-note {
  margin-top: 8px;
  font-size: 12px;
  opacity: 0.85;
}

/* ---- Cancel-subscription confirm dialog ---- */

.sp-modal-open { overflow: hidden; }

.sp-modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(0, 0, 0, 0.62);
  backdrop-filter: blur(2px);
  animation: sp-modal-fade 0.14s ease;
}

.sp-modal {
  width: 100%;
  max-width: 440px;
  padding: 26px 26px 22px;
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: var(--surface, #16161a);
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55);
  animation: sp-modal-rise 0.16s ease;
}

.sp-modal-title {
  margin: 0 0 10px;
  font-size: 19px;
  font-weight: 700;
  color: #f4f4f5;
}

.sp-modal-body {
  margin: 0 0 22px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-muted);
}

.sp-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  flex-wrap: wrap;
}

.sp-modal-actions button {
  padding: 10px 16px;
  border-radius: 10px;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, opacity 0.15s ease;
}
.sp-modal-actions button:disabled { opacity: 0.6; cursor: default; }

.sp-modal-keep {
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: rgba(255, 255, 255, 0.04);
  color: #f4f4f5;
}
.sp-modal-keep:hover:not(:disabled) { background: rgba(255, 255, 255, 0.1); }

.sp-modal-confirm {
  border: 1px solid rgba(248, 113, 113, 0.5);
  background: rgba(248, 113, 113, 0.16);
  color: #fca5a5;
}
.sp-modal-confirm:hover:not(:disabled) {
  background: rgba(248, 113, 113, 0.26);
  border-color: rgba(248, 113, 113, 0.7);
}

@keyframes sp-modal-fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes sp-modal-rise {
  from { opacity: 0; transform: translateY(8px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .sp-modal-overlay, .sp-modal { animation: none; }
}

@media (max-width: 820px) {
  .sp-grid { grid-template-columns: 1fr; max-width: 420px; gap: 26px; }
  .sp-featured { transform: none; }
}

/* ---- What's new (release log) ---- */

.wn-list { display: flex; flex-direction: column; gap: 14px; max-width: 760px; }

.wn-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding-bottom: 12px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--hairline);
}
.wn-version { font-size: 15px; font-weight: 700; }
.wn-latest {
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--buy-mark);
  color: var(--buy-ink);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}
.wn-date { margin-left: auto; font-size: 12.5px; color: var(--ink-muted); }

.wn-items { list-style: none; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.wn-item { display: flex; align-items: baseline; gap: 10px; }
.wn-copy { font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }

/* Fixed width (not min-width) so the copy column stays aligned across tags. */
.wn-tag {
  flex: none;
  width: 78px;
  padding: 2px 6px;
  border-radius: 6px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-align: center;
}
.wn-tag-new { background: var(--buy-wash); color: var(--buy); }
.wn-tag-improved { background: var(--accent-wash); color: var(--accent); }
.wn-tag-fixed { background: var(--muted-wash); color: var(--muted-tone); }

@media (max-width: 560px) {
  .wn-head { flex-wrap: wrap; }
  .wn-date { margin-left: 0; width: 100%; }
  .wn-item { flex-direction: column; gap: 4px; }
}

/* ---- Support ---- */

.sp-layout { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 16px; align-items: start; }
.sp-main, .sp-side { display: flex; flex-direction: column; gap: 16px; }

.sp-section-title { font-size: 15px; font-weight: 700; margin-bottom: 4px; }
.sp-section-sub { font-size: 12.5px; color: var(--ink-muted); line-height: 1.6; margin-bottom: 14px; }

/* FAQ — native <details>, so it works without JS. */
.sp-faq { border-top: 1px solid var(--hairline); }
.sp-faq:first-of-type { border-top: 0; }
.sp-q {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 0;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}
.sp-q::-webkit-details-marker { display: none; }
.sp-q:hover { color: var(--accent); }
.sp-q span { flex: 1; }
.sp-chevron { flex: none; color: var(--ink-muted); transition: transform 0.18s; }
.sp-faq[open] .sp-chevron { transform: rotate(180deg); }
.sp-a {
  padding: 0 0 16px;
  max-width: 68ch;
  font-size: 13.5px;
  line-height: 1.65;
  color: var(--ink-2);
}

.sp-codes { width: 100%; border-collapse: collapse; }
.sp-codes td { padding: 9px 0; border-top: 1px solid var(--hairline); vertical-align: baseline; }
.sp-codes tr:first-child td { border-top: 0; }
.sp-code {
  display: inline-block;
  min-width: 62px;
  margin-right: 14px;
  padding: 2px 8px;
  border-radius: 6px;
  background: var(--muted-wash);
  color: var(--ink);
  font-size: 11.5px;
  font-weight: 700;
  text-align: center;
}
.sp-code-meaning { font-size: 13.5px; line-height: 1.6; color: var(--ink-2); }

.sp-mail { width: 100%; justify-content: center; }
.sp-meta { margin-top: 10px; text-align: center; font-size: 12px; color: var(--ink-muted); }

.sp-links { list-style: none; padding: 0; display: flex; flex-direction: column; }
.sp-links li { border-top: 1px solid var(--hairline); }
.sp-links li:first-child { border-top: 0; }
.sp-links a { display: block; padding: 11px 0; font-size: 13.5px; color: var(--accent); }
.sp-links a:hover { text-decoration: underline; }

@media (max-width: 900px) {
  .sp-layout { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- Legal document (#/privacy) ----------
   A reading column, not a dashboard: one measure, generous leading, sections
   parted by hairlines. Nothing here is a card, because a legal notice is one
   continuous document and boxing its parts implies they can be read apart. */

.legal { max-width: 860px; }
.legal h1 { letter-spacing: -0.02em; }

.lg-intro { margin-top: 12px; max-width: 72ch; font-size: 14.5px; line-height: 1.7; color: var(--ink-2); }
.lg-effective { margin-top: 14px; font-size: 12.5px; color: var(--ink-muted); }

.lg-section {
  margin-top: 40px;
  padding-top: 32px;
  border-top: 1px solid var(--hairline);
  scroll-margin-top: 88px; /* clears the sticky appbar when linked by fragment */
}
.lg-section h2 { font-size: 19px; font-weight: 700; letter-spacing: -0.01em; }
.lg-section > p { margin-top: 12px; max-width: 74ch; font-size: 13.5px; line-height: 1.75; color: var(--ink-2); }
.lg-section a { color: var(--accent); }
.lg-section a:hover { text-decoration: underline; }
.lg-section code {
  padding: 1px 5px;
  border-radius: 4px;
  background: var(--surface-2);
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 0.92em;
}
.lg-note { color: var(--ink-muted) !important; font-size: 12.5px !important; }

/* An action rendered inline in prose: a button, because it opens the consent
   dialog rather than navigating, but it has to read as a link. */
.lg-linkbtn, .sf-linkbtn {
  border: 0;
  padding: 0;
  background: none;
  font: inherit;
  color: var(--accent);
  cursor: pointer;
  text-decoration: underline;
}
.lg-linkbtn:hover, .sf-linkbtn:hover { color: var(--accent-strong); }

/* §1 controller — a definition grid, so an unfilled field is conspicuous. */
.lg-controller {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 18px 32px;
  margin-top: 18px;
  padding: 20px 22px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--surface);
}
.lg-field dt {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.lg-field dd { margin-top: 5px; font-size: 13.5px; line-height: 1.5; color: var(--ink); }
.lg-field dd.lg-todo { color: var(--highlight); font-weight: 600; }

.lg-warn {
  margin-top: 16px;
  padding: 12px 16px;
  border: 1px solid var(--sell-mark);
  border-radius: var(--radius-sm);
  background: var(--sell-wash);
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--ink-2);
}
.lg-warn strong { color: var(--sell); }

/* Tables scroll inside themselves; the page never scrolls sideways. */
.lg-table-wrap {
  margin-top: 18px;
  overflow-x: auto;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--surface);
}
.lg-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.lg-table th {
  padding: 13px 16px;
  text-align: left;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  border-bottom: 1px solid var(--hairline);
  white-space: nowrap;
}
.lg-table td {
  padding: 14px 16px;
  vertical-align: top;
  line-height: 1.55;
  color: var(--ink-2);
  border-top: 1px solid var(--hairline);
}
.lg-table tbody tr:first-child td { border-top: 0; }
.lg-table .lg-key { color: var(--ink); font-weight: 600; min-width: 150px; }
.lg-table code { font-size: 11.5px; }

.lg-list { margin-top: 14px; padding-left: 20px; max-width: 74ch; }
.lg-list li { margin-top: 9px; font-size: 13.5px; line-height: 1.7; color: var(--ink-2); }
.lg-list li::marker { color: var(--accent); }
.lg-list strong { color: var(--ink); }

.lg-rights { margin-top: 18px; max-width: 76ch; }
.lg-rights dt {
  margin-top: 18px;
  padding-top: 16px;
  border-top: 1px solid var(--hairline);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink);
}
.lg-rights dt:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.lg-rights dd { margin-top: 5px; font-size: 13px; line-height: 1.65; color: var(--ink-2); }

@media (max-width: 640px) {
  .lg-controller { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- Site footer ----------
   Closes the long-form pages (Settings, What's new, Support). A hairline rather
   than a filled bar: the page's own ambience shows through, so the footer reads
   as the end of the content instead of a second, competing surface. */

.site-footer {
  margin-top: 40px;
  padding-top: 24px;
  border-top: 1px solid var(--hairline);
}

.sf-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px 32px;
  flex-wrap: wrap;
}

.sf-brand { display: inline-flex; align-items: center; gap: 10px; color: var(--ink); }

/* The mark gets a brand tile here, unlike the header's bare glyph — at the foot
   of the page it is the only thing carrying the brand colour. */
.sf-mark {
  flex-shrink: 0;
  padding: 5px;
  border-radius: var(--radius-sm);
  background: var(--cta);
  color: #fff;
  box-sizing: content-box;
}

.sf-name { font-size: 17px; font-weight: 700; letter-spacing: -0.01em; }
.sf-name em { font-style: normal; color: var(--accent); }

.sf-links { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 28px; }
.sf-links a, .sf-links .sf-linkbtn { font-size: 13.5px; color: var(--ink-2); text-decoration: none; }
.sf-links a:hover, .sf-links .sf-linkbtn:hover { color: var(--ink); text-decoration: underline; }

.sf-rights { margin-top: 22px; font-size: 13px; color: var(--ink-2); }

.sf-disclaimer {
  margin-top: 12px;
  max-width: 78ch;
  font-size: 12.5px;
  line-height: 1.6;
  color: var(--ink-muted);
}

@media (max-width: 560px) {
  .sf-top { flex-direction: column; align-items: flex-start; }
}

/* ---------- Upsell paywall (#/, #/database, #/graph for free users) ---------- */

.upsell {
  max-width: 560px;
  margin: 24px auto 0;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 40px 32px;
}
.upsell-lock {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  margin-bottom: 18px;
  border-radius: 16px;
  color: var(--accent);
  background: var(--accent-wash);
}
.upsell-lock svg { width: 28px; height: 28px; }
.upsell-title { font-size: 24px; margin: 0 0 8px; }
.upsell-sub {
  max-width: 42ch;
  margin: 0 0 22px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-2);
}
.upsell-perks {
  list-style: none;
  padding: 0;
  margin: 0 0 26px;
  display: flex;
  flex-direction: column;
  gap: 11px;
  text-align: left;
}
.upsell-perks li { display: flex; align-items: center; gap: 10px; font-size: 14px; color: var(--ink); }
.upsell-perks .sp-check { flex: none; width: 18px; height: 18px; color: var(--buy); }
.upsell-cta { display: inline-flex; align-items: center; gap: 8px; padding: 11px 22px; }
.upsell-cta svg { width: 18px; height: 18px; }
.upsell-foot { margin: 14px 0 0; font-size: 12.5px; color: var(--ink-muted); }

/* ---------- Developer plan switcher (localhost only; never on the public site) ----------
   Mounted by js/plan.js only on a dev host, so this UI never reaches real users. */

.dev-plan-switch {
  position: fixed;
  bottom: 14px;
  left: 14px;
  z-index: 9999;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 5px 7px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(15, 15, 18, 0.92);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
  font-size: 11px;
  backdrop-filter: blur(6px);
}
.dev-plan-label { color: #a1a1aa; font-weight: 800; letter-spacing: 0.08em; padding: 0 4px; }
.dev-plan-switch button {
  padding: 4px 9px;
  border-radius: 7px;
  border: 0;
  background: rgba(255, 255, 255, 0.08);
  color: #e4e4e7;
  font-size: 11px;
  font-weight: 600;
  text-transform: capitalize;
  cursor: pointer;
}
.dev-plan-switch button:hover { background: rgba(255, 255, 255, 0.16); }
.dev-plan-switch button.is-active { background: var(--accent); color: #fff; }
