/* ============================================================
   Dani Maldonado · portfolio v3
   Type: Fraunces variable (opsz, ital, SOFT, WONK) + JetBrains Mono
   Color: 60/30/10 modular per surface
   Motion: editorial pacing, reduced-motion honored
   ============================================================ */

:root {
  --paper: #FAFAF7;
  --ink: #0F0F0F;
  /* RGB triple behind --ink, so ink-based hairlines/tints can flip wholesale
     when a surface inverts (e.g. a dark-themed case). */
  --ink-rgb: 15, 15, 15;
  --orange: #FE5000;
  --starry: #FFD300;
  --lime: #B8E000;

  --hairline: rgba(var(--ink-rgb), 0.15);
  --ink-50: rgba(var(--ink-rgb), 0.5);
  --ink-70: rgba(var(--ink-rgb), 0.7);

  --gutter: clamp(20px, 6vw, 12vw);

  --ease-out-emph: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-inout: cubic-bezier(0.83, 0, 0.17, 1);
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: "Fraunces", Georgia, serif;
  font-weight: 400;
  font-variation-settings: "opsz" 18, "SOFT" 30, "WONK" 0;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-feature-settings: "ss01", "ss02";
}

body {
  min-height: 100vh;
  /* No persistent header chrome. No global cursor effects. */
  cursor: auto;
}

/* Legacy cursor system retired — global spotlight cursor handles it */

/* Mono utility */
.mono {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: clamp(11px, 0.85vw, 13px);
  letter-spacing: 0.04em;
  text-transform: lowercase;
  font-weight: 400;
  color: var(--ink-50);
}

.mono--ink {
  color: var(--ink);
}

.mono--hi {
  color: var(--ink-70);
}

a {
  color: inherit;
  text-decoration: none;
  -webkit-tap-highlight-color: transparent;
}

a.mono {
  display: inline-block;
  transition: color 220ms var(--ease-out-emph);
}

a.mono:hover {
  color: var(--orange);
}

/* Routed screens ---------------------------------------------- */

.screen {
  display: none;
  min-height: 100vh;
  width: 100%;
  position: relative;
}

.screen.is-active {
  display: block;
}

/* 200ms paper pause between routes — §6.8 */
.route-cover {
  position: fixed;
  inset: 0;
  background: var(--paper);
  z-index: 9998;
  opacity: 0;
  pointer-events: none;
  transition: opacity 80ms linear;
}

.route-cover.is-on {
  opacity: 1;
  pointer-events: auto;
  transition: opacity 0ms linear;
}

/* ============================================================
   HOME
   ============================================================ */

.home {
  background: var(--paper);
}

.top-strip {
  position: absolute;
  top: clamp(20px, 3vh, 36px);
  left: var(--gutter);
  right: var(--gutter);
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  z-index: 5;
}

.masthead {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  line-height: 1;
}

.masthead-name {
  font-family: "Fraunces", Georgia, serif;
  font-size: clamp(20px, 2vw, 28px);
  line-height: 1;
  letter-spacing: -0.022em;
  font-style: italic;
  font-variation-settings: "opsz" 36, "ital" 1, "SOFT" 50, "WONK" 0;
  color: var(--ink);
}

.masthead-role {
  color: var(--ink-50);
  font-size: clamp(10px, 0.8vw, 12px);
  letter-spacing: 0.08em;
}

.top-strip .nav {
  display: flex;
  gap: clamp(16px, 2vw, 28px);
}

.top-strip .nav .sep {
  color: var(--ink-50);
}

/* Fold 1 — anchor */

.fold-anchor {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: clamp(60px, 9vh, 100px) var(--gutter) clamp(40px, 6vh, 64px);
  position: relative;
}

.anchor-intro {
  font-family: "Fraunces", Georgia, serif;
  font-style: italic;
  font-size: clamp(20px, 2vw, 28px);
  line-height: 1;
  letter-spacing: -0.022em;
  font-variation-settings: "opsz" 36, "ital" 1, "SOFT" 50, "WONK" 0;
  color: var(--ink);
  /* margin-top: auto + nav's margin-top: auto split the free space evenly,
     centering the intro+h1 group vertically while keeping nav pinned at the
     viewport bottom. */
  margin: auto 0 clamp(16px, 2vh, 28px);
  /* Intro: drops in from above with a slight overshoot. Final state
     applied by applyHeroFinalState() for reduced-motion / returning
     visitors / touch. */
  opacity: 0;
  transform: translateY(-12px);
  transition:
    opacity 480ms cubic-bezier(0.4, 0, 0.2, 1),
    transform 600ms cubic-bezier(0.34, 1.36, 0.64, 1);
}

.anchor-intro.is-on {
  opacity: 1;
  transform: none;
}

.anchor-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: clamp(20px, 3vw, 48px);
  width: 100%;
}

.home-nav {
  margin-top: auto;
  display: flex;
  gap: clamp(16px, 2vw, 28px);
}

/* ------------------------------------------------------------
   Anchor: spotlight reveal
   ------------------------------------------------------------ */

@property --disc-r {
  syntax: '<length-percentage>';
  initial-value: 0px;
  inherits: true;
}

@property --mx {
  syntax: '<length-percentage>';
  initial-value: -200px;
  inherits: true;
}

@property --my {
  syntax: '<length-percentage>';
  initial-value: -200px;
  inherits: true;
}

.fold-anchor {
  position: relative;
  overflow: hidden;
}

.anchor {
  position: relative;
  z-index: 2;
  font-size: clamp(48px, 9vw, 144px);
  line-height: 1.05;
  letter-spacing: -0.022em;
  font-variation-settings: "opsz" 144, "SOFT" 30, "WONK" 0;
  margin: 0;
  max-width: 18ch;
  text-wrap: balance;
}

.anchor-line {
  display: block;
}

/* Forced break after "complex" so the headline always reads
   "I make complex" / "things clear" from tablet up to ultra-wide cinema
   screens. Without it, the sentence collapses onto a single line on big
   monitors and the (wider) particle "complex" overlaps "things". Hidden
   on mobile (<720px), where the layout is handled separately/later. */
.anchor-cut { display: none; }
@media (min-width: 720px) {
  .anchor-cut { display: inline; }
}

.anchor-line.two {
  /* Override the h1 clamp — line 2 is intentionally smaller (52px fixed)
     to sit as a secondary line under the primary statement. Base color
     is ink (black); the last word ("beautiful") flips to orange. */
  font-size: 52px;
  line-height: 1.1;
  margin-top: 0.4em;
  color: var(--ink);
  font-style: italic;
  font-variation-settings: "opsz" 60, "ital" 1, "SOFT" 50, "WONK" 0;
}

/* Word weights: "and clear things" semibold, "beautiful" bold + orange. */
.anchor-line.two .word {
  font-weight: 600; /* semibold */
}
.anchor-line.two .word:last-of-type {
  font-weight: 700;        /* bold — "beautiful" + its trailing period */
  color: var(--orange);
}

.anchor-line em {
  font-style: italic;
  font-variation-settings: "opsz" 144, "ital" 1, "SOFT" 40, "WONK" 0;
}

/* Mobile (<720px) hero fold sizing. The h1 statement stays as-is for now;
   only the secondary type shrinks: the greeting -30%, line two -50%. */
@media (max-width: 720px) {
  .anchor-intro {
    /* clamp resolves to its 20px floor on phones → 20 * 0.7 = 14px */
    font-size: 14px;
  }
  .anchor-line.two {
    /* 52px base → 50% smaller */
    font-size: 26px;
  }
}

/* Cinematic reveal: clip-path wipes the text in from the left (like a
   curtain pull) instead of a plain opacity fade. The negative insets
   on top/right/bottom/left extend the visible area beyond the box,
   which is critical for italic text — descenders and slanted ascenders
   overhang the bounding box and would otherwise crop ("clear" missing
   the r, "beautiful" missing the period, etc). */
.anchor .reveal {
  display: inline-block;
  opacity: 0;
  clip-path: inset(-20% 100% -20% -15%);
  -webkit-clip-path: inset(-20% 100% -20% -15%);
  transform: translateY(8px);
  transition:
    clip-path 700ms cubic-bezier(0.77, 0, 0.175, 1),
    -webkit-clip-path 700ms cubic-bezier(0.77, 0, 0.175, 1),
    opacity 280ms cubic-bezier(0.4, 0, 0.2, 1),
    transform 600ms cubic-bezier(0.34, 1.16, 0.64, 1);
}

.anchor .reveal.is-on {
  opacity: 1;
  clip-path: inset(-20% -15% -20% -15%);
  -webkit-clip-path: inset(-20% -15% -20% -15%);
  transform: translateY(0);
}

/* Letter-by-letter INK reveal (cinematic intro). Any element tagged
   .lettered is shown plainly (no clip-path wipe) and each glyph fades
   opacity 0→100% + blur bleed→sharp, driven by GSAP. Works on line-1 words,
   line-2 words and the greeting alike. */
.lettered {
  opacity: 1 !important;
  clip-path: none !important;
  -webkit-clip-path: none !important;
  transform: none !important;
}
.lettered .ltr {
  display: inline-block;
  opacity: 0;
  filter: blur(6px);            /* ink bleed → sharpens to 0 on reveal */
  white-space: pre;
  will-change: opacity, filter;
}

/* Line 2 — each word wipes in from the left with a hint of vertical
   travel. Same generous insets so italic overhangs don't crop. */
