/* THE VISITOR DECK (Steven 2026-10-13 afternoon): the logged-out Toll Bench
   homepage the way the signed-in /home reads. The hero and "Need ideas?"
   as ONE card (.vd-entry), then one card per swipe (.vd-deck, cards from
   templates/feed/_visitor_deck.html): log in first, then the intro video
   (Steven 2026-10-13 evening: "The top yellow should be LOG IN, then the
   ad"), the benchmark, easy/hard/moonshot, the market, the sign-in gate.
   The odds card, "Grading Agents", is Steven's episode 6 filling the card
   (static/share/ep06-abe7735c/, a native <video>, .vd-film); its chips
   are card.css's .tb-card__band:
   Easy the neon green, Hard the brand yellow, Moonshot the neon blue, no
   colour here.
   /toll-bench wears the same frame for its sections (templates/feed/
   toll_bench.html, body.toll-bench--cards; its dark faces live in
   pages/toll-bench.css).

   THE FRAME is the deck's one card: static/cards/card.css's .tb-card (the
   ring, the radius) at the screen's height under the header, 4px from each
   edge on a phone and TikTok's 9:16 from 900px wide, the /home deck's
   shape (pages/home-cards.css .hc-slide). The PAGE scrolls, not an inner
   box, and snaps one card per swipe: mandatory, stopping on every card.
   --vd-top is the header's height, measured by static/js/pages/
   visitor-deck.js (64px until it runs). Tokens only; no em-dashes. */

html:has([data-visitor-deck]),
html:has(.toll-bench--cards) {
  --vd-top: 64px;
  --vd-h: calc(100svh - var(--vd-top) - var(--space-2));
  scroll-snap-type: y mandatory;
  scroll-padding-top: var(--vd-top);
}
@media (prefers-reduced-motion: no-preference) {
  html:has([data-visitor-deck]) { scroll-behavior: smooth; }
}

/* ---- one card per screen --------------------------------------------- */
.vd-deck {
  --tb-card-full-h: var(--vd-h);
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  margin-top: var(--space-2);
}
.vd-slide {
  box-sizing: border-box;
  flex: none;
  display: flex;
  flex-direction: column;
  width: 100%;
  height: var(--vd-h);
  min-height: 0;
  margin: var(--space-1) auto var(--space-2);
  scroll-snap-align: start;
  scroll-snap-stop: always;
  scroll-margin-top: var(--space-1);
}
@media (min-width: 900px) {
  .vd-slide { width: min(100%, calc(var(--vd-h) * 9 / 16)); }
}
/* a full card fills its slide exactly, as on /home: the face scrolls inside
   when its words need more room, the card never grows past the screen */
.vd-slide.tb-card--full,
.vd-slide > .tb-card--full { flex: 1 1 auto; min-height: 0; }
.vd-slide.tb-card--full > .tb-card__inner,
.vd-slide > .tb-card--full > .tb-card__inner {
  flex: 1 1 auto;
  min-height: 0;
  grid-template-rows: minmax(0, 1fr);
}
.vd-slide--offer > .tb-card { width: 100%; }

/* ---- the hero and the ideas: one card, no rule between ----------------- */
.vd-entry {
  box-sizing: border-box;
  width: 100%;
  max-width: var(--feed-card-max-width);
  border: var(--feed-card-border);
  border-radius: var(--interface-radius, var(--feed-card-radius));
  background: var(--feed-card-bg);
  box-shadow: var(--shadow-drop);
  /* its snap is the page's top: the margin is larger than the room above
     it, so the snap clamps to 0 and the hero's tag is never cut */
  scroll-snap-align: start;
  scroll-margin-top: var(--size-24);
}
.vd-entry > .wants-hero,
body.start-home:has(.wants-hero) .vd-entry > .wants-hero {
  max-width: none;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  padding-bottom: var(--space-4);
}
.vd-entry > .start-homepage-proof--ideas {
  width: 100%;
  max-width: none;
  margin-top: 0;
}
.vd-entry .start-ideas-card {
  border: 0;
  border-radius: 0 0 var(--interface-radius, var(--feed-card-radius)) var(--interface-radius, var(--feed-card-radius));
  background: transparent;
  box-shadow: none;
  padding-top: var(--space-2);
}
/* the "Need ideas?" tag row sits in the card's flow, not on a seam */
.vd-entry .start-ideas-card > .start-intro-card__pills {
  position: static;
  transform: none;
}

