/* ==========================================================================
   vt.css · Case page side of the cross-document view transitions
   Owner: Case Study Bot. v0.2.4 (title name off while Present is open and off its slide copies). v0.2.3 (one image name: case-cover on the hero <img> only, none on the figure or Present copies; EB and PPB card review). v0.2.2 (hero name on the image, not the figure). v0.2.1 (trimmed: nav + root rules now come from page-transitions.css in system.css). v0.2.0 (transition audit 2026-10-29 fixes 2 + 3, Shah thumbs-up 11:24am ET; PLAN.md row 5c).
   v0.1.0 (card-to-case names, motion idea 11, agreed with Experience Bot, Oct 29) is kept as is.

   1. Card → case morph. /work names each OPEN card's image and title card-<slug>-img / card-<slug>-title
      (design-system/components/view-transitions.css). A case page links this file and sets <html data-cs-vt="<slug>">;
      its cover carries [data-cs-hero] and its h1 [data-cs-title], and the names below pair them with the card.
      Slugs are the lowercase folder names. The morph uses the same 626ms smooth spring as the /work side, but only
      on the 12 card names (it used to sit on ::view-transition-group(*), which also gave the page itself 626ms).
      Gated cases (chasedeposits, dependent) link this file WITHOUT data-cs-vt: no per-element names, so nothing on the
      locked cover pairs with a card; they get the page transition (3) only.
   2. Nav holds still. #main-navbar is named site-nav (same name as Portfolio Site Bot's page-transitions.css) and
      never animates. Case pages still fetch the nav (components.js), so on arrival only the old page's bar is
      captured: it stays put for the transition and the live bar takes over under it.
   3. Page change (M3 fade-through, ≤300ms). Old page recedes (scale .985 + fade, 140ms, --ease-exit); new page
      rises 24px and fades in (280ms, --ease-enter). Back (the 'back' type, set by the head script on a history
      traverse to an earlier entry) reverses it. A card name with no partner (case → case, or the other cards when
      leaving /work) travels with its page instead of fading on its own.
   4. Password sheet after the morph. While html.cs-vt-in is set (head script: from pagereveal until the transition
      finishes) the gate sheet holds its closed pose; then its own sheet.css spring plays. CSS timing only: gate.js,
      the form and the gate logic are untouched.
   Reduced motion: still opted in, but nothing moves: a 150ms crossfade of the page and the card images.
   Transform and opacity only; nothing here animates blur or backdrop-filter. Browsers without cross-document view
   transitions (Firefox) ignore all of it and simply navigate. Tokens all have fallbacks (case-tokens.css not needed).
   Keyframes are cs-vt-* so they never collide with the base page-transitions.css (same values on purpose).
   ========================================================================== */
@view-transition { navigation: auto; }

:root {
  --cs-vt-out: var(--dur-page-out, 140ms);
  --cs-vt-in: var(--dur-page-in, 280ms);
  --cs-vt-rise: var(--page-rise, 24px);
  --cs-vt-recede: var(--page-recede, .985);
  --cs-vt-reduced: var(--dur-page-reduced, 150ms);
  --cs-vt-morph: var(--dur-spring-smooth, 626ms);
  --cs-vt-morph-ease: var(--ease-spring-smooth, cubic-bezier(.2, .8, .2, 1));
  --cs-vt-enter: var(--ease-enter, cubic-bezier(.22, 1, .36, 1));
  --cs-vt-exit: var(--ease-exit, cubic-bezier(.64, 0, .78, 0));
}

/* ---- 1 · names (one pair per open case; never two elements with one name) ---- */
[data-cs-hero] { view-transition-name: none; }   /* the figure (plate) stays out of the card morph */
/* the one image name: case-cover on the hero <img> only (TurboTax puts data-cs-hero on the img itself). Not while Present
   is open and never on Present's .cs-slide copies, so a page never has two. --cs-hero-vt is kept but names nothing. */
html[data-cs-vt]:not(.csp-open) [data-cs-hero]:not(.cs-slide [data-cs-hero]) .cs-media img,
html[data-cs-vt]:not(.csp-open) img[data-cs-hero]:not(.cs-slide img) { view-transition-name: case-cover; }
[data-cs-title] { view-transition-name: var(--cs-title-vt, none); }
/* like the hero (efb4c51): no title name while Present is open, and never on Present's slide copies or anything in its deck */
html.csp-open [data-cs-title], .cs-slide [data-cs-title], .csp [data-cs-title] { view-transition-name: none; }