.anchor-line.two .word {
  display: inline-block;
  opacity: 0;
  clip-path: inset(-25% 100% -25% -15%);
  -webkit-clip-path: inset(-25% 100% -25% -15%);
  transform: translateY(12px);
  transition:
    clip-path 600ms cubic-bezier(0.77, 0, 0.175, 1),
    -webkit-clip-path 600ms cubic-bezier(0.77, 0, 0.175, 1),
    opacity 280ms cubic-bezier(0.4, 0, 0.2, 1),
    transform 550ms cubic-bezier(0.34, 1.16, 0.64, 1);
}

.anchor-line.two .word.is-on {
  opacity: 1;
  clip-path: inset(-25% -15% -25% -15%);
  -webkit-clip-path: inset(-25% -15% -25% -15%);
  transform: translateY(0);
}

.anchor .and {
  display: inline-block;
  transition: font-variation-settings 240ms ease-out;
}

.anchor-line.two:hover .and {
  font-variation-settings: "opsz" 144, "ital" 1, "SOFT" 80, "WONK" 1;
}

/* Replace the font glyph with a perfect circle. The `.` character itself
   is pushed off-screen via text-indent so that currentColor still resolves
   correctly from the inherited color, and the background follows it.
   (line 1 no longer has a static period — the spotlight cursor IS the
   period after intro. This rule kept for any future use + line 2's
   two-period if we choose to circle-ify it later.) */
.anchor-line.one .period {
  /* Desktop: the spotlight cursor IS the period after the intro, so the static
     dot stays hidden. Touch devices (no cursor) re-enable it below and the
     intro finale settles the orange protagonist here. */
  display: none;
  width: 0.18em;
  height: 0.18em;
  border-radius: 50%;
  background-color: currentColor;
  overflow: hidden;
  text-indent: 100%;
  white-space: nowrap;
  vertical-align: baseline;
  margin-left: 0.04em;
  transform-origin: 50% 50%;
  color: inherit;
  opacity: 0;
  transition: color 400ms var(--ease-out-emph),
              background-color 400ms var(--ease-out-emph),
              opacity 400ms var(--ease-out-emph);
}
@media (hover: none) {
  .anchor-line.one .period { display: inline-block; }
}
.anchor-line.one .period.is-on { opacity: 1; }

.anchor-line.one .period.is-signed {
  color: var(--orange);
  animation: period-call 600ms ease-out 1 both;
}

@keyframes period-call {
  0% {
    transform: scale(1);
    box-shadow: 0 0 0 rgba(254, 80, 0, 0);
  }
  50% {
    transform: scale(1.18);
    box-shadow: 0 0 22px rgba(254, 80, 0, 0.30);
  }
  100% {
    transform: scale(1);
    box-shadow: 0 0 0 rgba(254, 80, 0, 0);
  }
}

/* ---- Particle word "complex" ---- */
.complex-word {
  position: relative;
  display: inline-block;
  white-space: nowrap;
}

.cw-text {
  display: inline-block;
  color: inherit;
}

.fold-anchor[data-mode="spotlight"] .cw-text {
  color: transparent;
}

.cw-particles {
  /* Full-viewport canvas so particles can scatter across the entire
     screen on abrupt mouse movement — no local clipping. The canvas
     is drawn at viewport-relative coords (no offset math needed). */
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  pointer-events: none;
  opacity: 0;
  transition: opacity 200ms ease-out;
  /* Sits above default layout but below the spotlight reveal (z-index
     9990) so the disc still covers the particles when it passes over. */
  z-index: 5;
}

.fold-anchor[data-mode="spotlight"] .cw-particles {
  opacity: 1;
}

/* ===== Mode 1: SPOTLIGHT ============================================== */

.anchor-back {
  position: fixed;
  inset: 0;
  z-index: 9990;
  pointer-events: none;
  display: none;
}

.anchor-back-disc {
  position: absolute;
  inset: 0;
  background: var(--orange);
}

/* Soft orange halo around the disc — only during the intro choreography,
   where the disc is bigger and benefits from depth. Post-intro the disc
   is just a small 10px cursor and the halo would be noise. */
.fold-anchor.is-intro .anchor-back-disc {
  filter: drop-shadow(0 6px 14px rgba(254, 80, 0, 0.28));
}

/* Line 2 ("And clear things beautiful") is now part of the sentence —
   visible in spotlight mode too. Word-by-word fade-in handled by .word
   opacity rules + intro choreographer. */