/* ---- the faces --------------------------------------------------------- */
.vd-face { display: flex; flex-direction: column; min-height: 0; }
.vd-face > .tb-card__art { flex: 1 1 auto; min-height: 0; container-type: inline-size; }
.vd-face > .tb-card__art .tb-card__over { flex: 1 1 auto; justify-content: flex-end; }
.vd-face > .tb-card__panel { flex: none; padding-bottom: var(--space-5); }
.vd-face--night { background: var(--color-black); }
.vd-art .tb-card__title { overflow-wrap: anywhere; }

.vd-reasons {
  display: grid;
  gap: var(--space-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
.vd-reasons li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: var(--space-3);
  color: var(--text-secondary);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.4;
}
.vd-reasons b { color: var(--text-primary); font-weight: var(--font-bold); }
.vd-reasons iconify-icon {
  display: grid;
  place-items: center;
  width: var(--size-8);
  height: var(--size-8);
  border-radius: var(--radius-full);
  background: var(--surface-secondary);
  color: var(--tb-brand-purple, var(--accent-tertiary));
  font-size: var(--text-lg);
}

/* ---- the video, filling the card (card 2, the ad) ---------------------- */
.vd-video { position: relative; flex: 1 1 auto; min-height: 0; display: flex; }
.vd-video__tag {
  position: absolute;
  z-index: 2;
  top: var(--space-4);
  left: var(--space-4);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--highlight-yellow);
  color: var(--color-black);
  font-family: var(--font-mono);
  font-size: var(--text-sm);
  font-weight: var(--font-bold);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  pointer-events: none;
}
.vd-video__cover {
  position: relative;
  flex: 1 1 auto;
  display: block;
  width: 100%;
  min-height: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: var(--color-black);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  overflow: hidden;
}
.vd-video__cover:focus-visible { outline: 3px solid var(--highlight-yellow); outline-offset: -3px; }
.vd-video__thumb { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 52% 50%; }
.vd-video__cover::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, color-mix(in srgb, var(--color-black) 70%, transparent) 0%, color-mix(in srgb, var(--color-black) 20%, transparent) 34%, transparent 60%);
  pointer-events: none;
}
.vd-video__words {
  position: absolute;
  z-index: 1;
  left: var(--space-5);
  right: var(--space-5);
  bottom: var(--space-6);
  display: grid;
  justify-items: start;
  gap: var(--space-2);
  pointer-events: none;
}
.vd-video__line { color: var(--color-white); font-family: var(--font-heading); font-size: var(--text-3xl); font-weight: 800; line-height: 1.05; }
.vd-video__line--how .hl { padding: 2px var(--space-1); border-radius: var(--radius-sm); background: var(--highlight-yellow); color: var(--color-black); }
.vd-video__play {
  position: absolute;
  z-index: 1;
  top: 50%;
  left: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  width: var(--size-20);
  height: var(--size-20);
  border-radius: var(--radius-full);
  background: var(--tb-brand-purple, var(--accent-tertiary));
  box-shadow: var(--shadow-md);
  transform: translate(-50%, -50%);
  pointer-events: none;
}
.vd-video__play::before {
  content: "";
  display: block;
  margin-left: var(--space-1);
  border-style: solid;
  border-width: var(--space-4) 0 var(--space-4) var(--space-6);
  border-color: transparent transparent transparent var(--color-white);
}
.vd-video iframe { flex: 1 1 auto; width: 100%; height: 100%; min-height: 0; border: 0; background: var(--color-black); }

/* ---- card 4, Grading Agents: Steven's episode 6, the whole card -------- */
/* Steven 2026-10-14 morning: "This doesn't play as a full card. The title
   should be 'Grading Agents'. It shouldn't have a button; this should be a
   full-size video like Lumi's ... titles at the top ... as large as the
   probability text". The ad's shape (.vd-video above): the film fills the
   card edge to edge, no white panel, no button, no native controls. Over
   it, in the art's flow: the kicker, the title and its one line at the
   top under a soft fade from the picture's top edge (the want card's
   shade, card.css .tb-card--want .tb-card__shade), the middle clear, the
   three band chips with their rules in one row at the foot over the
   bottom fade. The title is as large as the want card's probability
   number (card.css .tb-card__number, the same clamp). The whole art is
   one tap (.vd-film__tap, under the words, which let taps through):
   visitor-deck.js plays the film with sound and pauses it; while it plays
   (.is-playing) the words and the play mark step aside as the ad's cover
   does, the kicker stays as the ad's tag does. */