html[data-cs-vt="podcast"]             { --cs-hero-vt: card-podcast-img;             --cs-title-vt: card-podcast-title; }
html[data-cs-vt="amnysystem"]          { --cs-hero-vt: card-amnysystem-img;          --cs-title-vt: card-amnysystem-title; }
html[data-cs-vt="accessibilityapp101"] { --cs-hero-vt: card-accessibilityapp101-img; --cs-title-vt: card-accessibilityapp101-title; }
html[data-cs-vt="turbotax"]            { --cs-hero-vt: card-turbotax-img;            --cs-title-vt: card-turbotax-title; }
html[data-cs-vt="chatbot"]             { --cs-hero-vt: card-chatbot-img;             --cs-title-vt: card-chatbot-title; }
html[data-cs-vt="easyyelp"]            { --cs-hero-vt: card-easyyelp-img;            --cs-title-vt: card-easyyelp-title; }

/* ---- 2 · nav holds still ----
   The site-nav name, its animation: none and the old bar's display: none come from page-transitions.css (system.css). */
::view-transition-old(site-nav):only-child { display: block; }   /* only the old page had it (the case nav is still loading): keep it */

/* ---- 3 · page change: recede / rise, Back reversed ---- */
::view-transition-group(*) { animation-duration: var(--cs-vt-in); }   /* replaces the system.css 626ms spring on every group */
/* root (old/new, Back reversed, reduced crossfade) comes from page-transitions.css (system.css), same values */

/* card names without a partner move with their page */
::view-transition-old(*):only-child { animation: var(--cs-vt-out) var(--cs-vt-exit) both cs-vt-recede; }
::view-transition-new(*):only-child { animation: var(--cs-vt-in) var(--cs-vt-enter) both cs-vt-rise; }
html:active-view-transition-type(back)::view-transition-old(*):only-child { animation-name: cs-vt-sink; }
html:active-view-transition-type(back)::view-transition-new(*):only-child { animation-name: cs-vt-settle; }
::view-transition-old(site-nav):only-child, ::view-transition-new(site-nav):only-child,
html:active-view-transition-type(back)::view-transition-old(site-nav):only-child,
html:active-view-transition-type(back)::view-transition-new(site-nav):only-child { animation: none; }   /* the bar holds in both directions
   (a named pseudo with :only-child outranks the plain named rule, so the nav needs its own :only-child line) */

/* the morph: the 626ms spring, card names only */
::view-transition-group(card-podcast-img), ::view-transition-group(card-podcast-title),
::view-transition-group(card-amnysystem-img), ::view-transition-group(card-amnysystem-title),
::view-transition-group(card-accessibilityapp101-img), ::view-transition-group(card-accessibilityapp101-title),
::view-transition-group(card-turbotax-img), ::view-transition-group(card-turbotax-title),
::view-transition-group(card-chatbot-img), ::view-transition-group(card-chatbot-title),
::view-transition-group(card-easyyelp-img), ::view-transition-group(card-easyyelp-title) {
  animation-duration: var(--cs-vt-morph);
  animation-timing-function: var(--cs-vt-morph-ease);
}

@keyframes cs-vt-recede { to   { opacity: 0; transform: scale(var(--cs-vt-recede)); } }
@keyframes cs-vt-rise   { from { opacity: 0; transform: translateY(var(--cs-vt-rise)); } }
@keyframes cs-vt-sink   { to   { opacity: 0; transform: translateY(var(--cs-vt-rise)); } }
@keyframes cs-vt-settle { from { opacity: 0; transform: scale(var(--cs-vt-recede)); } }
@keyframes cs-vt-fade-out { to   { opacity: 0; } }
@keyframes cs-vt-fade-in  { from { opacity: 0; } }

/* ---- 4 · the password sheet waits for the transition, then rises ---- */
html.cs-vt-in #password-gate-overlay.active .resume-modal-content.gate-sheet {
  transform: translateY(var(--reveal-distance, 16px)) scale(.96); opacity: 0;   /* sheet.css's closed pose */
}
@media (max-width: 47.99em) {   /* phones: sheet.css's bottom-sheet closed pose (below the fold, opaque) */
  html.cs-vt-in #password-gate-overlay.active .resume-modal-content.gate-sheet { transform: translateY(100%); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {   /* sheet.css's reduced closed pose: no movement, just hidden */
  html.cs-vt-in #password-gate-overlay.active .resume-modal-content.gate-sheet { transform: none; opacity: 0; }
}

/* ---- reduced motion: a 150ms crossfade, nothing moves ----
   Same rules as above with the movement set to zero, so every layer just fades. (Restyling ::view-transition-*(*):only-child
   inside this media query crashes WebKit, so it only overrides variables, the groups and root's linear easing.) */
@media (prefers-reduced-motion: reduce) {
  :root { --cs-vt-out: var(--cs-vt-reduced); --cs-vt-in: var(--cs-vt-reduced); --cs-vt-rise: 0px; --cs-vt-recede: 1; --cs-vt-enter: linear; --cs-vt-exit: linear; }
  ::view-transition-group(*) { animation-name: none; animation-duration: var(--cs-vt-reduced); }   /* no morph; paired layers take the UA crossfade at 150ms */
}
