@use "../../base/styles/variables" as *;
@use "../../base/styles/mixins" as *;

/* ===========================================================================
   Markets dashboard (Phase C): a market-hours banner, the normalized
   %-vs-S&P-500 day graph, the headline market reads, and the editable
   session watchlist. The sparkline card styles at the bottom are shared by the
   watchlist cards and the base stream client's live repaint.
   ======================================================================== */

.dash {
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}

/* ---------- market-hours banner ---------- */
.dash-banner {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--surface);
  font-size: var(--fs-sm);
}

.dash-banner__dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--ink-faint);
  flex: none;
}
.dash-banner[data-session="regular"] .dash-banner__dot {
  background: var(--up);
  box-shadow: 0 0 0 3px var(--up-soft);
}
.dash-banner[data-session="pre"] .dash-banner__dot,
.dash-banner[data-session="post"] .dash-banner__dot {
  background: var(--warn);
  box-shadow: 0 0 0 3px var(--warn-soft);
}

.dash-banner__label {
  @include mono;
  font-weight: 700;
}
.dash-banner__sub {
  color: var(--ink-faint);
  font-size: var(--fs-xs);
}

/* ---------- hero day graph ---------- */
.hero-graph {
  @include card;
  padding: var(--sp-3) var(--sp-3) var(--sp-2);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.hero-graph__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--sp-1) var(--sp-3);
}

.hero-graph__title {
  @include serif;
  font-size: var(--fs-lg);
  font-weight: 600;
}

.hero-graph__note {
  font-size: var(--fs-xs);
  color: var(--ink-faint);
}

/* The overview + watchlist grids: one mini chart per instrument. One column on
   a phone, two on a tablet, three on desktop. Explicit columns (rather than
   auto-fill) so the overview (inside the padded hero card) and the watchlist
   (full width) both land on the same 3-up on desktop. */
.overview-grid {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  gap: 11px;
  min-height: 120px;
}
@media (min-width: $bp-md) {
  .overview-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (min-width: $bp-lg) {
  .overview-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* ---------- loading skeletons ---------- */
/* Before /api/dashboard answers, the overview grid shows one skeleton card per
   slot. display: contents makes the wrapper vanish so each skeleton is a real
   grid item — the grid lays out exactly as it will with live cards, no jump. */
.ov-skels {
  display: contents;
}
/* Re-assert [hidden] — display:contents otherwise beats the UA rule, so the
   skeletons would linger behind the drawn charts (cf. the symbol page's
   .ind-btn[hidden] fix). */
.ov-skels[hidden] {
  display: none;
}

/* One shimmering placeholder block (a name line, a figure line, the chart
   area). The shimmer is a slow ink wash, not a flashy gradient sweep —
   restrained enough for the ledger aesthetic. */
.ov-skel {
  border-radius: var(--radius-sm);
  background: rgba(33, 31, 26, 0.07);
  animation: ov-skel-pulse 1.6s ease-in-out infinite;
}
.ov-skel--name {
  width: 7rem;
  height: 1rem;
}
.ov-skel--num {
  width: 4.5rem;
  height: 1rem;
}
.ov-skel--chart {
  animation-delay: 0.2s;
}
@keyframes ov-skel-pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.45;
  }
}
@media (prefers-reduced-motion: reduce) {
  .ov-skel {
    animation: none;
  }
}

/* A watchlist card's chart mount is server-rendered empty and only fills once
   hero.js draws into it; until then show the same quiet placeholder wash so
   the card doesn't read as broken. :empty stops matching the moment the chart
   library mounts. */
.ov-card--watch .ov-card__chart:empty {
  border-radius: var(--radius-sm);
  background: rgba(33, 31, 26, 0.07);
  animation: ov-skel-pulse 1.6s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .ov-card--watch .ov-card__chart:empty {
    animation: none;
  }
}

/* ---------- one instrument's chart card (overview + watchlist) ---------- */
.ov-card {
  @include card;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 13px 14px 10px;
  transition: border-color 0.14s, transform 0.14s, box-shadow 0.14s;
}

/* The card's inner stack. Overview cards stack directly; watchlist cards wrap
   the same stack in a navigating link. */
.ov-card__link {
  display: flex;
  flex-direction: column;
  gap: 10px;
  color: inherit;
}