.vd-art--film { background: var(--color-black); }
.vd-film {
  position: absolute;
  inset: 0;
  z-index: -2;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  background: var(--color-black);
}
/* the card is the player: no browser control layer, ever */
.vd-film::-webkit-media-controls { display: none !important; }
.vd-film::-webkit-media-controls-panel { display: none !important; }
.vd-film::-webkit-media-controls-overlay-play-button { display: none !important; }
.vd-film::-webkit-media-controls-start-playback-button { display: none !important; -webkit-appearance: none; }
/* the fade from the top edge runs deep enough that the cover's own small
   print (its "No 06" mark) sinks under the title and its line */
.vd-art--film > .vd-film__shade {
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--color-dark-900) 90%, transparent) 0%,
    color-mix(in srgb, var(--color-dark-900) 86%, transparent) 21%,
    color-mix(in srgb, var(--color-dark-900) 40%, transparent) 31%,
    transparent 42%,
    transparent 66%,
    color-mix(in srgb, var(--color-dark-900) 78%, transparent) 100%);
}
.vd-film__tap {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.vd-film__tap:focus-visible { outline: 3px solid var(--highlight-yellow); outline-offset: -3px; }
.vd-art--film > .vd-film__top,
.vd-art--film > .vd-film__head,
.vd-art--film > .vd-film__bands { position: relative; z-index: 1; pointer-events: none; }
.vd-film__head { display: flex; flex-direction: column; gap: var(--space-2); margin-top: var(--space-4); }
/* the size and the tracking are the probability number's exactly (one
   line on a phone); the title keeps its own leading and a little room
   under the last line, so a "g" is never clipped by its line clamp */
.vd-art--film .vd-film__title {
  margin: 0;
  padding-bottom: 0.08em;
  color: var(--text-inverse);
  font-size: clamp(var(--size-10), 12vw, var(--text-5xl));
  letter-spacing: -0.04em;
}
.vd-art--film .vd-film__line { font-size: var(--text-lg); line-height: 1.35; text-shadow: 0 1px 12px color-mix(in srgb, var(--color-black) 45%, transparent); }
.vd-film__bands {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-2);
  margin: auto 0 0;
  padding: 0;
  list-style: none;
}
.vd-film__bands li { display: flex; flex-direction: column; align-items: center; gap: var(--space-1); min-width: 0; }
.vd-film__bands .tb-card__band { justify-content: center; width: 100%; box-sizing: border-box; }
.vd-film__rule {
  color: var(--text-inverse);
  font-family: var(--font-body);
  --interface-font: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  line-height: 1.3;
  text-align: center;
  text-shadow: 0 1px 12px color-mix(in srgb, var(--color-black) 45%, transparent);
}
/* playing: the film is the card; a tap pauses it and the words come back */
.vd-art--film.is-playing > .vd-film__shade,
.vd-art--film.is-playing > .vd-film__head,
.vd-art--film.is-playing > .vd-film__bands,
.vd-art--film.is-playing .vd-video__play { opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  .vd-art--film > .vd-film__shade,
  .vd-art--film > .vd-film__head,
  .vd-art--film > .vd-film__bands,
  .vd-art--film .vd-video__play { transition: opacity var(--duration-normal) var(--ease-default); }
}

