/* =========================================================================
   AInnect dashboard — PANE LAYER
   The horizontal deck and the four sections inside it.
   Tokens, chrome and the orb card live in styles.css. No overlap.
   ========================================================================= */

/* ---------- deck: full-screen horizontal section slider ---------- */
.deck {
  position: relative; z-index: 10;
  display: flex;
  width: 100%; height: 100dvh;
  /* clip, not hidden: hidden makes WebKit treat this as a two-axis scroller
     and then refuse to paint or scroll the panes inside it. The second
     declaration keeps hidden on engines that don't know clip. */
  overflow-x: auto; overflow-y: hidden;
  overflow-y: clip;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
}
.deck::-webkit-scrollbar { display: none; }

.pane {
  position: relative;
  /* 100% of the deck, not 100vw. On iPad 100vw is wider than the visual
     viewport, scroll-snap pins each pane to that wider width, and the part
     that doesn't fit is clipped — swiping never brings it on screen. */
  flex: 0 0 100%; width: 100%; min-width: 100%; height: 100%;
  scroll-snap-align: start; scroll-snap-stop: always;
  display: flex; flex-direction: column;
  overflow: hidden;
  overflow: clip;
  color: var(--text-1);
}

/* Data panes sit over the same churning video as the hero. A FLAT scrim here
   read as a tile pasted over the vignette gradient (the "black box" in dark,
   flat white panel in light) — the orb has to stay an open gradient space.
   This wash is built from --wash like .bg-vignette, so it recolours with the
   theme: nearly clear over the orb's centre, firming up toward the pane edges
   and the top/bottom copy bands where text needs it. */
.pane--data::before {
  content: ''; position: absolute; inset: 0; z-index: 0;
  background:
    linear-gradient(to bottom,
      rgba(var(--wash), 0.60) 0%,
      rgba(var(--wash), 0) 18%,
      rgba(var(--wash), 0) 82%,
      rgba(var(--wash), 0.60) 100%),
    radial-gradient(ellipse 58% 50% at 50% 46%,
      rgba(var(--wash), 0.18) 0%,
      rgba(var(--wash), 0.34) 52%,
      rgba(var(--wash), 0.56) 78%,
      rgba(var(--wash), 0.68) 100%);
  pointer-events: none;
}
.pane--data > * { position: relative; z-index: 1; }

/* ---------- pane 1: hero ---------- */
.split {
  flex: 1; display: flex; flex-direction: column; gap: var(--s-6);
  padding: calc(var(--s-4) + 46px) var(--s-5) 2.5rem; min-height: 0;
}
@media (min-width: 768px) {
  .split {
    flex-direction: row; align-items: center; justify-content: space-between;
    gap: var(--s-8); padding: 0 var(--s-8);
  }
}
/* The orb used to occupy the middle. With it gone, pull the two columns
   toward each other and let them grow, instead of pinning them to the edges. */
@media (min-width: 1024px) {
  .split {
    justify-content: center;
    gap: clamp(3rem, 5vw, 6rem);
    width: min(1360px, 100%);
    margin-inline: auto;
    padding-inline: clamp(2.5rem, 4vw, 4rem);
  }
}

/* ---------- hero ticker ----------
   A continuously scrolling strip of today's live numbers. The track holds two
   identical copies of the item list and translates exactly -50%, so the loop
   is seamless rather than snapping back at the end. */
.tickerbar {
  position: relative; z-index: 2; flex: none;
  display: flex; align-items: center;
  height: 46px; margin: 0 var(--s-8) 46px;
  border-radius: var(--r-pill);
  background: transparent;
  --frost: var(--frost-strong);   /* was a hardcoded white, which greyed out in dark */
  border: 1px solid var(--glass-hi);
  box-shadow: var(--sh-tile);
  overflow: hidden;
}
.tickerbar__label {
  flex: none; align-self: stretch;
  display: flex; align-items: center; gap: 7px;
  padding: 0 var(--s-4);
  border-right: 1px solid var(--line);
  font-size: var(--fs-micro); text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--text-3);
}
.tickerbar__label::before {
  content: ''; width: 6px; height: 6px; border-radius: var(--r-pill);
  background: var(--pos);
  animation: tick-pulse 2.4s ease-in-out infinite;
}
@keyframes tick-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }

.tickerbar__viewport { flex: 1; min-width: 0; overflow: hidden; }
.ticker__track {
  display: flex; width: max-content;
  animation: ticker-scroll var(--ticker-duration, 70s) linear infinite;
}
/* pause when someone wants to read or tab through it — and whenever the hero
   is not the pane on screen, so it stops compositing entirely */
.tickerbar:hover .ticker__track,
.tickerbar:focus-within .ticker__track,
body:not(.at-hero) .ticker__track { animation-play-state: paused; }
body:not(.at-hero) .tickerbar__label::before { animation-play-state: paused; }
body:not(.at-hero) .swipe-hint { animation-play-state: paused; }

@keyframes ticker-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}