.ov-card__name {
  @include serif;
  font-size: var(--fs-md);
  font-weight: 600;
  line-height: 1.15;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ov-card__sub {
  font-size: var(--fs-2xs);
  color: var(--ink-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Watchlist card name: ticker bold with the company name trailing small on one
   line, so the card head matches the overview cards' single-line name. */
.ov-card__name--watch {
  display: flex;
  align-items: baseline;
  gap: 6px;
  min-width: 0;
  color: var(--ink);
}
.ov-card__name--watch .ov-card__sub {
  font-weight: 400;
  flex: 0 1 auto;
}

/* Value + % on one baseline-aligned row — the at-a-glance read. */
.ov-card__nums {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
}
.ov-card__value {
  font-size: var(--fs-lg);
  font-weight: 700;
  line-height: 1;
}
/* The % move as a tinted pill — the card's at-a-glance good/bad signal. */
.ov-card__chg {
  font-size: var(--fs-2xs);
  font-weight: 700;
  line-height: 1;
  padding: 3px 7px;
  border-radius: 999px;
  background: var(--ink-wash, rgba(33, 31, 26, 0.06));
  color: var(--ink-dim);
}
.ov-card__chg.is-up {
  color: var(--up);
  background: var(--up-soft);
}
.ov-card__chg.is-down {
  color: var(--down);
  background: var(--down-soft);
}

/* A real value move flashes the card briefly in the move's direction. */
.ov-card.ov-flash-up {
  animation: ov-flash-up 0.6s ease-out;
}
.ov-card.ov-flash-down {
  animation: ov-flash-down 0.6s ease-out;
}
@keyframes ov-flash-up {
  0% {
    box-shadow: inset 0 0 0 2px var(--up);
  }
  100% {
    box-shadow: inset 0 0 0 2px transparent;
  }
}
@keyframes ov-flash-down {
  0% {
    box-shadow: inset 0 0 0 2px var(--down);
  }
  100% {
    box-shadow: inset 0 0 0 2px transparent;
  }
}
@media (prefers-reduced-motion: reduce) {
  .ov-card.ov-flash-up,
  .ov-card.ov-flash-down {
    animation: none;
  }
}

/* The sparkline mount: a short, full-width SVG of the day's path. */
.ov-card__chart {
  position: relative;
  width: 100%;
  height: 42px;
}
.spark {
  display: block;
  width: 100%;
  height: 100%;
}

/* ---------- watchlist card extras (link + remove) ---------- */
.ov-card--watch:hover {
  border-color: var(--rule-strong);
  transform: translateY(-2px);
  box-shadow: var(--lift-hover);
}
.ov-card__remove {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 2;
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.05rem;
  line-height: 1;
  color: var(--ink-faint);
  background: var(--surface);
  border: 1px solid transparent;
  border-radius: 50%;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s, color 0.12s, border-color 0.12s;
}
.ov-card--watch:hover .ov-card__remove,
.ov-card__remove:focus-visible {
  opacity: 1;
}
.ov-card__remove:hover {
  color: var(--down);
  border-color: var(--down);
}
.ov-card__remove:disabled {
  cursor: default;
  opacity: 0.4;
}


/* ---------- sector heatmap ("what's moving") ---------- */
.sectors {
  margin-top: var(--sp-4);
}
.sectors__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  margin-bottom: var(--sp-2);
}
.sectors__note {
  font-size: var(--fs-2xs);
  color: var(--ink-faint);
}
.sectors__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 7px;
  min-height: 2.5em;
}
@media (min-width: $bp-sm) {
  .sectors__grid {
    /* 11 sector tiles flow into as many columns as fit, so the strip stays one
       or two tidy rows on desktop without hard-coding a count. */
    grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
  }
}
.sector-tile {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 10px;
  border-radius: var(--radius-sm, 6px);
  border: 1px solid var(--rule);
  text-decoration: none;
  color: var(--ink);
  transition:
    transform 0.12s ease,
    box-shadow 0.12s ease;
}
.sector-tile:hover {
  transform: translateY(-1px);
  box-shadow: var(--lift-hover);
  border-color: var(--rule-strong);
}
.sector-tile__name {
  font-size: var(--fs-2xs);
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sector-tile__pct {
  font-size: var(--fs-sm);
  font-weight: 700;
  line-height: 1;
}

/* ---------- headline market reads ---------- */
.reads-head {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: var(--sp-2);
  margin-bottom: calc(-1 * var(--sp-3) + 4px);
}
.reads-head__asof {
  font-size: var(--fs-xs);
  color: var(--ink-faint);
}
.reads-head__refresh {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--fs-xs);
  color: var(--ink-dim);
}
.reads-head__spinner {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 1.5px solid var(--rule-strong);
  border-top-color: var(--ink-dim);
  animation: reads-spin 0.7s linear infinite;
}
@keyframes reads-spin {
  to {
    transform: rotate(360deg);
  }
}
@media (prefers-reduced-motion: reduce) {
  .reads-head__spinner {
    animation: none;
  }
}

.reads {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 11px;
}
@media (min-width: $bp-sm) {
  .reads {
    // Five reads: the crash-response row (S&P-from-high, VIX, credit) leads, then
    // market volume + the S&P 50/200 trend.
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.read {
  @include card;
  padding: var(--sp-2) var(--sp-3);
  display: flex;
  flex-direction: column;
  gap: 3px;
}
/* The crash-response lead read carries a hairline accent so the at-a-glance
   "how far from the high" number reads as the headline of the pulse row. */
.read--lead {
  border-left: 2px solid var(--rule-strong);
}

.read__label {
  @include eyebrow;
}

.read__value {
  font-size: var(--fs-lg);
  font-weight: 700;
}
.read__value--text {
  font-size: var(--fs-sm);
  font-weight: 600;
  line-height: 1.25;
}

.read__sub {
  font-size: var(--fs-xs);
  color: var(--ink-dim);
}

/* tone classes for the VIX / trend reads (semantic, sparing) */
.read__tone--calm,
.read__tone--up {
  color: var(--up);
}
.read__tone--steady {
  color: var(--ink-dim);
}
.read__tone--elevated,
.read__tone--warn {
  color: var(--warn);
}
.read__tone--stressed,
.read__tone--down {
  color: var(--down);
}

/* ---------- watchlist ---------- */
.watch__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--sp-2) var(--sp-3);
}

.watch-add {
  display: flex;
  gap: var(--sp-1);
}

.watch-add__input {
  width: 14rem;
  max-width: 48vw;
  padding: 0.4rem 0.6rem;
  font: inherit;
  font-size: var(--fs-sm);
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--rule-strong);
  border-radius: var(--radius-sm);
}
.watch-add__input:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 1px;
}

