/* =========================================================
   Intro: the egg fills with real loading progress, cracks,
   splits, and a portal opens onto the site.
   ========================================================= */
@property --r { syntax: "<length>"; inherits: false; initial-value: 0px; }
.intro { display: none; }
body.has-intro { overflow: hidden; }
body.has-intro .intro {
  display: flex; position: fixed; inset: 0; z-index: 100; align-items: center; justify-content: center;
  background: radial-gradient(60% 60% at 50% 45%, #151b2c, #07080c 72%);
  -webkit-mask-image: radial-gradient(circle at 50% 46%, transparent calc(var(--r) - 2px), #000 var(--r));
  mask-image: radial-gradient(circle at 50% 46%, transparent calc(var(--r) - 2px), #000 var(--r));
}
.intro-glow { position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(30vmax 30vmax at 50% 45%, rgba(124,92,255,.22), transparent 70%), radial-gradient(22vmax 22vmax at 50% 50%, rgba(61,214,245,.12), transparent 70%);
  animation: introGlow 3.2s ease-in-out infinite; }
@keyframes introGlow { 50% { transform: scale(1.12); opacity: .75; } }
.intro-center { position: relative; display: flex; flex-direction: column; align-items: center; gap: 12px; }
.intro-egg { width: min(190px, 44vw); height: auto; overflow: visible; animation: eggFloat 3s ease-in-out infinite;
  filter: drop-shadow(0 30px 40px rgba(0,0,0,.65)) drop-shadow(0 0 36px rgba(61,214,245,.18)); }
@keyframes eggFloat { 50% { transform: translateY(-8px); } }
.intro-egg .wave { animation: waveMove 2.2s linear infinite; }
.intro-egg .wave-b { animation-duration: 3.6s; animation-direction: reverse; }
@keyframes waveMove { to { transform: translateX(100px); } }
.intro-egg .crack { stroke-dasharray: 240; stroke-dashoffset: 240; opacity: 0; filter: drop-shadow(0 0 5px #43f0a0); }
.intro-egg .half { transform-box: fill-box; transform-origin: center; opacity: 0; }
.intro.crack .intro-egg { animation: eggShake .45s ease-in-out; }
.intro.crack .intro-egg .crack { opacity: 1; stroke-dashoffset: 0; transition: stroke-dashoffset .4s ease-out; }
@keyframes eggShake { 20% { transform: rotate(-6deg); } 40% { transform: rotate(6deg); } 60% { transform: rotate(-4deg); } 80% { transform: rotate(3deg); } }
.intro.split .intro-egg { animation: none; }
.intro.split .intro-egg .whole { opacity: 0; }
.intro.split .half-top { animation: flyTop .85s cubic-bezier(.25,.8,.2,1) forwards; }
.intro.split .half-bottom { animation: flyBottom .85s cubic-bezier(.25,.8,.2,1) forwards; }
@keyframes flyTop { 0% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translate(-8px, -130px) rotate(-24deg); } }
@keyframes flyBottom { 0% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translate(10px, 100px) rotate(12deg); } }
.intro.split .intro-egg .crack { opacity: 0; transition: opacity .2s; }
.burst { position: absolute; left: 50%; top: 38%; width: 24px; height: 24px; border-radius: 50%; pointer-events: none; opacity: 0;
  background: radial-gradient(circle, #fff 0%, rgba(67,240,160,.9) 28%, rgba(61,214,245,.5) 48%, transparent 70%); transform: translate(-50%, -50%) scale(0); }
.intro.split .burst { animation: burst .9s ease-out forwards; }
@keyframes burst { 0% { transform: translate(-50%, -50%) scale(0); opacity: 1; } 55% { opacity: .95; } 100% { transform: translate(-50%, -50%) scale(46); opacity: 0; } }
.intro-pct { font: 700 46px "JetBrains Mono", monospace; letter-spacing: -.04em; background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; min-width: 3.4ch; text-align: center; }
.intro-status { font: 500 13px "JetBrains Mono", monospace; color: var(--muted); min-height: 1.4em; text-align: center; padding: 0 20px; }
.intro-pct, .intro-status { transition: opacity .35s, transform .35s; }
.intro.split .intro-pct, .intro.split .intro-status { opacity: 0; transform: translateY(12px); }
.intro-skip { position: absolute; bottom: 26px; right: 26px; font: 500 12px "JetBrains Mono", monospace; color: var(--muted); background: rgba(255,255,255,.03);
  border: 1px solid var(--line-2); border-radius: 999px; padding: 8px 14px; cursor: pointer; transition: color .2s, border-color .2s, opacity .3s; }
.intro-skip:hover { color: var(--text); border-color: rgba(255,255,255,.3); }
/* The portal used to be a thin outline expanding over empty black — a dead gap before the site caught up.
   Now it's a bright burst of light (the egg's own glow, breaking free) that fills the gap itself, timed so
   the real site is already fully visible well before the flash fades — never an empty circle.
   It lives OUTSIDE #intro on purpose: #intro's own mask cuts a growing transparent hole in itself to reveal
   the site, and a child would have that same hole punched through its fill in lockstep, leaving only the
   thin rim visible. As a sibling in the DOM, this flash is never masked. */
.portal-ring { display: none; position: fixed; left: 50%; top: 46%; width: 0; height: 0; border-radius: 50%;
  transform: translate(-50%, -50%); pointer-events: none; opacity: 0; z-index: 101;
  background: radial-gradient(circle, #fff 0%, rgba(210,225,255,.95) 18%, rgba(160,140,255,.7) 38%, rgba(61,214,245,.4) 60%, transparent 78%);
  box-shadow: 0 0 0 2px rgba(61,214,245,.95), 0 0 70px 20px rgba(124,92,255,.6); }
.intro.portal { animation: portalOpen 1.05s cubic-bezier(.7,0,.25,1) forwards; }
body.entering .portal-ring { display: block; animation: ringOpen 1.05s cubic-bezier(.65,0,.3,1) forwards; }
@keyframes portalOpen { to { --r: 150vmax; } }
@keyframes ringOpen {
  0%   { width: 0; height: 0; opacity: 0; }
  10%  { opacity: 1; }
  50%  { width: 70vmax; height: 70vmax; opacity: .95; }
  100% { width: 320vmax; height: 320vmax; opacity: 0; }
}
.intro.portal .intro-skip { opacity: 0; }

main, .nav { transition: opacity .4s ease, transform .6s cubic-bezier(.2,.8,.2,1), filter .35s ease; }
body.has-intro:not(.entering) main, body.has-intro:not(.entering) .nav { opacity: 0; transform: scale(1.07); filter: blur(8px); }
body.entering main, body.entering .nav { transition-delay: .1s; }

/* First screen: one choreography, in reading order, started while the portal flash is at its brightest
   (or immediately on repeat visits). Eyebrow → the three headline words → lead → form, then Mr. Market's
   card lands with a small bounce: the egg has hatched and the creature arrives last. */
.js .hero-copy > .eyebrow, .js .hero-copy > .lead, .js .hero-copy > .input-card, .js .tape {
  opacity: 0; transform: translateY(16px); transition: opacity .55s ease, transform .7s cubic-bezier(.2,.8,.2,1); }
.js .split-words .w { display: inline-block; opacity: 0; transform: translateY(45%) rotate(4deg); filter: blur(6px);
  transition: opacity .6s ease, transform .75s cubic-bezier(.2,.8,.2,1), filter .6s ease; }
.js .hero > .habitat { opacity: 0; transform: translateY(26px) scale(.93);
  transition: opacity .5s ease .78s, transform .85s cubic-bezier(.34,1.56,.64,1) .78s; }
body.hero-in .hero-copy > .eyebrow, body.hero-in .hero-copy > .lead, body.hero-in .hero-copy > .input-card, body.hero-in .tape,
body.hero-in .split-words .w, body.hero-in .hero > .habitat { opacity: 1; transform: none; filter: none; }
body.hero-in .hero-copy > .eyebrow { transition-delay: 0s; }
body.hero-in .split-words .w:nth-of-type(1) { transition-delay: .1s; }
body.hero-in .split-words .w:nth-of-type(2) { transition-delay: .2s; }
body.hero-in .split-words .w:nth-of-type(3) { transition-delay: .32s; }
body.hero-in .hero-copy > .lead { transition-delay: .48s; }
body.hero-in .hero-copy > .input-card { transition-delay: .6s; }
body.hero-in .tape { transition-delay: .3s; }

/* =========================================================
   Living pets: gaze follows the pointer, boop on click
   ========================================================= */
.pet-stage.interactive { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.pet .gaze { transform: translate(calc(var(--lx, 0) * 1.3px), calc(var(--ly, 0) * 1.3px)); transition: transform .3s ease-out; }
.pet .look { transform: translate(calc(var(--lx, 0) * 2.6px), calc(var(--ly, 0) * 2.6px)); transition: transform .22s ease-out; }
.pet-stage.boop svg { animation: squish .6s cubic-bezier(.3,1.5,.5,1); transform-origin: 50% 88%; }
@keyframes squish { 0% { transform: scale(1, 1); } 25% { transform: scale(1.13, .85); } 55% { transform: scale(.93, 1.09); } 100% { transform: scale(1, 1); } }
.heart { position: absolute; width: 22px; height: 22px; pointer-events: none; z-index: 3; animation: heartUp 1.1s ease-out forwards; }
.heart svg { width: 100%; height: 100%; display: block; filter: drop-shadow(0 0 6px rgba(255,122,154,.7)); }
@keyframes heartUp { 0% { transform: translate(-50%, 0) scale(.3); opacity: 0; } 20% { opacity: 1; } 100% { transform: translate(calc(-50% + var(--dx, 0px)), -110px) scale(1.1) rotate(var(--rot, 0deg)); opacity: 0; } }
.boop-toast { position: absolute; left: 50%; top: 6%; transform: translateX(-50%); font: 600 12px "JetBrains Mono", monospace; color: #ffd1dd;
  background: rgba(255,122,154,.14); border: 1px solid rgba(255,122,154,.4); border-radius: 999px; padding: 4px 10px; pointer-events: none; z-index: 3; animation: toast 1.2s ease forwards; white-space: nowrap; }
@keyframes toast { 0% { opacity: 0; transform: translate(-50%, 6px); } 15%, 75% { opacity: 1; transform: translate(-50%, 0); } 100% { opacity: 0; transform: translate(-50%, -6px); } }

/* eating, evolution */
.pet .chomp { animation: chomp .32s ease-in-out infinite; }
@keyframes chomp { 0%, 100% { transform: scaleY(1); } 50% { transform: scaleY(.25); } }
.pet .crumbs circle { animation: crumb 1s ease-in infinite; }
.pet .crumbs circle:nth-child(2) { animation-delay: .3s; }
.pet .crumbs circle:nth-child(3) { animation-delay: .6s; }
@keyframes crumb { 0% { transform: translateY(-8px); opacity: 0; } 30% { opacity: 1; } 100% { transform: translateY(18px); opacity: 0; } }
.pet .halo { animation: halo 3s ease-in-out infinite; transform-origin: 120px 18px; }
@keyframes halo { 50% { transform: translateY(-4px); } }
.pet .sparkles path { animation: sparkle 2.2s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.pet .sparkles path:nth-child(2) { animation-delay: .7s; }
.pet .sparkles path:nth-child(3) { animation-delay: 1.4s; }
@keyframes sparkle { 0%, 100% { transform: scale(.4); opacity: .2; } 50% { transform: scale(1); opacity: 1; } }
.pet .wobble { animation: eggWob 2.6s ease-in-out infinite; }
@keyframes eggWob { 0%, 100% { transform: rotate(0); } 20% { transform: rotate(-5deg); } 40% { transform: rotate(4deg); } 60% { transform: rotate(-2deg); } }
.pet .peek { animation: peek 4s ease-in-out infinite; }
@keyframes peek { 0%, 40%, 100% { transform: translateX(0); } 55% { transform: translateX(-4px); } 75% { transform: translateX(4px); } }

/* motes behind Mr. Market */
.motes { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; }
.habitat-top, .habitat-inner .pet-stage, .hero-caption, .timeline { position: relative; z-index: 1; }
.habitat-inner .chip-back { z-index: 2; }

/* spotlight + tilt */
.card { position: relative; }
.spot::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0; transition: opacity .35s;
  background: radial-gradient(380px circle at var(--mx, 50%) var(--my, 50%), rgba(124,92,255,.16), transparent 45%); }
.spot:hover::after { opacity: 1; }
.tile { transition: transform .25s ease, border-color .2s; will-change: transform; }
.react, .step, .phase { position: relative; overflow: hidden; }

/* nav: scroll spy + mobile row */
.links a { position: relative; }
.links a::after { content: ""; position: absolute; left: 0; right: 0; bottom: -7px; height: 2px; border-radius: 2px; background: var(--grad); transform: scaleX(0); transition: transform .3s ease; }
.links a.active { color: var(--text); }
.links a.active::after { transform: scaleX(1); }
.nav-mobile a.active { color: var(--text); background: var(--line); }
/* offscreen blocks: freeze looping animations (fx.js toggles this with an IntersectionObserver) */
.anim-off, .anim-off *, .anim-off *::before, .anim-off *::after { animation-play-state: paused !important; }
@media (prefers-reduced-motion: reduce) {
  .intro { display: none !important; }
  .js .split-words .w, .js .hero-copy > .eyebrow, .js .hero-copy > .lead, .js .hero-copy > .input-card, .js .tape, .js .hero > .habitat { opacity: 1; transform: none; filter: none; transition: none; }
  .motes { display: none; }
}