.tick {
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: 0 var(--s-5); white-space: nowrap;
  border-right: 1px solid var(--line);
  font-size: var(--fs-xs); color: var(--text-2); text-decoration: none;
}
a.tick:hover { color: var(--text-1); }
a.tick:hover .tick__sym { text-decoration: underline; }
.tick__sym {
  font-weight: 700; letter-spacing: 0.05em;
  text-transform: uppercase; color: var(--text-1);
}
.tick__val { font-variant-numeric: tabular-nums; font-weight: 700; }
.tick__val.up   { color: var(--pos); }
.tick__val.down { color: var(--neg); }
.tick__val.flat { color: var(--text-3); }
.tick__note { color: var(--text-3); }
.tick__price { font-variant-numeric: tabular-nums; color: var(--text-1); font-weight: 600; }
/* section markers keep price, tone, rankings and stories from blurring together */
.tick--marker {
  font-size: var(--fs-micro); text-transform: uppercase; letter-spacing: 0.11em;
  color: var(--text-3); background: var(--ink-05);
}

@media (prefers-reduced-motion: reduce) {
  .ticker__track { animation: none; }
  .tickerbar__label::before { animation: none; }
  .tickerbar__viewport { overflow-x: auto; }
}

@media (max-width: 767px) {
  /* the extra bottom margin is the lane the swipe hint and the section dots
     share below the ticker; at 42px the hint sat on top of the dots */
  .tickerbar { height: 42px; margin: 0 var(--s-5) 64px; }
  .tickerbar__label { padding: 0 var(--s-3); }
  .tick { padding: 0 var(--s-4); }
}

/* portrait stacks the hero into one viewport — see the matching hero
   compaction rules in styles.css */
@media (max-width: 767px) {
  /* the shorthand used to reset the base rule's nav clearance, so the kicker
     and the H1 rendered underneath the fixed nav.
     Do NOT centre this column: .lede::before is a near-opaque wash that bleeds
     ~12rem past the copy, and centring drags it straight over the orb — the
     hero went flat grey in dark mode. Top-aligned keeps the wash above it. */
  .split {
    gap: var(--s-4);
    padding: calc(var(--s-3) + 46px) var(--s-5) var(--s-6);
  }
}

.swipe-hint {
  position: absolute; right: 1.4rem; bottom: 1.2rem;
  display: flex; align-items: center; gap: 6px;
  font-size: var(--fs-kick); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-2);
  animation: nudge 2.4s ease-in-out infinite;
}
@keyframes nudge {
  0%, 100% { transform: translateX(0); opacity: 0.5; }
  50%      { transform: translateX(8px); opacity: 0.8; }
}
/* Portrait has no right gutter to spare — the hint ran back across the centred
   dots. Centre it in its own lane above them and nudge from there. */
@media (max-width: 767px) {
  .swipe-hint { right: auto; left: 50%; bottom: 2.45rem; margin-left: -4rem; }
}

/* ---------- shared pane header ----------
   One header component for all three data panes: index, title, subtitle on the
   left; live meta on the right; ghosted numeral behind. Previously the news
   pane used a different class and a different axis. */