.fold-anchor[data-mode="spotlight"] .anchor-back {
  -webkit-mask-image: radial-gradient(circle var(--disc-r) at var(--mx) var(--my), #000 96%, transparent 100%);
  mask-image: radial-gradient(circle var(--disc-r) at var(--mx) var(--my), #000 96%, transparent 100%);
}

/* Post-intro: the cursor stays small (10px ø) at all times. No grow-on-h1
   behavior — the orange spotlight is purely the page cursor now, not a
   reveal mechanic. (Was: clamp(110px, 14vw, 180px) during anchor hover.) */
body.gcursor-on.cur-anchor {
  --disc-r: 10px;
}

/* anchor-back is the global spotlight cursor while activated, AND during
   the intro choreography (so the orange disc shows even on touch devices
   that never set body.gcursor-on). */
body.gcursor-on .fold-anchor[data-mode="spotlight"] .anchor-back { display: block; }
.fold-anchor.is-intro[data-mode="spotlight"] .anchor-back { display: block; }
body.gcursor-on.cur-carousel .fold-anchor[data-mode="spotlight"] .anchor-back { display: none; }

/* Hide the small gcursor element while the intro plays — the WebGL orange
   dot is the only spotlight during the choreography. !important + the
   is-glintro rule below beat the later `body.gcursor-on .gcursor{opacity:1}`
   so a moved mouse can't leak a second orange dot into the scene. */
body.is-intro .gcursor { opacity: 0 !important; }

body {
  --mx: -200px;
  --my: -200px;
  --disc-r: 10px;
}

body.gcursor-on {
  /* enabled — values driven from JS */
}

body.gcursor-on.cur-anchor {
  /* target value computed in JS for smooth tween */
}

/* ---- Spotlight cursor styling ---- */
.fold-anchor[data-mode="spotlight"] { cursor: default; }
.fold-anchor[data-mode="spotlight"] .anchor-line.one .period { cursor: pointer; }
body.gcursor-on,
body.gcursor-on * { cursor: none; }

.anchor-hint {
  opacity: 0;
  pointer-events: none;
  transition: opacity 300ms ease-out;
}

.anchor-hint.is-shown {
  opacity: 1;
}

.anchor-hint.is-hiding {
  opacity: 0;
  transition: opacity 200ms ease-out;
}

@media (hover: none) {
  .anchor-hint {
    opacity: 1;
    transition: none;
  }
}

/* ---- Replay intro button (revealed after intro completes) ---- */
.anchor-replay {
  position: absolute;
  right: clamp(16px, 2vw, 28px);
  bottom: clamp(16px, 2vh, 28px);
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--ink-30, rgba(var(--ink-rgb), 0.18));
  background: transparent;
  color: var(--ink-60, rgba(var(--ink-rgb), 0.55));
  font-size: 16px;
  line-height: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0;
  transition: opacity 320ms ease-out 200ms,
              color 200ms ease-out,
              border-color 200ms ease-out,
              transform 200ms ease-out;
  z-index: 3;
  -webkit-tap-highlight-color: transparent;
}

.anchor-replay[hidden] {
  display: none !important;
}

.anchor-replay.is-shown {
  opacity: 1;
}

.anchor-replay:hover,
.anchor-replay:focus-visible {
  color: var(--orange);
  border-color: var(--orange);
  transform: rotate(-90deg);
  outline: none;
}

/* ---- Intro: physics scene canvases (2D) ---- */
/* Gray "multiplier ball" field sits BEHIND the headline so the text reads
   on top of it as it inks in. */
.intro-balls {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100svh;
  pointer-events: none;
  z-index: 1;             /* behind the headline (.anchor is z-index 2) */
  opacity: 0;             /* JS fades in on intro start, out at handoff */
  transition: opacity 520ms ease-out;
}
/* The orange spotlight-dome sits IN FRONT of the headline so it passes over
   the text, but below the cursor/disc. */
.intro-dome {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100svh;
  pointer-events: none;
  z-index: 9985;
  opacity: 0;
  transition: opacity 520ms ease-out;
}

/* Film grain — subtle moving texture during the intro for cinematic feel.
   Multiply blend darkens the off-white paper just slightly. */
.intro-grain {
  position: fixed;
  inset: -50%;            /* oversized so the drift never reveals an edge */
  pointer-events: none;
  z-index: 9986;
  opacity: 0;
  mix-blend-mode: multiply;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  will-change: opacity, transform;
  display: none;
}
/* Skip control — discreet, bottom-center, only during play */
.intro-skip {
  position: fixed;
  left: 50%;
  bottom: clamp(20px, 4vh, 40px);
  transform: translateX(-50%) translateY(6px);
  z-index: 9992;
  font-family: var(--mono-font, ui-monospace, "SF Mono", Menlo, monospace);
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: lowercase;
  color: var(--ink-50, rgba(var(--ink-rgb), 0.5));
  background: transparent;
  border: 0;
  padding: 8px 10px;
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity 360ms ease-out, color 200ms ease-out, transform 360ms ease-out;
  -webkit-tap-highlight-color: transparent;
}
.intro-skip[hidden] { display: none; }
.intro-skip.is-shown {
  opacity: 1;
  pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}
.intro-skip:hover,
.intro-skip:focus-visible {
  color: var(--orange);
  outline: none;
}
.intro-skip span {
  display: inline-block;
  transition: transform 200ms ease-out;
}
.intro-skip:hover span { transform: translateX(3px); }

/* ============================================================
   Global cursor (orange spotlight follower) + carousel + mobile hold
   ============================================================ */

.gcursor {
  position: fixed;
  top: 0; left: 0;
  width: 20px;
  height: 20px;
  margin: -10px 0 0 -10px;
  border-radius: 50%;
  background: var(--orange);
  pointer-events: none;
  z-index: 9991;
  opacity: 0;
  transform: translate3d(-200px, -200px, 0);
  transition:
    opacity 240ms ease-out,
    width 380ms cubic-bezier(0.16, 1, 0.3, 1),
    height 380ms cubic-bezier(0.16, 1, 0.3, 1),
    margin 380ms cubic-bezier(0.16, 1, 0.3, 1),
    background 240ms ease-out;
  will-change: transform;
  overflow: hidden;
}

body.gcursor-on .gcursor { opacity: 1; }

/* On a job page the cursor dot inherits the job's color (Starry = yellow).
   The .gcursor lives outside .case, so the color is keyed off the
   body's per-screen class. Home keeps the orange identity dot. The base
   `background 240ms` transition makes the orange↔job swap smooth on nav. */
body.on-starry .gcursor { background: var(--starry); }

/* (Removed: cur-anchor used to hide the small dot in favor of the big
   anchor-back disc. Now the cursor stays small at 10px ø regardless of
   hover target, so the gcursor element is always visible.) */

body.gcursor-on.cur-carousel .gcursor {
  width: 240px;
  height: 240px;
  margin: -120px 0 0 -120px;
  background: var(--spotlight-color, var(--starry));
  opacity: 1;
}

/* Dim the spotlight when it passes over title/client text so the type
   underneath stays legible. Higher specificity beats the cur-carousel
   opacity:1 rule above. */
body.gcursor-on .gcursor.is-dimmed,
body.gcursor-on.cur-carousel .gcursor.is-dimmed {
  opacity: 0.5;
}

.gcursor-carousel {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.gcursor-carousel .ci {
  position: absolute;
  inset: 14%;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center;
  opacity: 0;
  transition: opacity 700ms ease-in-out;
}

.gcursor-carousel .ci.is-on { opacity: 1; }

/* Uploaded gallery images fill the disc (vs the contained product PNGs). */
.gcursor-carousel .ci.ci-img {
  inset: 0;
  background-size: cover;
  border-radius: 50%;
}

/* Press-and-hold (mobile only) */
.anchor-hold {
  display: none;
  position: relative;
  margin-top: clamp(28px, 5vh, 44px);
  align-self: flex-start;
  width: 92px;
  height: 92px;
  border-radius: 50%;
  background: var(--orange);
  color: var(--paper);
  border: none;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 4px;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  letter-spacing: 0.06em;
  text-transform: lowercase;
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 160ms ease-out, background 200ms ease-out;
}

.anchor-hold .h-arrow {
  font-size: 18px;
  line-height: 1;
}

.anchor-hold .h-label {
  font-size: 9px;
  line-height: 1.05;
  white-space: nowrap;
}

.anchor-hold:active,
.anchor-hold.is-pressed {
  transform: scale(0.92);
}

@media (hover: none) {
  .anchor-hold { display: inline-flex; }
}

@media (hover: hover) and (pointer: fine) {
  .anchor-hold { display: none; }
}

/* Fullscreen press-hold reveal (mobile) — anchor-back forced visible regardless of gcursor-on */
.fold-anchor[data-mode="spotlight"].is-hold .anchor-back {
  display: block;
  -webkit-mask-image: radial-gradient(circle var(--disc-r) at var(--mx) var(--my), #000 96%, transparent 100%);
  mask-image: radial-gradient(circle var(--disc-r) at var(--mx) var(--my), #000 96%, transparent 100%);
}

.fold-anchor[data-mode="spotlight"].is-hold {
  --disc-r: 130vmax !important;
  --mx: 50% !important;
  --my: 50% !important;
}

.fold-anchor[data-mode="spotlight"].is-hold .anchor-back {
  transition: --disc-r 320ms cubic-bezier(0.83, 0, 0.17, 1);
}

/* Fold 2 — Selected decisions */

.fold-decisions {
  padding: clamp(80px, 14vh, 160px) var(--gutter);
}

.decisions-intro {
  font-family: "Fraunces", Georgia, serif;
  font-size: clamp(18px, 1.9vw, 25px);
  line-height: 1.32;
  letter-spacing: -0.012em;
  color: var(--ink-70);
  max-width: 44ch;
  margin: 12px 0 clamp(40px, 6vh, 64px);
  text-wrap: balance;
}

.decisions {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 0.5px solid var(--hairline);
}

.decision {
  --row-color: var(--ink-50);
  border-bottom: 0.5px solid var(--hairline);
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  gap: clamp(20px, 3vw, 48px);
  align-items: baseline;
  padding: clamp(22px, 2.4vw, 32px) clamp(16px, 2vw, 28px);
  transition: border-color 220ms ease-out;
}

.decision:hover {
  border-bottom-color: rgba(var(--ink-rgb), 0.55);
}

/* Make the whole row clickable. Cursor: pointer only when the gcursor
   spotlight isn't taking over (otherwise the OS pointer would show on
   top of the orange spotlight, doubling cursors). */
body:not(.gcursor-on) .decision[data-carousel] {
  cursor: pointer;
}

/* Hover wash: the work takes on its OWN accent color (the case color that
   travels with the decision — Adendo §05), fading in from the right edge.
   Lives on a ::after pseudo so the row's grid layout and content stay
   untouched. */
.decision[data-carousel] {
  position: relative;
  isolation: isolate;
}

.decision[data-carousel]::after {
  content: "";
  position: absolute;
  /* Gradient extends to the row's full edges — the row's horizontal
     padding keeps the content (dot, num, title, client) inset so the
     dot floats over the gradient with breathing room. */
  inset: 0;
  background: linear-gradient(
    to left,
    color-mix(in srgb, var(--case-row-color, var(--orange)) 24%, transparent) 0%,
    transparent 62%
  );
  opacity: 0;
  pointer-events: none;
  transition: opacity 400ms ease-out;
  z-index: -1;
}

.decision[data-carousel]:hover::after {
  opacity: 1;
}

.decision .num {
  color: var(--row-color);
  transition: color 200ms ease-out;
  font-variant-numeric: tabular-nums;
}

.decision:hover .num {
  color: var(--case-row-color, var(--orange));
}

.decision .decision-title {
  font-size: clamp(20px, 2.4vw, 32px);
  line-height: 1.18;
  letter-spacing: -0.01em;
  font-style: italic;
  font-variation-settings: "opsz" 72, "ital" 1, "SOFT" 35;
  font-weight: 400;
  margin: 0;
  color: var(--ink);
  max-width: 22ch;
}

.decision .client {
  color: var(--ink-50);
  white-space: nowrap;
}

.decision .dot {
  width: 11px;
  height: 11px;
  border-radius: 999px;
  background: var(--case-row-color, var(--hairline));
  display: inline-block;
  align-self: center;
}

.decision.is-locked .decision-title,
.decision.is-locked .client {
  color: var(--ink-50);
  font-style: italic;
  font-variation-settings: "opsz" 72, "ital" 1, "SOFT" 35;
}

.decision a.row-link {
  display: contents;
}

/* Fold 3 — About teaser + email */



.email {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: clamp(13px, 1vw, 15px);
  letter-spacing: 0.02em;
  color: var(--ink);
  transition: color 220ms var(--ease-out-emph);
}

.email:hover {
  color: var(--orange);
}

/* ============================================================
   STARRY case study
   60% = #FFD300 · 30% = ink · 10% = orange
   ============================================================ */

.case {
  /* Entering a job, the accent IS the job's color (Starry = yellow): cursor,
     pagination, eyebrows, fold, outcome, next — everything inherits it. Page
     stays paper (Adendo §05). Trade-off: the job color as TEXT on paper is
     low-contrast — a deliberately quiet accent. */
  --case-color: var(--starry);
  --case-accent: var(--case-color);
  --case-accent-soft: color-mix(in srgb, var(--case-color) 22%, transparent);
  background-color: var(--paper);
  color: var(--ink);
  /* The open animation fills the overlay with the case color; once the page
     settles it dissolves to its resting surface (--paper). */
  transition: background-color 900ms ease-in-out;
}

/* Per-case theme intelligence: paper is the default surface. When the job's
   color has no contrast on paper (e.g. Starry's yellow), the case flips to a
   dark surface so the accent becomes the protagonist. We invert the surface
   and the ink tokens wholesale; the accent (--case-color) is untouched, so it
   now pops. Add `is-dark` to a case whose color fails on paper. */
.case.is-dark {
  --paper: #0F0F0F;            /* surface → near-black */
  --ink: #FAFAF7;              /* text → paper */
  --ink-rgb: 250, 250, 247;    /* in-rule ink hairlines/tints flip light */
  /* --ink-50/70 and --hairline nest var(--ink-rgb) but are declared at :root,
     so they resolve there and don't re-flip — redefine them directly. */
  --ink-50: rgba(250, 250, 247, 0.5);
  --ink-70: rgba(250, 250, 247, 0.7);
  --hairline: rgba(250, 250, 247, 0.15);
}

/* During the case-color flash (open expand / close collapse) the surface IS
   the job color, so text must read on it — force ink dark regardless of the
   case theme. Resolves back to the theme's ink the instant the flash ends. */
.case.is-active.is-collapsed,
.case.is-active.is-expanding,
.case.is-active.morph-target,
.case.is-active.is-collapsing {
  --ink: #0F0F0F;
  --ink-rgb: 15, 15, 15;
  --ink-50: rgba(15, 15, 15, 0.5);
  --ink-70: rgba(15, 15, 15, 0.7);
  --hairline: rgba(15, 15, 15, 0.15);
}

/* Inside a dark case, surfaces painted with the (light) case color still need
   dark text — the can tile and the current thumb are case-color, not page. */
.case.is-dark .beauty-tile.has-can .tile-label,
.case.is-dark .thumb-current .mono {
  color: rgba(15, 15, 15, 0.55);
}

.case.is-dark .thumb-current .thumb-name {
  color: #0F0F0F;
}

/* ============================================================
   Per-case identity — accent color + theme per job.
   Starry keeps the base --case-color (yellow). Each job's accent is its own;
   the theme (dark vs paper) follows the contrast rule via the `is-dark` class
   in markup: yellow / orchid / champagne have no contrast on paper → dark; the
   DEW blue placeholder does → paper (no is-dark). Colors §05 a definir.
   ============================================================ */
#screen-dew   { --case-color: #2D52EE; }   /* cor §05 a definir · royal-blue placeholder · paper theme */
#screen-brisk { --case-color: #E472DE; }   /* cor §05 a definir · orchid placeholder · dark theme */
#screen-fdp   { --case-color: #E4D2B4; }   /* cor §05 a definir · champagne placeholder · dark theme */

/* Cursor inherits each job's color (the .gcursor lives outside the screen). */
body.on-dew   .gcursor { background: #2D52EE; }
body.on-brisk .gcursor { background: #E472DE; }
body.on-fdp   .gcursor { background: #E4D2B4; }

/* DEW's accent (blue placeholder) is dark, so its open/close flash needs LIGHT
   text — overrides the default dark-on-flash (which suits the light accents). */
#screen-dew.is-active.is-collapsed,
#screen-dew.is-active.is-expanding,
#screen-dew.is-active.morph-target,
#screen-dew.is-active.is-collapsing {
  --ink: #FAFAF7;
  --ink-rgb: 250, 250, 247;
  --ink-50: rgba(250, 250, 247, 0.5);
  --ink-70: rgba(250, 250, 247, 0.7);
  --hairline: rgba(250, 250, 247, 0.15);
}

/* Hero — top padding clears the fixed masthead + toolbar (~140px tall) and
   leaves breathing room before the content. */
.case-hero {
  min-height: 100svh;
  padding: clamp(150px, 18vh, 200px) var(--gutter) clamp(32px, 5vh, 64px);
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(28px, 5vh, 52px);
}

/* Decision block (Adendo §01) — paper surface, no image, left-aligned. */
.case-decision {
  position: relative;
  z-index: 4;
  max-width: 760px;
}

.case-eyebrow {
  color: var(--case-accent);
  margin: 0 0 clamp(18px, 2.6vh, 30px);
}

.case-title {
  font-size: clamp(30px, 4.6vw, 72px);
  line-height: 1.06;
  letter-spacing: -0.022em;
  font-style: italic;
  font-variation-settings: "opsz" 144, "ital" 1, "SOFT" 30, "WONK" 0;
  font-weight: 400;
  margin: 0;
  text-wrap: balance;
  max-width: 16ch;
}

/* Stakes line — what was at stake, not the brief (Adendo §01). */
.case-stakes {
  font-size: clamp(16px, 1.5vw, 21px);
  line-height: 1.5;
  font-variation-settings: "opsz" 24, "SOFT" 35;
  color: var(--ink-70);
  max-width: 34ch;
  margin: clamp(20px, 3vh, 32px) 0 0;
}

/* Metadata strip — BRAND · ROLE · OUTCOME. Inline row on desktop; on mobile
   each cell stacks (label over value) so the whole block fits one screen. */
.case-meta {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(14px, 2vh, 20px);
  margin: clamp(28px, 4vh, 44px) 0 0;
}

@media (min-width: 720px) {
  .case-meta {
    grid-template-columns: repeat(3, auto);
    gap: clamp(28px, 5vw, 64px);
    align-items: start;
    justify-content: start;
  }
}

.meta-cell dt {
  color: var(--ink-50);
  margin: 0 0 6px;
}

.meta-cell dd {
  margin: 0;
  font-size: clamp(14px, 1.1vw, 16px);
  line-height: 1.35;
  font-variation-settings: "opsz" 18, "SOFT" 35;
  max-width: 24ch;
}

.meta-outcome {
  color: var(--case-accent);
}

/* The fold — a thin accent rule where the scroll (the reasoning) begins. */
.case-fold {
  height: 0;
  border-top: 1.5px dashed var(--case-accent);
  opacity: 0.85;
  margin-top: clamp(4px, 1.5vh, 16px);
}

@keyframes hero-can-drift {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(-1.2deg); }
  50% { transform: translate3d(0, -10px, 0) rotate(-0.4deg); }
}

/* low-gravity flow — used by the floating chrome stars inside "the beauty" */
@keyframes low-grav {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
  33% { transform: translate3d(10px, -14px, 0) rotate(2deg); }
  66% { transform: translate3d(-8px, 10px, 0) rotate(-1.6deg); }
}

/* Reading rail (sticky lateral right) */
.reading-rail {
  position: fixed;
  top: 50%;
  right: clamp(12px, 2vw, 28px);
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 22px;
  z-index: 6;
  width: 32px;
}

@media (max-width: 720px) {
  .reading-rail {
    display: none;
  }
}

.rail-dots {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  position: relative;
}

.rail-dots::before {
  content: "";
  position: absolute;
  top: 8px;
  bottom: 8px;
  width: 1px;
  background: rgba(var(--ink-rgb), 0.15);
}

.rail-dot {
  display: block;
  width: 9px;
  height: 9px;
  border-radius: 999px;
  background: rgba(var(--ink-rgb), 0.25);
  position: relative;
  z-index: 1;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 220ms ease-out, box-shadow 320ms ease-out;
}

.rail-dot.is-past {
  background: var(--ink);
}

.rail-dot.is-current {
  background-color: var(--case-accent);
  box-shadow: 0 0 0 4px var(--case-accent-soft);
  animation: rail-pulse 3s ease-in-out infinite;
  cursor: default;
  /* Slower transition so it syncs with the 1200ms case bg fade */
  transition: background-color 1200ms ease-in-out,
              box-shadow 1200ms ease-in-out;
}

.rail-dot:not(.is-current):hover {
  background: var(--ink);
}

@keyframes rail-pulse {
  0%, 100% { opacity: 0.85; }
  50% { opacity: 1; }
}

/* Tooltip on hover — chapter name floats to the left of the rail */
.rail-dot::before {
  content: attr(data-chapter);
  position: absolute;
  right: calc(100% + 14px);
  top: 50%;
  transform: translateY(-50%);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: lowercase;
  color: var(--ink);
  background: var(--paper);
  padding: 5px 9px;
  border: 0.5px solid var(--hairline);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 180ms ease-out;
  z-index: 2;
}

.rail-dot:hover::before,
.rail-dot:focus-visible::before {
  opacity: 1;
}

/* Layer 01 — complexity */
.layer-complexity {
  background: transparent;
  padding: clamp(60px, 10vh, 120px) var(--gutter) clamp(60px, 10vh, 120px);
  position: relative;
}

.layer-eyebrow {
  color: var(--case-accent);
  margin: 0 0 clamp(28px, 4vh, 48px);
  transition: color 1200ms ease-in-out;
}

.complexity-intro {
  font-size: clamp(16px, 1.4vw, 19px);
  line-height: 1.65;
  font-variation-settings: "opsz" 18, "SOFT" 35;
  max-width: 44ch;
  margin: 0 0 clamp(60px, 9vh, 100px);
  font-weight: 400;
}

/* Layer 02 — clarity */
.layer-clarity {
  background: transparent;
  padding: clamp(60px, 9vh, 100px) var(--gutter) clamp(80px, 12vh, 140px);
}

/* The page's only pull-quote (Adendo §03). Serif, large, left-aligned;
   weight equal to the work in "the beauty". */
.clarity-quote {
  margin: clamp(40px, 7vh, 80px) 0 0;
  max-width: 24ch;
  font-size: clamp(28px, 4.4vw, 60px);
  line-height: 1.12;
  font-style: italic;
  font-variation-settings: "opsz" 72, "ital" 1, "SOFT" 35;
  letter-spacing: -0.015em;
  font-weight: 400;
  text-wrap: balance;
}

.clarity-quote .period {
  color: var(--case-accent);
}

/* Layer 03 — beauty tile: real can + chrome stars */
.beauty-tile.has-can {
  background: var(--case-color);
  border: 0.5px solid rgba(var(--ink-rgb), 0.18);
  position: relative;
  overflow: hidden;
  aspect-ratio: 4/3;
}

.beauty-can {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%) rotate(-2deg);
  height: 86%;
  width: auto;
  filter: drop-shadow(0 24px 48px rgba(var(--ink-rgb), 0.22));
  animation: hero-can-drift 16s ease-in-out infinite -2s;
  z-index: 2;
}

.beauty-tile .float-star {
  position: absolute;
  pointer-events: none;
  user-select: none;
  z-index: 3;
}

.beauty-tile .float-star img { width: 100%; height: auto; display: block; }

.beauty-tile .float-star.fs-a {
  width: 22%;
  top: 8%;
  left: 6%;
  animation: low-grav 11s ease-in-out infinite;
}

.beauty-tile .float-star.fs-b {
  width: 14%;
  bottom: 14%;
  right: 8%;
  animation: low-grav 13s ease-in-out infinite -5s reverse;
}

.layer-beauty {
  background: transparent;
  padding: clamp(60px, 9vh, 100px) var(--gutter) clamp(80px, 12vh, 140px);
}

.beauty-eyebrow {
  margin: 0 0 clamp(32px, 4vh, 56px);
  color: var(--case-accent);
  transition: color 1200ms ease-in-out;
}

.beauty-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(16px, 2vw, 24px);
  margin-bottom: clamp(40px, 6vh, 72px);
}

@media (min-width: 720px) {
  .beauty-grid {
    grid-template-columns: 1.4fr 1fr;
  }
}

.beauty-tile {
  background: var(--paper);
  border: 0.5px solid rgba(var(--ink-rgb), 0.15);
  aspect-ratio: 4/3;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
}

.beauty-tile .tile-label {
  position: absolute;
  bottom: 14px;
  left: 16px;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.05em;
  color: var(--ink-50);
  text-transform: lowercase;
}

/* Uploaded media gallery — fills the tile; replaces placeholder/art tiles. */
.beauty-tile.media-tile { padding: 0; background: #000; }
.beauty-tile.media-tile .media-el,
.beauty-tile.media-tile .media-play {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
}
.beauty-tile.media-tile img.media-el { object-fit: cover; display: block; }
.beauty-tile.media-tile video.media-el { object-fit: contain; background: #000; }
.beauty-tile.media-tile .media-play {
  border: 0;
  cursor: pointer;
  background: #000;
  display: block;
}
.beauty-tile.media-tile .media-play img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}
.beauty-tile.media-tile .media-play .play-icon {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 30px;
  color: #fff;
  background: rgba(0, 0, 0, 0.18);
  transition: background 0.2s ease;
}
.beauty-tile.media-tile .media-play:hover .play-icon { background: rgba(0, 0, 0, 0.34); }
.beauty-tile.media-tile .tile-label {
  z-index: 2;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 26px 16px 12px;
  color: #fff;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.5));
}

/* Stylized can mock */


.beauty-tile.shelf-row {
  aspect-ratio: 4/3;
  background: var(--paper);
  flex-direction: row;
  justify-content: space-evenly;
  gap: 4%;
  padding: 12% 6%;
}

.shelf-can {
  width: 12%;
  aspect-ratio: 1/2.4;
  border-radius: 8px / 6px;
  border: 0.5px solid rgba(var(--ink-rgb), 0.4);
  position: relative;
}

.shelf-can.s-1 { background: #2EB872; }
.shelf-can.s-2 { background: #66CC33; }
.shelf-can.s-3 { background: var(--starry); border-color: var(--ink); transform: translateY(-6%); }
.shelf-can.s-4 { background: #97D700; }
.shelf-can.s-5 { background: #00A551; }

.shelf-can .shelf-cap {
  position: absolute;
  inset: 0 0 auto 0;
  height: 6%;
  background: rgba(var(--ink-rgb), 0.2);
  border-radius: 8px 8px 0 0;
}

.shelf-can.s-3::after {
  content: "";
  position: absolute;
  inset: 35% 18% auto 18%;
  height: 18%;
  background: var(--ink);
  clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
}

.metrics {
  border-top: 0.5px solid rgba(var(--ink-rgb), 0.3);
  padding-top: clamp(20px, 3vh, 32px);
  display: grid;
  grid-template-columns: 1fr;
  gap: 14px;
}

@media (min-width: 720px) {
  .metrics {
    grid-template-columns: repeat(4, 1fr);
  }
}

.metric {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.metric .m-value {
  font-family: "Fraunces", serif;
  font-size: clamp(28px, 3.4vw, 44px);
  line-height: 1;
  letter-spacing: -0.02em;
  font-variation-settings: "opsz" 72, "SOFT" 30;
  font-weight: 400;
}

.metric .m-label {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 10px;
  letter-spacing: 0.05em;
  text-transform: lowercase;
  color: var(--ink-70);
  line-height: 1.4;
  max-width: 22ch;
}

.case-foot {
  padding: clamp(40px, 6vh, 80px) var(--gutter) clamp(28px, 4vh, 40px);
  display: flex;
  justify-content: space-between;
  border-top: 0.5px solid rgba(var(--ink-rgb), 0.3);
}

/* ============================================================
   Case shell: masthead + toolbar + thumbs strip
   ============================================================ */

.case-masthead {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  padding: clamp(16px, 2.4vh, 28px) var(--gutter) 12px;
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  z-index: 60;
  background-color: color-mix(in srgb, var(--paper) 75%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  transition: background-color 1200ms ease-in-out;
}

.case-masthead .masthead-name {
  font-family: "Fraunces", Georgia, serif;
  font-size: clamp(20px, 2vw, 28px);
  line-height: 1;
  letter-spacing: -0.022em;
  font-style: italic;
  font-variation-settings: "opsz" 36, "ital" 1, "SOFT" 50, "WONK" 0;
  color: var(--ink);
}

.case-masthead .masthead-role {
  color: rgba(var(--ink-rgb), 0.6);
  font-size: clamp(10px, 0.8vw, 12px);
  letter-spacing: 0.08em;
  position: relative;
  display: inline-block;
}

/* Hover swap: tagline morphs from "I make complex things clear." into
   "And clear things beautiful." on hover of the masthead. Both texts have
   the same character count in mono, so the swap is seamless. */
.case-masthead .masthead-role .role-base,
.case-masthead .masthead-role .role-alt {
  display: inline-block;
  transition: opacity 240ms ease-out;
}

.case-masthead .masthead-role .role-alt {
  position: absolute;
  left: 0;
  top: 0;
  opacity: 0;
  white-space: nowrap;
}

.case-masthead .masthead:hover .role-base {
  opacity: 0;
}

.case-masthead .masthead:hover .role-alt {
  opacity: 1;
}

.case-masthead .nav {
  display: flex;
  gap: clamp(12px, 1.6vw, 22px);
  padding-top: 8px;
}

.case-toolbar {
  position: fixed;
  top: clamp(74px, 9vh, 96px);
  left: 0;
  right: 0;
  padding: 12px var(--gutter);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 24px;
  z-index: 59;
  background-color: color-mix(in srgb, var(--paper) 75%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
  backdrop-filter: blur(14px) saturate(140%);
  border-top: 0.5px solid rgba(var(--ink-rgb), 0.25);
  border-bottom: 0.5px solid rgba(var(--ink-rgb), 0.1);
  transition: background-color 1200ms ease-in-out;
}

.case-toolbar > :first-child {
  justify-self: start;
}

.case-toolbar .case-counter {
  text-align: center;
}

/* Counter nav: wraps the 01/06 + prev/next arrows + works dropdown. */
.case-counter-wrap {
  justify-self: center;
  position: relative;
}

.case-counter-bar {
  display: flex;
  align-items: center;
  gap: 6px;
}

.counter-arrow {
  background: none;
  border: none;
  color: var(--ink);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 6px;
  opacity: 0;
  transition: opacity 200ms ease-out, color 200ms ease-out;
  -webkit-tap-highlight-color: transparent;
}

.case-counter-wrap:hover .counter-arrow,
.case-counter-wrap:focus-within .counter-arrow {
  opacity: 1;
}

.counter-arrow:disabled {
  cursor: not-allowed;
  color: var(--ink-50);
}

.counter-arrow:not(:disabled):hover {
  color: var(--case-accent);
}

/* Dropdown — hover-with-intent: requires the user to dwell on the
   counter area for 1s before it appears. Leaving is instant (no delay
   on the out-transition) so the dropdown vanishes immediately when
   the cursor leaves the wrap. */
.case-dropdown {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(8px);
  margin-top: 12px;
  background: var(--paper);
  border: 0.5px solid rgba(var(--ink-rgb), 0.18);
  min-width: 460px;
  max-width: 560px;
  padding: 4px 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 220ms ease-out,
              transform 220ms ease-out,
              visibility 0s linear 220ms;
  z-index: 70;
  box-shadow: 0 18px 36px rgba(var(--ink-rgb), 0.10);
}

.case-counter-wrap:hover .case-dropdown,
.case-counter-wrap:focus-within .case-dropdown {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
  /* 1s dwell before any in-animation starts */
  transition: opacity 220ms ease-out 1000ms,
              transform 220ms ease-out 1000ms,
              visibility 0s linear 1000ms;
}

.case-dropdown-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.case-dropdown-item {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  gap: 18px;
  align-items: baseline;
  padding: 12px 20px;
  border-bottom: 0.5px solid rgba(var(--ink-rgb), 0.08);
  transition: background 180ms ease-out;
}

.case-dropdown-item:last-child {
  border-bottom: none;
}

.case-dropdown-item .num {
  color: var(--ink-50);
  font-variant-numeric: tabular-nums;
}

.case-dropdown-item .dropdown-title {
  font-family: "Fraunces", Georgia, serif;
  font-style: italic;
  font-size: 14px;
  line-height: 1.2;
  margin: 0;
  color: var(--ink);
  font-variation-settings: "opsz" 36, "ital" 1, "SOFT" 35;
  letter-spacing: -0.005em;
}

.case-dropdown-item .client {
  color: var(--ink-50);
  white-space: nowrap;
}

.case-dropdown-item .dot {
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: rgba(var(--ink-rgb), 0.18);
  align-self: center;
}

/* Current row — the job's own color */
.case-dropdown-item.is-current {
  background: color-mix(in srgb, var(--case-accent) 9%, transparent);
}

.case-dropdown-item.is-current .num,
.case-dropdown-item.is-current .client {
  color: var(--case-accent);
}

.case-dropdown-item.is-current .dot {
  background: var(--case-accent);
}

/* Locked rows — non-interactive, gray italic */
.case-dropdown-item.is-locked .dropdown-title,
.case-dropdown-item.is-locked .client {
  color: var(--ink-50);
}

.case-dropdown-item.is-locked .dropdown-title {
  font-style: italic;
}

/* Hover on a non-current, non-locked row (future cases) */
.case-dropdown-item:not(.is-locked):not(.is-current):hover {
  background: rgba(var(--ink-rgb), 0.04);
  cursor: pointer;
}

.case-close {
  color: var(--ink);
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  justify-self: end;
  transition: transform 220ms var(--ease-out-emph);
  -webkit-tap-highlight-color: transparent;
}

.case-close svg {
  width: 24px;
  height: 24px;
  display: block;
}

.case-close:hover {
  transform: rotate(90deg);
}

/* Title morph: the case-title slides + resizes from the row's
   .decision-title position to its natural case-hero position. Base rule
   keeps transition always declared so the morph fires when morph-target
   is removed (forward) or added (reverse). Forward's initial pin uses
   inline style="transition:none" to avoid the natural→row jump. */
.case .case-title {
  transform-origin: top left;
  transition: transform 800ms cubic-bezier(0.83, 0, 0.17, 1),
              font-size 800ms cubic-bezier(0.83, 0, 0.17, 1),
              line-height 800ms cubic-bezier(0.83, 0, 0.17, 1),
              letter-spacing 800ms cubic-bezier(0.83, 0, 0.17, 1),
              font-variation-settings 800ms cubic-bezier(0.83, 0, 0.17, 1),
              /* ease the ink↔paper flip so the dark-case yellow flash doesn't
                 snap the title color mid-dissolve */
              color 700ms ease-in-out;
  will-change: transform;
}

.case.morph-target .case-title {
  transform: translate(var(--title-dx, 0px), var(--title-dy, 0px));
  font-size: clamp(20px, 2.4vw, 32px);
  line-height: 1.18;
  letter-spacing: -0.01em;
  font-variation-settings: "opsz" 72, "ital" 1, "SOFT" 35;
  /* Match .decision-title's wrap width AND wrap mode so the pinned case-title
     has the exact same line breaks as the row's title — otherwise the case
     title (text-wrap: balance) and the row title (normal) break in different
     places and ghost as "two elements" on the way back. */
  max-width: 22ch;
  text-wrap: wrap;
}

/* Decision-block siblings are hidden during the title morph so the pinned
   title sits cleanly in the row strip without other case content peeking in.
   Revealed by case-stage-in after the expansion. */
.case.morph-target .case-eyebrow,
.case.morph-target .case-stakes,
.case.morph-target .case-meta,
.case.morph-target .case-fold {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

/* Sequence footer (Adendo §04) — paper, full width: counter left, next right. */
.case-foot-counter {
  color: var(--ink-50);
}

.case-foot-next {
  color: var(--case-accent);
}

.case-foot-next.is-disabled {
  color: var(--ink-50);
  opacity: 0.6;
  pointer-events: none;
}

/* Thumbs strip at bottom */
.case-thumbs {
  background: var(--paper);
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: clamp(8px, 1.2vw, 18px);
  padding: clamp(16px, 2.4vw, 28px) var(--gutter);
  border-top: 0.5px solid rgba(var(--ink-rgb), 0.2);
}

.thumb {
  aspect-ratio: 4/3;
  background: rgba(var(--ink-rgb), 0.06);
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 12px 14px;
  position: relative;
  border-radius: 2px;
  transition: background 220ms ease-out;
}

.thumb-current {
  background: var(--case-color);
}

.thumb .thumb-name {
  font-family: "Fraunces", Georgia, serif;
  font-style: italic;
  font-variation-settings: "opsz" 36, "ital" 1, "SOFT" 50, "WONK" 0;
  font-size: clamp(13px, 1vw, 16px);
  line-height: 1.1;
  letter-spacing: -0.012em;
  color: var(--ink);
}

/* Forthcoming cases — name reads as a quiet placeholder, not live work. */
.thumb-empty .thumb-name {
  color: var(--ink-50);
}

/* Clickable thumbs — on hover the box fills with the LINKED project's accent
   color (each carries its own --thumb-color / contrast ink, keyed by href so
   no per-thumb markup is needed). */
a.thumb {
  text-decoration: none;
  color: inherit;
  cursor: pointer;
}
a.thumb[href$="/starry"]              { --thumb-color: #FFD300; --thumb-ink: #0F0F0F; }
a.thumb[href$="/mtn-dew-got"]         { --thumb-color: #2D52EE; --thumb-ink: #FAFAF7; } /* cor §05 a definir */
a.thumb[href$="/brisk-black-panther"] { --thumb-color: #E472DE; --thumb-ink: #0F0F0F; } /* cor §05 a definir */
a.thumb[href$="/food-deserves-pepsi"] { --thumb-color: #E4D2B4; --thumb-ink: #0F0F0F; } /* cor §05 a definir */

a.thumb .thumb-name,
a.thumb .mono {
  transition: color 220ms ease-out;
}

a.thumb:hover {
  background: var(--thumb-color, var(--case-color));
}
a.thumb:hover .thumb-name,
a.thumb:hover .mono {
  color: var(--thumb-ink, var(--ink));
}

@media (max-width: 720px) {
  .case-thumbs {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* ============================================================
   Case page open/close animation — clip-path from row strip
   ============================================================ */

.case {
  --row-top: 0px;
  --row-h: 100vh;
}

.case.is-active.is-collapsed {
  clip-path: inset(var(--row-top) 0 calc(100vh - var(--row-top) - var(--row-h)) 0);
  -webkit-clip-path: inset(var(--row-top) 0 calc(100vh - var(--row-top) - var(--row-h)) 0);
  opacity: 0;
  animation: case-overlay-fade-in 280ms ease-out forwards;
  /* Fill with the case color the moment the overlay appears (no fade-in here);
     it dissolves to paper later, when the .case base rule takes over. */
  background-color: var(--case-color);
  transition: none;
}

@keyframes case-overlay-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

.case.is-active.is-expanding {
  clip-path: inset(0 0 0 0);
  -webkit-clip-path: inset(0 0 0 0);
  /* Stay filled with the case color through the expand (no bg change here, so
     the clip-path transition is the only thing animating). */
  background-color: var(--case-color);
  transition: clip-path 1100ms cubic-bezier(0.77, 0, 0.18, 1),
              -webkit-clip-path 1100ms cubic-bezier(0.77, 0, 0.18, 1);
}

/* The way back (reverse of the open). While the title morphs natural → row
   (morph-target, ~800ms), the bg dissolves paper → case color via the .case
   base transition — the mirror of the open's color → paper dissolve. On the
   OPEN this rule is harmless: morph-target there coexists with is-collapsed
   (transition: none), so the fill is instant, and it's dropped at stage-in
   exactly when paper takes over. */
.case.is-active.morph-target {
  background-color: var(--case-color);
}

.case.is-active.is-collapsing {
  clip-path: inset(var(--row-top) 0 calc(100vh - var(--row-top) - var(--row-h)) 0);
  -webkit-clip-path: inset(var(--row-top) 0 calc(100vh - var(--row-top) - var(--row-h)) 0);
  /* Stay filled with the case color through the collapse. */
  background-color: var(--case-color);
  transition: clip-path 1100ms cubic-bezier(0.77, 0, 0.18, 1),
              -webkit-clip-path 1100ms cubic-bezier(0.77, 0, 0.18, 1);
  /* In the last ~280ms of the collapse, fade the whole overlay out so the
     case-color bg and pinned title soften their disappearance. The home row
     text is already visible underneath (z-index keeps the overlay on top from
     t=0), so it "fades in" naturally as the overlay fades out. */
  animation: case-collapse-tail 280ms ease-out 820ms forwards;
}

@keyframes case-collapse-tail {
  from { opacity: 1; }
  to { opacity: 0; }
}

/* Masthead + toolbar fade in after the yellow expansion settles */
.case.is-active.is-collapsed .case-masthead,
.case.is-active.is-collapsed .case-toolbar,
.case.is-active.is-expanding .case-masthead,
.case.is-active.is-expanding .case-toolbar {
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
}

.case .case-masthead,
.case .case-toolbar {
  transition: opacity 360ms ease-out 700ms,
              transform 360ms ease-out 700ms;
}

.case.is-active.is-collapsing .case-masthead,
.case.is-active.is-collapsing .case-toolbar {
  opacity: 0;
  transform: translateY(-8px);
  transition: opacity 220ms ease-out, transform 220ms ease-out;
}

/* ============================================================
   ABOUT
   ============================================================ */

.about {
  background-color: var(--paper);
  /* The contact flow may darken the page (focus) or flash green
     (success); transition the bg so the shift is smooth. */
  transition: background-color 600ms ease-in-out;
}

/* Focus mode: clicking "get in touch" darkens the page so the paper
   form panel reads as a bright focal point. */
.about.is-contact-focus {
  background-color: #0F0F0F;
}

/* Success mode: form submit flashes the bg to a softer celebratory
   green — desaturated so it feels affirming rather than alarming. */
.about.is-contact-success {
  background-color: #5BAD7A;
}

/* Use the case-masthead structure on about, but with a paper-tinted
   backdrop instead of the case's yellow/green surface. */
.about-masthead {
  background-color: color-mix(in srgb, var(--paper) 75%, transparent);
  transition: background-color 600ms ease-in-out;
}

.about.is-contact-focus .about-masthead {
  background-color: color-mix(in srgb, #0F0F0F 75%, transparent);
}

.about.is-contact-focus .masthead-name,
.about.is-contact-focus .role-base,
.about.is-contact-focus .role-alt,
.about.is-contact-focus .about-nav a {
  color: var(--paper);
  transition: color 600ms ease-in-out;
}

.about.is-contact-focus .about-nav-current {
  color: var(--orange);
}

.about.is-contact-success .about-masthead {
  background-color: color-mix(in srgb, #5BAD7A 75%, transparent);
}

/* Orange and green have similar luminance — on the success green bg,
   orange text loses contrast. Flip orange accents to ink while the
   success state is active. The 600ms color transition is declared
   only on the .is-contact-success rule (matches the bg's 600ms fade);
   leaving success falls back to each element's own default transition
   so hover and other interactions stay snappy. */
.about.is-contact-success .about-contact-trigger,
.about.is-contact-success .about-nav-current,
.about.is-contact-success .about-coda .period.is-signed {
  color: var(--ink);
  transition: color 600ms ease-in-out;
}

.about-nav-current {
  color: var(--orange);
}

.about-body {
  max-width: 640px;
  margin: 0 auto;
  padding: clamp(160px, 22vh, 220px) 24px clamp(80px, 14vh, 160px);
}

.about-header {
  margin-bottom: clamp(48px, 8vh, 80px);
}

.about-eyebrow {
  margin: 0 0 clamp(12px, 2vh, 20px);
  color: var(--ink-50);
}

.about-locations {
  margin: clamp(16px, 2vh, 24px) 0 0;
  color: var(--ink-50);
}

.about-title {
  font-size: clamp(40px, 6vw, 80px);
  line-height: 1.04;
  letter-spacing: -0.02em;
  font-style: italic;
  font-variation-settings: "opsz" 96, "ital" 1, "SOFT" 35, "WONK" 0;
  font-weight: 400;
  margin: 0;
}

.about-passages {
  border-top: 0.5px solid var(--hairline);
  padding-top: clamp(40px, 6vh, 64px);
}

.about-passage {
  font-size: clamp(17px, 1.4vw, 20px);
  line-height: 1.7;
  font-variation-settings: "opsz" 18, "SOFT" 35;
  margin: 0 0 clamp(28px, 4vh, 44px);
  text-wrap: pretty;
}

.about-passage em {
  font-style: italic;
  font-variation-settings: "opsz" 18, "ital" 1, "SOFT" 50;
}

.about-coda {
  margin-top: clamp(48px, 7vh, 80px);
  font-size: clamp(18px, 1.6vw, 22px);
  line-height: 1.5;
  font-style: italic;
  font-variation-settings: "opsz" 36, "ital" 1, "SOFT" 40;
  text-wrap: pretty;
}

.about-coda .period {
  transition: color 400ms var(--ease-out-emph);
}

.about-coda .period.is-signed {
  color: var(--orange);
}

/* Contact: "get in touch" trigger + form panel. The panel mirrors the
   case-dropdown component (paper bg, hairline border, soft shadow) but
   is click-to-toggle rather than hover-with-intent — forms need stable
   interaction state. */
.about-contact {
  position: relative;
  margin-top: clamp(48px, 7vh, 80px);
}

.about-contact-trigger {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: clamp(13px, 1.05vw, 16px);
  letter-spacing: 0.04em;
  text-transform: lowercase;
  color: var(--orange);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color 220ms var(--ease-out-emph);
}

.about-contact-trigger:hover,
.about-contact-trigger:focus-visible {
  color: var(--ink);
}

.about-contact-panel {
  margin-top: clamp(16px, 2vh, 24px);
  background: var(--paper);
  border: 0.5px solid rgba(var(--ink-rgb), 0.18);
  box-shadow: 0 18px 36px rgba(var(--ink-rgb), 0.08);
  padding: clamp(24px, 4vh, 36px);
  max-width: 480px;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 220ms ease-out, transform 220ms ease-out;
}

.about-contact-panel[hidden] {
  display: none;
}

.about-contact-panel.is-open {
  opacity: 1;
  transform: translateY(0);
}

.contact-form {
  display: flex;
  flex-direction: column;
  gap: clamp(14px, 2vh, 20px);
}

.contact-form-eyebrow {
  margin: 0 0 clamp(4px, 0.5vh, 8px);
  color: var(--ink-50);
}

.contact-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.contact-row label {
  color: var(--ink-50);
  letter-spacing: 0.04em;
  text-transform: lowercase;
}

.contact-row input,
.contact-row textarea {
  font-family: "Fraunces", Georgia, serif;
  font-size: clamp(15px, 1.2vw, 17px);
  line-height: 1.4;
  font-variation-settings: "opsz" 18, "SOFT" 35;
  color: var(--ink);
  background: transparent;
  border: none;
  border-bottom: 0.5px solid var(--hairline);
  padding: 6px 0;
  outline: none;
  width: 100%;
  resize: none;
  transition: border-color 200ms ease-out;
}

.contact-row textarea {
  font-family: "Fraunces", Georgia, serif;
  resize: vertical;
  min-height: 80px;
}

.contact-row input:focus,
.contact-row textarea:focus {
  border-bottom-color: var(--ink);
}

.contact-row input:invalid:not(:placeholder-shown),
.contact-row textarea:invalid:not(:placeholder-shown) {
  border-bottom-color: var(--orange);
}

.contact-actions {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-top: clamp(8px, 1vh, 12px);
}

.contact-submit {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 12px;
  letter-spacing: 0.06em;
  text-transform: lowercase;
  color: var(--paper);
  background: var(--ink);
  border: none;
  padding: 12px 24px;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background 200ms ease-out;
}

.contact-submit:hover,
.contact-submit:focus-visible {
  background: var(--orange);
}

.contact-submit:disabled,
.contact-submit[disabled] {
  background: var(--ink-50);
  cursor: not-allowed;
  pointer-events: none;
}

.contact-feedback {
  color: var(--ink-50);
}

/* Particle word generic — reusable container for the canvas-rendered
   "complex" and "arc" treatments. */
.particle-word {
  position: relative;
  display: inline-block;
  white-space: nowrap;
}

.particle-word .pw-text {
  display: inline-block;
  color: transparent;
}

.particle-word .pw-canvas {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  pointer-events: none;
  opacity: 1;
  z-index: 5;
}

.about-foot {
  padding: clamp(40px, 6vh, 80px) var(--gutter) clamp(28px, 4vh, 40px);
  display: flex;
  justify-content: space-between;
  border-top: 0.5px solid var(--hairline);
}

/* ============================================================
   Fourth-wall flash — §6.5
   ============================================================ */

.fourth-wall {
  position: fixed;
  bottom: clamp(20px, 4vh, 40px);
  right: clamp(20px, 4vw, 48px);
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: clamp(11px, 0.9vw, 13px);
  letter-spacing: 0.04em;
  text-transform: lowercase;
  color: var(--ink);
  background: var(--paper);
  padding: 10px 14px;
  border: 0.5px solid var(--hairline);
  z-index: 50;
  opacity: 0;
  pointer-events: none;
  transition: opacity 600ms var(--ease-out-emph);
  white-space: nowrap;
  max-width: calc(100vw - 40px);
}

.fourth-wall .yellow { color: var(--starry); background: var(--ink); padding: 1px 5px; }
.fourth-wall .lime { color: var(--lime); background: var(--ink); padding: 1px 5px; }

.fourth-wall.is-on {
  opacity: 1;
}

@media (max-width: 520px) {
  .fourth-wall {
    left: 16px;
    right: 16px;
    white-space: normal;
    text-align: center;
  }
}

/* ============================================================
   Reduced motion
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .anchor .reveal {
    opacity: 1;
    transform: none;
  }
  .fourth-wall {
    display: none;
  }
}

/* ============================================================
   Row-expand transition · home → case (and reverse)
   The clicked row's borders push outward to fill the viewport.
   Neighboring rows fade + translate away (above ↑, below ↓).
   Title-block stays anchored to the row's original position
   during expansion, then settles into the case hero layout.
   ============================================================ */

/* Overlay state: starry sits on top of home during expand/collapse.
   clip-path: inset(0) is the "fully open" state — CRITICAL for the
   collapse to animate, because clip-path won't interpolate from `none`
   to inset(). The is-collapsing rule (higher specificity) overrides
   this with the row-strip inset when applied. */
.screen.is-overlay {
  position: fixed !important;
  inset: 0;
  z-index: 100;
  display: block;
  clip-path: inset(0 0 0 0);
  -webkit-clip-path: inset(0 0 0 0);
}

/* Push-aside: neighboring decision rows fade + translate during launch */
.decisions.is-launching .decision {
  transition: opacity 480ms ease-out,
              transform 700ms cubic-bezier(0.83, 0, 0.17, 1);
}

.decisions.is-launching .decision.is-pushed-up {
  opacity: 0;
  transform: translateY(-32px);
  pointer-events: none;
}

.decisions.is-launching .decision.is-pushed-down {
  opacity: 0;
  transform: translateY(32px);
  pointer-events: none;
}

.decisions.is-launching .decision.is-launching-source {
  /* the source row keeps its layout space; only the content vanishes,
     so the case overlay's pinned title is the only visible identity */
}

/* .row-link has display: contents (so the grid sees its children directly),
   which means opacity on .row-link itself has no rendering effect. Target
   the actual rendered children instead. */

/* Persistent transition on the children — declared OUTSIDE the
   is-launching-source rule so opacity still animates back to 1 when the
   class is removed mid-reverse. */
.decisions.is-launching .decision .num,
.decisions.is-launching .decision .decision-title,
.decisions.is-launching .decision .client,
.decisions.is-launching .decision .dot {
  transition: opacity 240ms ease-out;
}

.decisions.is-launching .decision.is-launching-source .num,
.decisions.is-launching .decision.is-launching-source .decision-title,
.decisions.is-launching .decision.is-launching-source .client,
.decisions.is-launching .decision.is-launching-source .dot {
  opacity: 0;
}

.decisions.is-launching .decision.is-launching-source .row-link {
  pointer-events: none;
}

/* Case content staging — runs after row-expand completes.
   Note: case-title is NOT pre-faded; it morphs in place via transform
   during the expansion. Logos and chapter menu fade in via case-stage-in. */
.case.case-prefade .case-eyebrow,
.case.case-prefade .case-stakes,
.case.case-prefade .case-meta,
.case.case-prefade .case-fold,
.case.case-prefade > section.layer-complexity,
.case.case-prefade > section.layer-clarity,
.case.case-prefade > section.layer-beauty,
.case.case-prefade > .case-thumbs,
.case.case-prefade > .case-masthead,
.case.case-prefade > .case-toolbar,
.case.case-prefade > .reading-rail {
  opacity: 0 !important;
  pointer-events: none;
}

.case.case-stage-in .case-eyebrow { animation: case-fade-in 400ms ease-out 60ms both; }
.case.case-stage-in .case-stakes { animation: case-fade-in 400ms ease-out 160ms both; }
.case.case-stage-in .case-meta { animation: case-fade-in 400ms ease-out 260ms both; }
.case.case-stage-in .case-fold { animation: case-fade-in 400ms ease-out 360ms both; }
.case.case-stage-in > .case-masthead,
.case.case-stage-in > .case-toolbar { animation: case-fade-in 400ms ease-out 220ms both; }
.case.case-stage-in > section.layer-complexity { animation: case-fade-in 500ms ease-out 200ms both; }
.case.case-stage-in > section.layer-clarity { animation: case-fade-in 500ms ease-out 320ms both; }
.case.case-stage-in > section.layer-beauty { animation: case-fade-in 500ms ease-out 440ms both; }
.case.case-stage-in > .case-thumbs { animation: case-fade-in 500ms ease-out 540ms both; }
.case.case-stage-in > .reading-rail { animation: case-fade-in 500ms ease-out 600ms both; }

@keyframes case-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* Reverse: kept as a class hook for potential future use. Currently the
   OUT animation lets the clip-path collapse do all the visual work and
   the case-collapse-tail animation fades the whole overlay at the end. */


/* ============================================================
   Work → work transition — clip-path text wipe
   The origin's hero text un-reveals, the destination page sweeps in over
   it (masking the dark↔paper surface swap), then the new hero text reveals
   with the same left-to-right clip wipe as the home headline (.anchor .reveal).
   ============================================================ */

/* Destination page sweep: the overlay clip-path wipes left → right, carrying
   the new surface + content in over the old page. */
.screen.is-overlay.case-sweep-in {
  clip-path: inset(0 100% 0 0);
  -webkit-clip-path: inset(0 100% 0 0);
}
.screen.is-overlay.case-sweep-in.is-sweeping {
  clip-path: inset(0 0 0 0);
  -webkit-clip-path: inset(0 0 0 0);
  transition: clip-path 540ms cubic-bezier(0.77, 0, 0.18, 1),
              -webkit-clip-path 540ms cubic-bezier(0.77, 0, 0.18, 1);
}

/* Hero text wipe — baseline (revealed) state + transition. The explicit
   clip-path here lets the wipe interpolate (none → inset would not animate). */
.case.is-wiping .case-eyebrow,
.case.is-wiping .case-title,
.case.is-wiping .case-stakes,
.case.is-wiping .case-meta {
  opacity: 1;
  clip-path: inset(-20% -15% -20% -15%);
  -webkit-clip-path: inset(-20% -15% -20% -15%);
  transform: translateY(0);
  transition: clip-path 720ms cubic-bezier(0.77, 0, 0.175, 1),
              -webkit-clip-path 720ms cubic-bezier(0.77, 0, 0.175, 1),
              opacity 300ms ease-out,
              transform 700ms cubic-bezier(0.34, 1.16, 0.64, 1);
}
/* Reveal stagger (enter): eyebrow → title → stakes → meta. */
.case.is-wiping .case-eyebrow { transition-delay: 0ms; }
.case.is-wiping .case-title   { transition-delay: 90ms; }
.case.is-wiping .case-stakes  { transition-delay: 210ms; }
.case.is-wiping .case-meta    { transition-delay: 310ms; }

/* Enter — pre-reveal hidden state (clipped on the right; appears L→R). Set
   instantly so the destination starts hidden, then animates to baseline when
   .case-wipe-in is removed. */
.case.is-wiping.case-wipe-in .case-eyebrow,
.case.is-wiping.case-wipe-in .case-title,
.case.is-wiping.case-wipe-in .case-stakes,
.case.is-wiping.case-wipe-in .case-meta {
  opacity: 0;
  clip-path: inset(-20% 100% -20% -15%);
  -webkit-clip-path: inset(-20% 100% -20% -15%);
  transform: translateY(12px);
  transition: none;
}

/* Exit — origin hero un-reveals left→right: a clean clip wipe with opacity
   held (so it reads as a directional un-reveal, not a fade), mirroring the
   enter reveal's easing. The clip erases from the left edge rightward. */
.case.is-wiping.case-wipe-out .case-eyebrow,
.case.is-wiping.case-wipe-out .case-title,
.case.is-wiping.case-wipe-out .case-stakes,
.case.is-wiping.case-wipe-out .case-meta {
  opacity: 1;
  clip-path: inset(-20% -15% -20% 100%);
  -webkit-clip-path: inset(-20% -15% -20% 100%);
  transform: translateY(0);
  transition: clip-path 460ms cubic-bezier(0.77, 0, 0.175, 1),
              -webkit-clip-path 460ms cubic-bezier(0.77, 0, 0.175, 1);
}
/* Exit stagger — top-down (eyebrow → meta), mirroring the reveal order. */
.case.is-wiping.case-wipe-out .case-eyebrow { transition-delay: 0ms; }
.case.is-wiping.case-wipe-out .case-title   { transition-delay: 70ms; }
.case.is-wiping.case-wipe-out .case-stakes  { transition-delay: 150ms; }
.case.is-wiping.case-wipe-out .case-meta    { transition-delay: 210ms; }


@media (prefers-reduced-motion: reduce) {
  .decisions.is-launching .decision.is-pushed-up,
  .decisions.is-launching .decision.is-pushed-down {
    opacity: 0;
    transform: none;
    transition: none;
  }
  .case.case-prefade,
  .case.case-stage-in{
    opacity: 1 !important;
  }
  .case.case-prefade *,
  .case.case-stage-in *{
    opacity: 1 !important;
    animation: none !important;
    transition: none !important;
  }
}

.asset-starry-can { background-image: url("assets/starry-can.png"); background-repeat: no-repeat; background-position: center; background-size: contain; }
.asset-stars-chrome { background-image: url("assets/stars-chrome.png"); background-repeat: no-repeat; background-position: center; background-size: contain; }
.asset-lime-wedge { background-image: url("assets/lime-wedge.png"); background-repeat: no-repeat; background-position: center; background-size: contain; }
.asset-lime-full { background-image: url("assets/lime-full.png"); background-repeat: no-repeat; background-position: center; background-size: contain; }
.asset-lemon-wedge { background-image: url("assets/lemon-wedge.png"); background-repeat: no-repeat; background-position: center; background-size: contain; }

.asset { display: block; width: 100%; height: 100%; background-repeat: no-repeat; background-position: center; background-size: contain; }
span.beauty-can { position: absolute; left: 50%; top: 50%; height: 86%; width: 70%; aspect-ratio: 960 / 1920; transform: translate(-50%, -50%) rotate(-2deg); filter: drop-shadow(0 24px 48px rgba(var(--ink-rgb), 0.22)); animation: hero-can-drift 16s ease-in-out infinite -2s; z-index: 2; }