.watch-add__btn {
  @include tap;
  padding: 0.4rem 0.9rem;
  font: 500 var(--fs-sm) / 1 inherit;
  color: var(--surface);
  background: var(--ink);
  border: 1px solid var(--ink);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.watch-add__btn:disabled {
  opacity: 0.6;
  cursor: default;
}

.watch-msg {
  margin-top: var(--sp-2);
  font-size: var(--fs-sm);
  color: var(--ink-dim);
}
.watch-msg.is-error {
  color: var(--down);
}

.watch-empty {
  @include card;
  padding: var(--sp-4);
  text-align: center;
  color: var(--ink-dim);
  font-size: var(--fs-sm);
}

/* The watchlist reuses the overview grid + chart cards (`.overview-grid` +
   `.ov-card--watch`); it only needs the top margin under its header. */
.watch-grid {
  margin-top: var(--sp-3);
}

/* ---------- market movers ---------- */
.movers {
  margin-top: var(--sp-5);
}
.movers__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
  margin-bottom: var(--sp-2);
}
.movers__asof {
  font-size: var(--fs-2xs);
  color: var(--ink-faint);
}
/* "S&P 500" scope chip beside the Market movers title. */
.movers__scope {
  margin-left: 6px;
  font-size: var(--fs-2xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  vertical-align: middle;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--ink-wash, rgba(33, 31, 26, 0.06));
  color: var(--ink-dim);
}
.movers__cols {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-3);
}
@media (min-width: $bp-sm) {
  .movers__cols {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}
.movers__col {
  @include card;
  padding: var(--sp-2) var(--sp-3) var(--sp-1);
}
.movers__title {
  @include eyebrow;
  margin-bottom: 4px;
}
.movers__title--up {
  color: var(--up);
}
.movers__title--down {
  color: var(--down);
}
.movers__empty {
  font-size: var(--fs-xs);
  color: var(--ink-faint);
  padding: var(--sp-2) 0;
}
.mv-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  padding: 7px 0;
  border-top: 1px solid var(--rule);
  text-decoration: none;
  color: var(--ink);
}
.movers__list .mv-row:first-child {
  border-top: none;
}
.mv-row:hover {
  color: var(--ink);
  background: var(--ink-wash, rgba(33, 31, 26, 0.04));
  margin: 0 calc(-1 * var(--sp-2));
  padding-left: var(--sp-2);
  padding-right: var(--sp-2);
}
.mv-row__id {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.mv-row__sym {
  font-weight: 700;
  font-size: var(--fs-sm);
  line-height: 1.1;
}
.mv-row__name {
  font-size: var(--fs-2xs);
  color: var(--ink-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 13ch;
}
.mv-row__nums {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  flex: none;
}
.mv-row__pct {
  font-weight: 700;
  font-size: var(--fs-sm);
  line-height: 1;
}
.mv-row__pct.is-up {
  color: var(--up);
}
.mv-row__pct.is-down {
  color: var(--down);
}
.mv-row__sub {
  font-size: var(--fs-2xs);
  color: var(--ink-faint);
}