.pane__head {
  position: relative;
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--s-5);
  /* top padding clears the fixed nav — must come after the shorthand, which
     would otherwise reset it back to --s-6 */
  padding: var(--s-6) var(--s-7) var(--s-4);
  padding-top: calc(var(--s-6) + 58px);
  border-bottom: 1px solid var(--line);
}
.pane__headText { display: flex; flex-direction: column; gap: 0.3rem; min-width: 0; }
.pane__num2 {
  font-size: var(--fs-kick); letter-spacing: 0.14em;
  color: var(--text-3); font-variant-numeric: tabular-nums;
}
.pane__title { font-size: var(--fs-title); font-weight: 350; letter-spacing: -0.02em; color: var(--text-1); }
.pane__sub { color: var(--text-2); font-size: var(--fs-sm); }
.pane__meta {
  flex: none; text-align: right;
  font-size: var(--fs-xs); color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
/* The oversized ghost numeral collided with the live meta and, at 5% ink over
   a moving video, read as a smudge rather than a numeral. The 01/02/03 kicker
   already indexes the section, so the decoration earns nothing. */
/* Portrait: the meta held its intrinsic width against a flexing headText, so
   a long subtitle was squeezed into a ~9ch column running half the screen.
   Stack instead — title block full width, meta as its own trailing line. */
@media (max-width: 767px) {
  .pane__head {
    flex-direction: column; align-items: flex-start;
    gap: var(--s-2);
    padding: calc(var(--s-5) + 46px) var(--s-5) var(--s-3);
  }
  .pane__title { font-size: 1.25rem; }
  .pane__headText { width: 100%; gap: 0.2rem; }
  /* two lines of standfirst is the brief; the rest is detail the pane repeats */
  .pane__sub {
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    overflow: hidden;
  }
  .pane__meta { text-align: left; }
}

/* ---------- shared pane footer nav ---------- */
.pane__nav {
  display: flex; align-items: center; gap: 10px;
  padding: 0 var(--s-7) var(--s-7);
}
.pane__nav .spacer { flex: 1; }
.dig-btn {
  width: 40px; height: 38px; border-radius: var(--r-pill);
  border: 1px solid var(--line-strong);
  background: var(--glass-2); color: var(--text-1); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background 200ms, transform 200ms;
  pointer-events: auto;
}
.dig-btn:hover { background: var(--glass-3); }
.dig-btn:active { transform: scale(0.94); }
@media (max-width: 639px) { .pane__nav { padding: 0 var(--s-5) 2.5rem; } }

/* ---------- pane 2: news ----------
   Was a 4-column horizontal rail of stacked tiles that filled ~45% of the
   pane height and needed arrow paging. All eight stories fit on one screen,
   so this is now a grid that fills the pane — no paging, no ragged columns. */
.news-grid {
  flex: 1; min-height: 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  /* minmax so a short iPad viewport scrolls the grid instead of crushing
     every card into the leftover height, where the copy is clipped and
     there is nothing left to scroll. Tall screens still stretch to fill. */
  grid-auto-rows: minmax(11.5rem, 1fr);
  gap: var(--s-4);
  padding: var(--s-4) var(--s-7) var(--s-5);
  overflow-y: auto;
  overscroll-behavior-y: contain;
  scrollbar-width: none;
}
.news-grid::-webkit-scrollbar { display: none; }

.news-mini {
  display: flex; flex-direction: column; gap: var(--s-2);
  min-height: 0;
  padding: var(--s-5);
  border-radius: var(--r-md);
  text-decoration: none; color: var(--text-1);
  background: var(--glass-2);
  border: 1px solid var(--glass-hi);
  box-shadow: var(--sh-inset), var(--sh-tile);
  transition: transform 300ms var(--ease), background 250ms, box-shadow 250ms;
}
.news-mini:hover {
  background: var(--glass-3);
  transform: translateY(-3px);
  box-shadow: 0 12px 28px -12px rgba(20, 30, 40, 0.32);
}
.nm-row { display: flex; align-items: center; gap: 7px; flex: none; }
.dc-fav {
  display: inline-flex; align-items: center; justify-content: center;
  flex: none; width: 22px; height: 18px; border-radius: 5px;
  font-size: 0.8rem; font-weight: 700; color: #fff; letter-spacing: 0.02em;
}
.dc-src {
  font-size: 0.9rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--text-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.nm-date {
  margin-left: auto; flex: none;
  font-size: 0.9rem; color: var(--text-3);
  font-variant-numeric: tabular-nums;
}
/* plain block so the -webkit-box clamp inside survives (a flex item would be
   blockified to flow-root and the clamp would be dropped) */
.nm-body { flex: 1 1 auto; min-height: 0; overflow: hidden; }
.nm-title {
  margin-top: var(--s-1);
  font-size: 1.24rem; font-weight: 600; line-height: 1.32;
  letter-spacing: -0.012em; color: var(--text-1);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.news-mini:hover .nm-title { color: var(--link); }
.dc-sum--none { font-style: italic; color: var(--text-3); }
.dc-sum {
  margin-top: var(--s-2);
  font-size: 1.04rem; line-height: 1.55; color: var(--text-2);
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
/* nm-body's flex:1 holds the cue on the tile floor, so cards with no summary
   still align their read-cue with the rest of the row */
.nm-cue {
  flex: none; margin-top: var(--s-2);
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-micro); color: var(--text-3);
  opacity: 0; transform: translateX(-4px);
  transition: opacity 250ms, transform 250ms;
}
.news-mini:hover .nm-cue { opacity: 1; transform: translateX(0); }

@media (max-width: 1199px) { .news-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 899px)  { .news-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 639px)  {
  .news-grid {
    grid-template-columns: 1fr; grid-auto-rows: min-content;
    padding: var(--s-3) var(--s-5) var(--s-4);
  }
  .nm-cue { display: none; }
  .nm-title { -webkit-line-clamp: 3; font-size: 1.1rem; }
  .dc-sum { -webkit-line-clamp: 3; }
}

/* ---------- glass panel (mood + leaderboards) ---------- */
.glass-pane {
  margin: 0 var(--s-7) var(--s-4);
  flex: 1; min-height: 0;
  border-radius: var(--r-xl);
  /* Deliberately NOT a [data-glass] surface. Refraction here meant a
     full-viewport filtered draw behind a wall of body copy every frame — the
     most expensive surface on the page and the least legible. */
  background: var(--glass-1);
  border: 1px solid var(--glass-hi);
  box-shadow: var(--sh-inset), var(--sh-pane);
  overflow: hidden;
  display: flex; flex-direction: column;
}
@media (max-width: 639px) { .glass-pane { margin: 0 var(--s-5) var(--s-3); border-radius: var(--r-lg); } }

/* ---------- pane 3: market mood ----------
   The job here is comparison, and the old version had no working bars — six
   rows of text stranded on the left of a 1280px panel. Now a diverging bar
   chart on a shared zero axis, held to a readable measure. */
.mood-wrap {
  flex: 1; min-height: 0; overflow-y: auto;
  overscroll-behavior-y: contain;
  width: 100%; max-width: var(--measure); margin: 0 auto;
  padding: var(--s-5) var(--s-6) var(--s-4);
  display: flex; flex-direction: column; gap: var(--s-4);
  scrollbar-width: none;
}
.mood-wrap::-webkit-scrollbar { display: none; }

.mood-strip { display: flex; flex-wrap: wrap; gap: var(--s-3); }
.mood-cell {
  display: flex; align-items: baseline; gap: var(--s-3);
  padding: var(--s-2) var(--s-4);
  border-radius: var(--r-pill);
  background: var(--glass-2);
  border: 1px solid var(--ink-08);
}
.mood-k {
  font-size: var(--fs-micro); text-transform: uppercase;
  letter-spacing: 0.09em; color: var(--text-3);
}
.mood-v { font-size: var(--fs-md); font-weight: 700; font-variant-numeric: tabular-nums; }
.mood-v.up { color: var(--pos); }
.mood-v.down { color: var(--neg); }

/* axis header — labels the scale the bars are drawn against */
.mood-axis {
  display: grid; align-items: center;
  grid-template-columns: var(--mood-cols);
  gap: var(--s-4);
  padding: 0 var(--s-3) var(--s-1);
  font-size: var(--fs-micro); color: var(--text-3);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.mood-axis__scale { display: flex; justify-content: space-between; }

.mood-rows { display: flex; flex-direction: column; gap: 2px; }
:root { --mood-cols: 7rem minmax(0, 1fr) 5.5rem 3rem; }

.mood-row {
  padding: var(--s-3) var(--s-3);
  border-radius: var(--r-md);
  transition: background 200ms;
}
.mood-row:hover { background: var(--glass-1); }
.mood-row__head {
  display: grid; align-items: center;
  grid-template-columns: var(--mood-cols);
  gap: var(--s-4);
}

/* the terms that actually produced the number */
.mood-why {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px;
  margin-top: var(--s-2); padding-left: 7rem;
  font-size: var(--fs-micro); color: var(--text-2);
}
.mood-why__lead { color: var(--text-2); }
.mood-why__src { font-style: italic; color: var(--text-3); }

/* methodology disclosure */
.mood-foot {
  margin-top: var(--s-2); padding-left: 7rem;
  font-size: var(--fs-micro); color: var(--text-2);
}
@media (max-width: 767px) { .mood-foot { padding-left: 0; } }

.method {
  margin-top: var(--s-3);
  border-top: 1px solid var(--line);
  padding-top: var(--s-3);
}
.method__summary {
  cursor: pointer; list-style: none;
  display: inline-flex; align-items: center; gap: var(--s-2);
  font-size: var(--fs-xs); color: var(--text-2);
  padding: var(--s-1) 0;
}
.method__summary::-webkit-details-marker { display: none; }
.method__summary::before { content: '+'; font-weight: 700; color: var(--text-3); }
.method[open] .method__summary::before { content: '−'; }
.method__summary:hover { color: var(--text-1); }
.method__body {
  display: flex; flex-direction: column; gap: var(--s-2);
  max-width: 68ch; padding: var(--s-2) 0 0;
}
.method__p { font-size: var(--fs-xs); line-height: 1.6; color: var(--text-2); }
.method__p--warn {
  padding: var(--s-2) var(--s-3);
  border-left: 2px solid var(--neg);
  background: rgba(143, 26, 16, 0.05);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  color: var(--text-2);
}
.mood-name { font-size: var(--fs-lg); font-weight: 600; letter-spacing: -0.015em; }

.mood-track {
  position: relative; display: block;
  height: 14px; border-radius: var(--r-pill);
  background: var(--ink-05);
}
/* zero line — the anchor that makes positive/negative readable at a glance */
.mood-track::before {
  content: ''; position: absolute; left: 50%; top: -5px; bottom: -5px;
  width: 1px; background: var(--ink-12);
}
.mood-fill {
  position: absolute; top: 0; height: 100%;
  border-radius: var(--r-pill);
  transition: width 700ms var(--ease), left 700ms var(--ease);
}
.mood-fill.pos { background: var(--pos); }
.mood-fill.neg { background: var(--neg); }

.mood-mentions { font-size: var(--fs-micro); color: var(--text-3); font-variant-numeric: tabular-nums; }
.mood-score {
  text-align: right; font-size: var(--fs-lg); font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.mood-score.up { color: var(--pos); }
.mood-score.down { color: var(--neg); }
.mood-score.flat { color: var(--text-3); }

@media (max-width: 767px) {
  :root { --mood-cols: 5rem minmax(0, 1fr) 2.75rem; }
  .mood-mentions, .mood-axis > :nth-child(n + 3) { display: none; }
  .mood-why { padding-left: 0; }
  .mood-wrap { padding: var(--s-4) var(--s-4); }
  .mood-row { gap: var(--s-3); padding: var(--s-2) var(--s-2); }
}

/* ---------- pane 4: leaderboards ----------
   Was one long list with the score column stranded ~1300px from the model
   name. Two side-by-side boards inside a measure, with a fill bar so the
   size of the gap between ranks is visible, not just inferable. */
/* The two boards used to be independent columns, so a blurb that wrapped to a
   different number of lines pushed one model list lower than the other. They
   now share row tracks: header, blurb, source, rows, footer and note each line
   up across both columns whatever the copy length. */
.board-list {
  flex: 1; min-height: 0; overflow-y: auto;
  overscroll-behavior-y: contain;
  width: 100%; max-width: var(--measure); margin: 0 auto;
  padding: var(--s-5) var(--s-6) var(--s-4);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  /* row tracks are set by syncBoardRows() in data.js to match the board count */
  grid-template-rows: repeat(6, auto);
  column-gap: var(--s-6); row-gap: var(--s-6);
  align-content: start;
  scrollbar-width: none;
}
.board { display: grid; grid-template-rows: subgrid; grid-row: span 6; }

/* Safari < 16 / older engines: approximate with a reserved blurb height */
@supports not (grid-template-rows: subgrid) {
  .board { display: block; }
  .board__blurb { min-height: 3.2em; }
}
.board-list::-webkit-scrollbar { display: none; }
.board { min-width: 0; align-content: start; }
.board__head { display: flex; align-items: baseline; gap: var(--s-3); }
.board__title {
  font-size: var(--fs-kick); text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--text-2);
}
.board__unit {
  padding: 1px 8px; border-radius: var(--r-pill);
  background: var(--ink-05); border: 1px solid var(--ink-08);
  font-size: var(--fs-micro); color: var(--text-3);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.board__blurb {
  margin-top: var(--s-2);
  font-size: var(--fs-xs); line-height: 1.55; color: var(--text-2);
  max-width: 46ch;
}
.board-src {
  display: inline-flex; align-items: center; gap: 6px;
  margin: var(--s-2) 0 var(--s-3);
  font-size: var(--fs-micro); color: var(--text-3); text-decoration: none;
}
.board-src__label { text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-3); }
.board-src__name { color: var(--text-2); font-weight: 600; }
.board-src:hover .board-src__name { text-decoration: underline; }
.board__foot {
  margin-top: var(--s-3);
  font-size: var(--fs-micro); color: var(--text-3); font-variant-numeric: tabular-nums;
}
.board__note {
  margin-top: 2px;
  font-size: var(--fs-micro); line-height: 1.5; color: var(--text-3); max-width: 44ch;
}
.badge {
  flex: none; padding: 2px 7px; border-radius: var(--r-pill);
  font-size: 0.78rem; font-weight: 700; letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
}
.badge--new  { color: var(--link); background: rgba(76, 29, 149, 0.08); }
.badge--up   { color: var(--pos);  background: rgba(10, 92, 57, 0.08); }
.badge--down { color: var(--neg);  background: rgba(143, 26, 16, 0.08); }
.board__rows { display: flex; flex-direction: column; gap: 1px; }

.board__row {
  position: relative;
  display: grid; align-items: center;
  grid-template-columns: 1.5rem minmax(0, 1fr) auto;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-3);
  border-radius: var(--r-sm);
  text-decoration: none; color: var(--text-1);
  transition: background 200ms;
}
/* No proportional fill bar here on purpose: the frontier board spans 1461-1507,
   and any normalised bar turns a 3% Elo spread into a full-width difference.
   The two-column layout already puts each score beside its model name. */
.board__row:hover { background: var(--glass-2); }
.board__row + .board__row { border-top: 1px solid var(--ink-05); }
.board__rank { font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }
.board__label { display: flex; align-items: baseline; gap: var(--s-2); min-width: 0; }
.board__name {
  font-weight: 600; font-size: var(--fs-md);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.board__org { flex: none; font-size: var(--fs-micro); color: var(--text-3); }
.board__score {
  font-variant-numeric: tabular-nums; font-size: var(--fs-md);
  color: var(--text-1); font-weight: 600;
}

@media (max-width: 899px) {
  .board-list { grid-template-columns: 1fr; row-gap: var(--s-6); padding: var(--s-4) var(--s-5); }
  .board { display: block; }
}
/* one narrow column: the larger name size truncated most models to an ellipsis */
@media (max-width: 639px) {
  .board__name { font-size: var(--fs-sm); }
  .board__row { grid-template-columns: 1.4rem minmax(0, 1fr) auto; gap: var(--s-2); }
}

/* ---------- pane 5: coding agents ---------- */
.agent-list {
  flex: 1; min-height: 0; overflow-y: auto;
  overscroll-behavior-y: contain;
  width: 100%; max-width: var(--measure); margin: 0 auto;
  padding: var(--s-5) var(--s-6) var(--s-4);
  display: flex; flex-direction: column; gap: var(--s-6);
  scrollbar-width: none;
}
.agent-list::-webkit-scrollbar { display: none; }

/* --- the week, up front --- */
.aweek {
  padding-bottom: var(--s-4);
  border-bottom: 1px solid var(--line);
}
.aweek__lede { display: flex; align-items: baseline; gap: var(--s-3); }
.aweek__num {
  font-size: 2.1rem; font-weight: 300; line-height: 1;
  letter-spacing: -0.03em; color: var(--text-1); font-variant-numeric: tabular-nums;
}
.aweek__text { font-size: var(--fs-sm); line-height: 1.4; color: var(--text-2); }
.aweek__chips {
  display: flex; flex-wrap: wrap; gap: var(--s-2);
  margin-top: var(--s-3);
}
.aweek__chip {
  display: inline-flex; align-items: baseline; gap: 7px;
  padding: 3px 11px; border-radius: var(--r-pill);
  background: var(--glass-2); border: 1px solid var(--line);
  text-decoration: none; color: var(--text-1);
  transition: background 180ms, border-color 180ms;
}
.aweek__chip:hover { background: var(--glass-3); border-color: var(--line-strong); }
.aweek__chipName { font-size: var(--fs-xs); font-weight: 600; }
.aweek__chipTag { font-size: var(--fs-micro); color: var(--text-3); font-variant-numeric: tabular-nums; }
.aweek__facts {
  display: flex; flex-wrap: wrap; gap: var(--s-2) var(--s-5);
  margin-top: var(--s-3);
  font-size: var(--fs-micro); color: var(--text-2);
}
.aweek__fact { display: inline-flex; align-items: center; gap: 6px; }
.aweek__fact::before {
  content: ''; width: 4px; height: 4px; border-radius: var(--r-pill);
  background: var(--text-3);
}
@media (max-width: 639px) { .aweek__num { font-size: 1.7rem; } }

.asec__head {
  display: flex; align-items: baseline; gap: var(--s-3); flex-wrap: wrap;
  padding-bottom: var(--s-2); margin-bottom: var(--s-3);
  border-bottom: 1px solid var(--line);
}
.asec__title {
  font-size: var(--fs-kick); text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--text-2);
}
.asec__note { font-size: var(--fs-micro); color: var(--text-3); }

/* --- popularity --- */
.arank-list { display: flex; flex-direction: column; }
.arank { border-radius: var(--r-sm); transition: background 180ms; }
.arank:hover, .arank.is-open { background: var(--glass-2); }
.arank.is-stale { opacity: 0.55; }

/* the whole collapsed row is the control — one line, always showing a caret */
.arank__head {
  width: 100%; display: grid;
  grid-template-columns: 1.75rem minmax(0, 1fr) auto 1.25rem;
  align-items: center; gap: var(--s-3);
  padding: var(--s-2) var(--s-3);
  background: none; border: 0; font: inherit; color: inherit;
  text-align: left; cursor: pointer;
}
.arank__pos { font-size: var(--fs-xs); color: var(--text-3); font-variant-numeric: tabular-nums; }
.arank__main { min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.arank__top { display: flex; align-items: baseline; gap: var(--s-2); flex-wrap: wrap; }
.arank__name {
  font-size: var(--fs-md); font-weight: 600; letter-spacing: -0.012em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.arank__cadence { font-size: var(--fs-micro); color: var(--text-3); font-variant-numeric: tabular-nums; }
.arank__track {
  display: block; height: 5px; border-radius: var(--r-pill);
  background: var(--ink-05); overflow: hidden;
}
.arank__fill { display: block; height: 100%; border-radius: var(--r-pill); background: var(--text-3); }
.arank:hover .arank__fill, .arank.is-open .arank__fill { background: var(--text-1); }

.arank__nums {
  display: flex; align-items: baseline; gap: var(--s-2); flex: none;
  min-width: 9.5rem; justify-content: flex-end;
}
.arank__stars { font-size: var(--fs-xs); color: var(--text-2); font-variant-numeric: tabular-nums; }
.arank__delta {
  font-size: var(--fs-micro); font-weight: 700; font-variant-numeric: tabular-nums;
  min-width: 4.2rem; text-align: right;
}
.arank__delta.up { color: var(--pos); }
.arank__delta.down { color: var(--neg); }
.arank__delta.flat { color: var(--text-3); }

.arank__chev { color: var(--text-3); transition: transform 200ms; text-align: center; }

/* Portrait: the star count and delta reserved ~9.5rem of a ~280px row, which
   left the name column under 40px — every agent rendered as "O…". Drop the
   numbers onto their own line beneath the name instead of squeezing it. */
@media (max-width: 639px) {
  .arank__head { grid-template-columns: 1.75rem minmax(0, 1fr) 1.25rem; row-gap: 6px; }
  .arank__pos  { grid-column: 1; grid-row: 1; align-self: start; padding-top: 3px; }
  .arank__main { grid-column: 2; grid-row: 1; }
  .arank__chev { grid-column: 3; grid-row: 1; align-self: start; padding-top: 2px; }
  .arank__nums {
    grid-column: 2; grid-row: 2;
    min-width: 0; justify-content: flex-start; gap: var(--s-3);
  }
  .arank__delta { min-width: 0; text-align: left; }
  /* the panel's indent was keyed to the collapsed row's number column */
  .arank__panel { margin-left: calc(1.75rem + var(--s-3) * 2); }
}
.arank.is-open .arank__chev { transform: rotate(180deg); color: var(--text-1); }

/* `display: flex` overrides the hidden attribute's UA `display: none`, so every
   panel rendered open and the caret appeared to do nothing. */
.arank__panel[hidden] { display: none; }
.arank__panel {
  display: flex; flex-direction: column; gap: var(--s-2);
  margin: 0 var(--s-3) var(--s-3) calc(1.75rem + var(--s-3) * 2);
  padding-left: var(--s-3);
  border-left: 2px solid var(--line-strong);
}
.arank__summary {
  font-size: var(--fs-xs); line-height: 1.55; color: var(--text-1);
  padding-bottom: var(--s-2); border-bottom: 1px solid var(--line);
}
.arank__desc { font-size: var(--fs-micro); color: var(--text-2); line-height: 1.5; }
.arel--inline { padding: var(--s-2) 0; border-left: 0; }

.arel__what--none { font-style: italic; color: var(--text-3); }

/* ---------- release changelog groups ----------
   A release note answers three different questions — what can it do now, what
   stopped being broken, what got quicker — and a single undifferentiated
   bullet list makes the reader sort them by hand. The fetcher buckets each
   line; these are the labelled sections it renders into. */
.arel__groups { display: flex; flex-direction: column; }
.chg { margin-top: var(--s-3); }
.chg:first-of-type { margin-top: var(--s-2); }
.chg__label {
  display: block; margin-bottom: 5px;
  font-size: var(--fs-micro); font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--text-3);
}
.chg__list { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 5px; }
.chg__item { display: flex; gap: var(--s-3); align-items: baseline; }
/* the dot carries the bucket's colour, so a scan down the card reads as
   green-additions / amber-fixes / blue-speedups without reading the labels */
.chg__dot {
  flex: none; width: 5px; height: 5px; margin-top: 1px;
  border-radius: var(--r-pill); background: var(--text-3);
}
.chg__text { font-size: var(--fs-micro); line-height: 1.55; color: var(--text-1); }
/* the palette carries exactly three accents; "faster" takes a solid ink dot
   rather than borrowing --neg, which would read as a regression */
.chg--new    .chg__dot { background: var(--pos); }
.chg--fixed  .chg__dot { background: var(--link); }
.chg--faster .chg__dot { background: var(--text-1); }
.chg--changed .chg__dot { background: var(--text-3); }

/* Colouring the label as well as the dot made four bright headings compete
   with the release tag; only the dot carries hue. */
.chg--new .chg__label { color: var(--text-2); }

.arank__btn {
  display: inline-flex; align-items: center; gap: 5px; align-self: flex-start;
  padding: 3px 10px; margin-top: var(--s-1); border-radius: var(--r-pill);
  border: 1px dashed var(--line-strong); background: transparent;
  font-size: var(--fs-micro); color: var(--text-2); text-decoration: none;
  transition: background 160ms, color 160ms;
}
.arank__btn:hover { background: var(--glass-3); color: var(--text-1); }

/* health is release cadence + commit recency, never a quality claim */
.health {
  flex: none; padding: 1px 8px; border-radius: var(--r-pill);
  font-size: var(--fs-micro); font-weight: 600; letter-spacing: 0.02em;
  border: 1px solid currentColor;
}
.health--active   { color: var(--pos); }
.health--steady   { color: var(--text-2); }
.health--slowing  { color: #9a6b12; }
.health--dormant,
.health--archived { color: var(--neg); }
.health--unknown  { color: var(--text-3); }
:root[data-theme="dark"] .health--slowing { color: #e0b357; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .health--slowing { color: #e0b357; }
}

/* --- what shipped, grouped by when --- */
.agroup { margin-bottom: var(--s-4); }
.agroup__head {
  display: flex; align-items: baseline; gap: var(--s-2);
  margin-bottom: var(--s-2);
}
.agroup__label {
  font-size: var(--fs-xs); font-weight: 600; color: var(--text-1);
}
.agroup__count {
  font-size: var(--fs-micro); color: var(--text-3);
  padding: 0 7px; border-radius: var(--r-pill); background: var(--ink-05);
  font-variant-numeric: tabular-nums;
}
.arel-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2) var(--s-5); }
.arel {
  display: flex; flex-direction: column; gap: 3px;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm);
  border-left: 2px solid var(--line-strong);
  text-decoration: none; color: var(--text-1);
  transition: background 180ms, border-color 180ms;
}
.arel:hover { background: var(--glass-2); border-left-color: var(--link); }
.arel__head { display: flex; align-items: baseline; gap: var(--s-2); flex-wrap: wrap; }
.arel__name { font-size: var(--fs-sm); font-weight: 600; }
.arel__tag {
  font-size: var(--fs-micro); color: var(--text-2); font-variant-numeric: tabular-nums;
  padding: 0 6px; border-radius: var(--r-pill); background: var(--ink-05);
}
.arel__date { margin-left: auto; font-size: var(--fs-micro); color: var(--text-3); }
.arel__what {
  font-size: var(--fs-micro); line-height: 1.5; color: var(--text-2);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
@media (max-width: 899px) {
  .arel-list { grid-template-columns: 1fr; }
  .arank__head { grid-template-columns: 1.5rem minmax(0, 1fr) auto 1.1rem; gap: var(--s-2); }
  .arank__nums { min-width: 0; }
  .arank__cadence { display: none; }
}

.aclosed { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-3); }
.aclosed__item {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--s-3);
  border: 1px dashed var(--line-strong); border-radius: var(--r-md);
  text-decoration: none; color: var(--text-1);
  transition: background 180ms;
}
.aclosed__item:hover { background: var(--glass-2); }
.aclosed__name { font-size: var(--fs-sm); font-weight: 600; }
.aclosed__org { font-size: var(--fs-micro); color: var(--text-2); }
.aclosed__fresh {
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: 2px; font-size: var(--fs-micro); color: var(--text-2);
}
.aclosed__dot { width: 5px; height: 5px; border-radius: var(--r-pill); background: var(--pos); }
.aclosed__why { font-size: var(--fs-micro); color: var(--text-3); line-height: 1.45; margin-top: 2px; }
@media (max-width: 899px) { .aclosed { grid-template-columns: 1fr; } }

/* ---------- pane 6: explainers + sources ----------
   Authored static markup, unlike every other pane. This is the crawlable
   substance the marketing homepage used to carry, and it has to survive
   without JavaScript for that to count. */
.learn {
  flex: 1; min-height: 0; overflow-y: auto;
  overscroll-behavior-y: contain;
  width: 100%; max-width: var(--measure); margin: 0 auto;
  padding: var(--s-5) var(--s-6) var(--s-4);
  display: flex; flex-direction: column; gap: var(--s-6);
  scrollbar-width: none;
}
.learn::-webkit-scrollbar { display: none; }
.learn__h {
  font-size: var(--fs-kick); text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--text-2);
}
.learn__lede { margin-top: 4px; font-size: var(--fs-xs); color: var(--text-2); }