/* ---- the benchmark card: the field card the landing draws ------------- */
.vd-card--bench { cursor: pointer; }
.vd-face--bench { background: var(--surface-primary); }
.vd-bench__field { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.vd-bench__field > .fv-section {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  border: 0;
}
.vd-bench__field .fv-card {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  max-width: none;
  margin: 0;
  padding: var(--space-8) var(--space-4) 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.vd-bench__field .fv-live { top: var(--space-4); left: var(--space-4); transform: none; }
.vd-bench__field .fv-head { flex: none; margin-top: var(--space-2); }
.vd-bench__field .fv-chart-wrap { flex: 1 1 auto; min-height: 0; display: flex; }
.vd-bench__field .fv-svg { flex: 1 1 auto; width: 100%; height: 100%; min-height: 0; }
.vd-bench__field .fv-clock-help { display: none; }
.vd-panel--bench { padding-top: var(--space-3); }

/* ---- the gate --------------------------------------------------------- */
.vd-card--gate .tb-card__title { font-size: var(--text-3xl); line-height: 1.1; }
/* THE GATE'S PICTURE (Steven 2026-10-15: "this needs to be the cat meme! why
   didn't we make it the right shape?"). The art is a column: the cat clip
   fills the picture box (the card's art above the title, cut to that box's
   own shape, login-cat-card.*, so cover crops almost nothing), the title
   under it with no stars and no shade behind. The poster is the box's own
   background, so the first paint and the no-script case show the cat; the
   clip fades in over it once its poster has loaded (login-art.js) and never
   loads under reduced motion or Save-Data. */
.vd-face > .tb-card__art.vd-art--gate-clip { padding: 0; justify-content: flex-start; background: var(--color-black); }
.vd-art--gate-clip > .tb-card__bg,
.vd-art--gate-clip > .tb-card__shade { display: none; }
.vd-art--gate-clip > .vd-gate__pic {
  position: relative;
  flex: 1 1 0;
  min-height: 0;
  overflow: hidden;
  background: var(--color-black) 50% 32% / cover no-repeat;
}
.vd-gate__clip {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 32%;
  opacity: 0;
  transition: opacity var(--duration-slow, 0.5s) ease;
  pointer-events: none;
}
.vd-gate__clip[hidden] { display: none; }
.vd-gate__clip.is-on { opacity: 1; }
.vd-face > .tb-card__art.vd-art--gate-clip > .tb-card__over {
  flex: none;
  margin-top: 0;
  justify-content: flex-start;
  padding: var(--space-4) var(--space-5) var(--space-3);
}
@media (prefers-reduced-motion: reduce) {
  .vd-gate__clip { transition: none; }
}
.vd-legal {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-2);
  margin: 0;
  color: var(--text-secondary);
  font-size: var(--text-xs);
}
.vd-legal a { color: inherit; text-decoration: none; }
.vd-legal a:hover { text-decoration: underline; }

/* The deck ends on the gate: no page below it until sign-in. The public
   footer's links ride the gate card (.vd-legal). */
html:has([data-visitor-deck]) .site-public-footer { display: none; }
.start-home__main:has([data-visitor-deck]),
.start-home__main:has([data-visitor-deck]) .wants-page { padding-bottom: 0; }

/* a short phone (375x667): smaller words so the button stays on the card */
@media (max-height: 760px) {
  .vd-face > .tb-card__panel { gap: var(--space-2); padding-top: var(--space-3); }
  .vd-reasons li { font-size: var(--text-sm); }
  .vd-video__line { font-size: var(--text-2xl); }
  .vd-card--gate .tb-card__title { font-size: var(--text-2xl); }
}

/* ---- /start: the same deck under its own entry card ------------------ */
/* Steven 2026-10-13 evening, on /start: "it's supposed to move like these
   are cards, and then it's supposed to continue on to become the cards
   that are part of the Want Market." templates/feed/start_home.html draws
   this deck under "Need ideas?" for a visitor with LAYOUT_CARDS on.
   /start scrolls an inner box (.start-home__page, start-home.css), not the
   html, so the snap rides that box. Once a want is sent
   (body.start-home--future) the snap is off and the deck folds away with
   the other proof sections (start-home.css), so the entry flow scrolls as
   it always has. The entry card itself is not restyled: "Need ideas?"
   tucks up under its rounded foot (one card radius), its own top corners
   square and its tag row in the flow, so the two read as one set with no
   gap and no rule between. */
body.start-home:not(.start-home--future) .start-home__page:has([data-visitor-deck]) {
  scroll-snap-type: y mandatory;
  scroll-padding-top: var(--vd-top);
}
@media (prefers-reduced-motion: no-preference) {
  body.start-home:not(.start-home--future) .start-home__page:has([data-visitor-deck]) { scroll-behavior: smooth; }
}
.start-home__main:has([data-visitor-deck]) > .start-homepage-proof--ideas {
  position: relative;
  z-index: 1;
  margin-top: calc(var(--feed-card-radius) * -1);
  /* the set is the first stop: the margin reaches past the entry card, so
     the snap clamps to the page's top, the set scrolls freely down to its
     foot, and the deck takes over card by card from there */
  scroll-snap-align: start;
  scroll-margin-top: 100vh;
}
.start-home__main:has([data-visitor-deck]) > .start-homepage-proof--ideas > .start-ideas-card {
  border-top: 0;
  border-top-left-radius: 0;
  border-top-right-radius: 0;
  padding-top: var(--space-4);
  /* a shadow that falls below the set, never up over the seam */
  box-shadow: var(--shadow-lg);
}
.start-home__main:has([data-visitor-deck]) > .start-homepage-proof--ideas .start-ideas-card > .start-intro-card__pills {
  position: static;
  transform: none;
}
.start-home__main > .start-homepage-proof--deck { margin-top: 0; }

/* ---- card 1, the login: a picture of the login card itself ----------- */
/* Steven 2026-10-13 evening: "Create your login to post", the why in two
   sentences on the white panel, the three rows gone, and the card's own
   art: the /login card floating over the brand purple and the yellow
   bullseye, a soft shadow under it (static/images/login-card-floating.png,
   780x1160, the art box at 2x, baked by scripts/make_login_card_image.py).
   The picture covers the art; its lower third is plain purple for the
   title, so the crop anchors a little above the middle and the floating
   card stays whole on a short phone. */
.vd-art--login { background: var(--tb-brand-purple); }
.vd-art--login .vd-login__img { object-fit: cover; object-position: 50% 30%; }
/* a short phone: the art box is nearly square, so the crop rides higher and
   the floating card clears the LOG IN kicker */
@media (max-height: 760px) {
  .vd-art--login .vd-login__img { object-position: 50% 15%; }
}

/* ---- fluid: a card off the screen costs nothing ------------------------ */
/* Steven 2026-10-14: "Make sure clicking on this site feels fluid. I don't
   want these stalls when clicking into the PDP, or scrolling". Measured on
   the landing: the benchmark card's field draws one mark per want (a few
   SVG nodes each) and the gate's stars twinkle forever, so EVERY frame (a tap,
   a swipe, the ideas banner turning) re-laid and re-composited them, on or
   off the screen. Those two faces are now skipped while they are not near
   the screen (content-visibility: auto): not styled, laid out or painted,
   the stars still, the size the slide's. Measured (live port, load 3 to
   5): a tap on a "Need ideas?" tile to its popped card done in 42 to 83 ms
   with them skipped, 215 to 297 ms without. The other faces (log in, the
   ad, the bands video) are light and stay drawn, so arriving on them costs
   nothing mid-swipe; an offer card (the one card) turns in 3D, which paint
   containment would flatten. */
.vd-slide .vd-face--bench,
.vd-card--gate .vd-face {
  content-visibility: auto;
  contain-intrinsic-size: auto var(--vd-h);
}
/* The deck's copy of the field draws each mark plain: one glow filter and
   one opacity per mark made every mark its own compositing layer. The full
   chart on /toll-bench keeps its glow. */
.vd-face--bench .fv-work-line,
.vd-face--bench .fv-marker {
  filter: none;
  opacity: 1;
}
/* The Details sheet (static/js/pages/ready-sheet.js) rises the moment it
   is tapped; this stands in its body, a picture and two lines, until the
   product page's words arrive. */
.ready-sheet__wait {
  display: grid;
  gap: var(--space-3);
  padding: var(--space-4) 0 var(--space-8);
}
.ready-sheet__wait > span {
  display: block;
  height: var(--space-4);
  border-radius: var(--radius-sm);
  background: var(--surface-tertiary);
  animation: vd-sheet-wait 0.9s ease-in-out infinite alternate;
}
.ready-sheet__wait > span:first-child {
  height: auto;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-lg);
}
.ready-sheet__wait > span:last-child { width: 60%; }
@keyframes vd-sheet-wait { from { opacity: 1; } to { opacity: 0.55; } }
/* The page keeps its scrollbar's room while a card or a sheet holds it
   still (body overflow: hidden), so opening one never re-lays the page. */
html:has([data-visitor-deck]) { scrollbar-gutter: stable; }
@media (prefers-reduced-motion: reduce) {
  .ready-sheet__wait > span { animation: none; }
}