.learn__grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--s-3); margin-top: var(--s-3);
}
.learn__card {
  display: flex; flex-direction: column; gap: 5px;
  padding: var(--s-4);
  border-radius: var(--r-md);
  background: var(--glass-2);
  border: 1px solid var(--glass-hi);
  box-shadow: var(--sh-tile);
}
.learn__kicker {
  font-size: var(--fs-micro); text-transform: uppercase;
  letter-spacing: 0.09em; color: var(--link); font-weight: 700;
}
.learn__title { font-size: var(--fs-md); font-weight: 600; letter-spacing: -0.012em; line-height: 1.3; }
.learn__body { font-size: var(--fs-micro); line-height: 1.55; color: var(--text-2); }

.learn__sources {
  list-style: none; margin-top: var(--s-3);
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s-2) var(--s-4);
}
.learn__sources a {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm); border-left: 2px solid var(--line-strong);
  text-decoration: none; color: var(--text-1);
  transition: background 180ms, border-color 180ms;
}
.learn__sources a:hover { background: var(--glass-2); border-left-color: var(--link); }
.learn__src { font-size: var(--fs-sm); font-weight: 600; }
.learn__srcNote { font-size: var(--fs-micro); color: var(--text-2); }

.learn__browse {
  list-style: none; margin-top: var(--s-3);
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s-2) var(--s-4);
}
.learn__browse a {
  display: flex; flex-direction: column; gap: 2px;
  padding: var(--s-2) var(--s-3);
  border-radius: var(--r-sm); border-left: 2px solid var(--link);
  text-decoration: none; color: var(--text-1);
  transition: background 180ms;
}
.learn__browse a:hover { background: var(--glass-2); }
@media (max-width: 639px) { .learn__browse { grid-template-columns: 1fr; } }

.learn__block--out { padding-top: var(--s-4); border-top: 1px solid var(--line); }
.learn__cta {
  display: inline-flex; align-items: center; margin-top: var(--s-3);
  padding: var(--s-2) var(--s-5); border-radius: var(--r-pill);
  border: 1px solid var(--line-strong);
  font-size: var(--fs-xs); color: var(--text-1); text-decoration: none;
  transition: background 180ms;
}
.learn__cta:hover { background: var(--glass-3); }

@media (max-width: 1199px) { .learn__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 899px)  { .learn__sources { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 639px)  {
  .learn { padding: var(--s-4) var(--s-5); }
  .learn__grid, .learn__sources { grid-template-columns: 1fr; }
}

/* ---------- scroll affordance ----------
   Several panes hold more than one screen of content — the leaderboards, the
   mood chart with its method panel, the news grid on narrow screens. Nothing
   signalled that, so readers stopped at the fold. A fade plus a cue appears
   only while there is more below, and clears once you reach the end. */
.scroller { position: relative; }
.scroller::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 68px;
  background: linear-gradient(to bottom, transparent, var(--page) 88%);
  opacity: 0; transition: opacity 250ms; pointer-events: none; z-index: 3;
}
.scroller.has-more::after { opacity: 0.9; }
/* the cue is an overlay, so without a tail of padding the final row always sat
   underneath it — most visible on a phone, where the pill is proportionally huge */
.scroller.has-more > .scroll-body { padding-bottom: 2.4rem; }

.scroll-cue {
  position: absolute; left: 50%; bottom: 10px; z-index: 4;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 12px; border-radius: var(--r-pill);
  background: var(--glass-3); border: 1px solid var(--line-strong);
  color: var(--text-2); font-size: var(--fs-micro);
  box-shadow: var(--sh-tile);
  opacity: 0; transform: translate(-50%, 6px);
  transition: opacity 250ms, transform 250ms;
  pointer-events: none;
}
.scroller.has-more > .scroll-cue { opacity: 1; transform: translate(-50%, 0); }
/* The news grid has no glass panel, so its scroller host is the pane itself
   and the cue anchored to the pane's bottom edge — behind the footer nav and
   the section dots. Lift it clear of that chrome. */
.pane > .scroll-cue { bottom: 76px; }

/* Portrait: the fixed section dots also sit centred at the bottom edge, so a
   centred cue landed on top of them. Tuck it into the right gutter instead —
   the pane's back/forward buttons hold the left, the dots hold the middle. */
@media (max-width: 767px) {
  .scroll-cue {
    left: auto; right: var(--s-4); transform: translateY(6px); max-width: 62%;
    /* it floats over live copy on a narrow column, so it needs its own ground */
    backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  }
  .scroller.has-more > .scroll-cue { transform: translateY(0); }
}
.scroll-cue__arrow { animation: cue-bob 1.8s ease-in-out infinite; }
@keyframes cue-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(3px); } }
@media (prefers-reduced-motion: reduce) { .scroll-cue__arrow { animation: none; } }

/* ---------- empty / error state ---------- */
.pane__empty {
  margin: auto; padding: var(--s-7);
  font-size: var(--fs-sm); color: var(--text-3); text-align: center;
}
