/* "Sticker" style: thick borders, solid offset shadows, buttons that press
   down, springy animations. Colors come from the palette selected below. */
:root {
  --line: 3px solid var(--ink);
  --lift: 0 6px 0 var(--ink);
  --radius: 28px;
  --spring: cubic-bezier(.34, 1.56, .64, 1);
  --font: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --display: "Momo Trust Display", Inter, sans-serif;
  --sombra: color-mix(in srgb, var(--ink) 32%, transparent);
  --suave: color-mix(in srgb, var(--ink) 70%, transparent);
}

/* ---------- Palettes: the switcher sets data-palette on <body> ----------
   --accent:   main accent (star sticker, badges, highlighted words)
   --accent-2: second accent (gradients, details)
   --deep:     dark background behind the mesh (while it loads)
   --ink:      text and borders
   --cream:    page background
   --tint:     tag background                                            */
@property --accent { syntax: "<color>"; inherits: true; initial-value: #eaee1a; }
@property --accent-2 { syntax: "<color>"; inherits: true; initial-value: #8fd14f; }
@property --deep { syntax: "<color>"; inherits: true; initial-value: #0e5a2c; }
@property --ink { syntax: "<color>"; inherits: true; initial-value: #10261a; }
@property --cream { syntax: "<color>"; inherits: true; initial-value: #fbf8e6; }
@property --tint { syntax: "<color>"; inherits: true; initial-value: var(--tint); }

body, body[data-palette="green-yellow"] {
  --accent: #eaee1a; --accent-2: #8fd14f; --deep: #0e5a2c;
  --ink: #10261a; --cream: #fbf8e6; --tint: var(--tint);
}
body[data-palette="purple-blue"] {
  --accent: #b8a4ff; --accent-2: #6ea8fe; --deep: #241a66;
  --ink: #15123a; --cream: #f5f3ff; --tint: #e6e1ff;
}
body[data-palette="pink-orange"] {
  --accent: #ffa3d1; --accent-2: #ffa24c; --deep: #6e1d3c;
  --ink: #2a1020; --cream: #fff5ef; --tint: #ffe3d8;
}
body { transition: --accent .6s, --accent-2 .6s, --deep .6s, --ink .6s, --cream .6s, --tint .6s; }

* { box-sizing: border-box; margin: 0; padding: 0; }
/* overflow-x on <html> (not only <body>) is what stops iOS Safari from making
   the page wider than the screen when the tilted marquee sticks out. */
html { scroll-behavior: smooth; overflow-x: hidden; }
body {
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}
a { color: inherit; text-decoration: none; }
.container { max-width: 1120px; margin: 0 auto; padding: 0 24px; }
.display { font-family: var(--display); font-weight: 400; letter-spacing: -.01em; }

/* ---------- Progress bar and top bar ---------- */
.progress {
  position: fixed; inset: 0 0 auto; height: 4px; z-index: 60;
  background: linear-gradient(90deg, var(--deep), var(--accent-2), var(--accent));
  transform-origin: left; transform: scaleX(0);
}
.topbar {
  position: fixed; inset: 0 0 auto; z-index: 50;
  display: flex; justify-content: space-between; align-items: center;
  margin: 10px 14px; padding: 10px 16px;
  font-weight: 600; font-size: 14px;
  border-radius: 999px;
  color: var(--cream); /* text color never changes, so it can't flicker */
  isolation: isolate;
}
/* The pill background is a separate layer that always exists (with its blur);
   only its opacity animates, which the browser does without repainting. */
.topbar::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  border-radius: inherit; border: var(--line);
  background: color-mix(in srgb, var(--ink) 86%, transparent);
  -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  box-shadow: 0 4px 0 color-mix(in srgb, var(--ink) 60%, transparent);
  opacity: 0; transform: scale(.97);
  transition: opacity .25s ease, transform .35s var(--spring);
  will-change: opacity, transform;
}
.topbar.scrolled::before { opacity: 1; transform: none; }
.brand { display: flex; align-items: center; gap: 10px; font-weight: 800; font-size: 18px; }
.brand-dot {
  width: 26px; height: 26px; border-radius: 8px; border: 2.5px solid var(--cream);
  background: conic-gradient(from 200deg, var(--accent), var(--accent-2), var(--deep), var(--deep), var(--accent));
  animation: girar 8s linear infinite;
}
@keyframes girar { to { rotate: 360deg; } }
.topbar nav { display: flex; gap: 22px; }
.topbar nav a { position: relative; }
.topbar nav a::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -4px; height: 2px;
  background: currentColor; transform: scaleX(0); transform-origin: right;
  transition: transform .3s var(--spring);
}
.topbar nav a:hover::after { transform: scaleX(1); transform-origin: left; }

/* ---------- Hero with mesh ---------- */
.hero {
  position: relative; overflow: hidden;
  min-height: 94vh; padding: 140px 24px 170px;
  display: grid; place-items: center;
  background: var(--deep);
  transition: color .5s;
}
.mesh { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.dots {
  position: absolute; inset: 0; pointer-events: none;
  background-image: radial-gradient(#ffffff38 1.6px, transparent 2px);
  background-size: 24px 24px;
}
.hero-copy { text-shadow: 0 2px 18px color-mix(in srgb, var(--ink) 35%, transparent); position: relative; z-index: 5; text-align: center; max-width: 920px;
  /* Own layer for the scroll fade: Safari then fades the whole block at once
     instead of each button/word separately (which looked choppy). */
  will-change: transform, opacity; }

.lockup { display: inline-flex; align-items: center; gap: 14px; text-align: left; }
.lockup b { display: block; font-size: 24px; line-height: 1; }
.lockup small { display: block; margin-top: 4px; font-size: 14px; font-weight: 600; opacity: .7; }
.avatar {
  width: 74px; height: 74px; flex: none; border-radius: 22px; overflow: hidden;
  border: var(--line); background: var(--cream);
  display: grid; place-items: center; transform: rotate(-6deg);
  box-shadow: 0 0 0 5px #fff, 0 20px 24px -2px var(--sombra);
  transition: transform .5s var(--spring);
}
.avatar:hover { transform: rotate(6deg) scale(1.08); }
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar span { font: 400 30px/1 var(--display); color: var(--ink); }

.hero h1 {
  margin: 22px auto 0; max-width: 11em; text-wrap: balance;
  font-size: clamp(44px, 6.6vw, 96px); line-height: 1.04;
}
.hl, .block h2 span, .closer h2 span {
  color: var(--accent); text-shadow: 0 .05em 0 var(--ink);
  -webkit-text-stroke: 2px var(--ink); paint-order: stroke fill;
}
.tagline { margin: 22px auto 0; max-width: 36em; font-size: 19px; line-height: 1.5; font-weight: 500; }
.ctas { display: flex; justify-content: center; flex-wrap: wrap; gap: 14px; margin-top: 34px; }

.word { display: inline-block; }

/* ---------- Intro (entrance choreography) ----------
   <html> gets .intro-wait while the font and GitHub data load, then
   .intro-play (script.js). Everything below only animates transform/opacity
   (and the individual scale/rotate properties), which the GPU handles, so it
   stays smooth on iPhone. --D delays it all on the first visit, while the
   loading screen opens. */
html { --D: 0s; }
html.first-visit { --D: .5s; }

html.intro-wait :is(.topbar, .lockup, .word, .tagline, .ctas, .palettes, .floater, .burst, .mesh, .dots) { opacity: 0; }

html.intro-play .mesh { animation: mesh-in 1.2s cubic-bezier(.2, .7, .2, 1) both; }
html.intro-play .dots { animation: fade-in 1s ease both calc(var(--D) + .3s); }
html.intro-play .topbar { animation: drop-in .7s var(--spring) both calc(var(--D) + .15s); }
html.intro-play .lockup { animation: pop-up .75s var(--spring) both var(--D); }
html.intro-play .avatar { animation: avatar-in .9s var(--spring) both var(--D); }
html.intro-play .word { animation: pop-up .7s var(--spring) both calc(var(--D) + .2s + var(--i, 0) * 65ms); }
html.intro-play .tagline { animation: pop-up .7s var(--spring) both calc(var(--D) + .55s); }
html.intro-play .ctas { animation: pop-up .7s var(--spring) both calc(var(--D) + .65s); }
html.intro-play .palettes { animation: pop-up .7s var(--spring) both calc(var(--D) + .75s); }
html.intro-play .wave { animation: rise 1s cubic-bezier(.2, .8, .2, 1) both var(--D); }

@keyframes mesh-in { from { opacity: 0; transform: scale(1.15); } to { opacity: 1; transform: none; } }
@keyframes fade-in { from { opacity: 0; } }
@keyframes drop-in { from { opacity: 0; transform: translateY(-18px); } }
@keyframes pop-up {
  from { opacity: 0; transform: translateY(.6em) rotate(5deg) scale(.85); }
  to { opacity: 1; transform: none; }
}
@keyframes avatar-in { from { scale: .3; rotate: -40deg; } to { scale: 1; rotate: 0deg; } }
@keyframes rise { from { translate: 0 40px; } to { translate: 0 0; } }
@keyframes sticker-in {
  0% { opacity: 0; scale: 0; }
  50% { opacity: 1; }
  100% { opacity: 1; scale: 1; }
}
@keyframes burst-in {
  from { opacity: 0; scale: .2; rotate: -200deg; }
  to { opacity: 1; scale: 1; rotate: 0deg; }
}

/* First-visit loading screen */
.intro-curtain { display: none; }
html.first-visit .intro-curtain {
  display: grid; place-items: center;
  position: fixed; inset: 0; z-index: 100; pointer-events: none;
  background: var(--cream);
}
.intro-mark {
  width: 64px; height: 64px; border-radius: 20px; border: 3px solid var(--ink);
  background: conic-gradient(from 200deg, var(--accent), var(--accent-2), var(--deep), var(--deep), var(--accent));
  box-shadow: 0 6px 0 var(--ink);
  animation: mark-wait .9s ease-in-out infinite alternate;
}
html.intro-play .intro-curtain { animation: fade-out .55s ease both .3s; }
html.intro-play .intro-mark { animation: mark-out .8s cubic-bezier(.7, 0, .3, 1) both; }
@keyframes mark-wait { from { transform: rotate(-8deg) scale(.92); } to { transform: rotate(8deg) scale(1.04); } }
@keyframes mark-out {
  0% { transform: rotate(0deg) scale(1); }
  30% { transform: rotate(-20deg) scale(.8); }
  100% { transform: rotate(90deg) scale(24); opacity: 0; }
}
@keyframes fade-out { to { opacity: 0; visibility: hidden; } }

/* All palettes are dark: text on top of the mesh is light */
.hero, .closer { color: var(--cream); }
.lockup small { opacity: .8; }

/* ---------- Palette switcher (segmented control) ---------- */
.palettes {
  position: relative; display: inline-flex; gap: 0; margin-top: 30px;
  padding: 4px; border: var(--line); border-radius: 999px;
  background: #ffffffcc; box-shadow: 0 4px 0 var(--ink);
  color: var(--ink);
}
.palettes button {
  position: relative; z-index: 1;
  padding: 9px 18px; border: 0; background: none; cursor: pointer;
  font: 700 14px/1 var(--font); color: var(--ink);
  transition: color .3s;
}
.palettes button[aria-checked="true"] { color: var(--cream); }
.palettes button { display: inline-flex; align-items: center; gap: 8px; }
.palettes .sw { display: inline-flex; }
.palettes .sw i {
  width: 14px; height: 14px; border-radius: 50%; border: 2px solid var(--ink);
}
.palettes .sw i + i { margin-left: -6px; }
.palettes button[aria-checked="true"] .sw i { border-color: var(--cream); }
.palettes-thumb {
  position: absolute; top: 4px; bottom: 4px; left: 4px; width: 0;
  border-radius: 999px; background: var(--ink);
  transition: transform .45s var(--spring), width .45s var(--spring);
}

/* ---------- "Pop" button ---------- */
.pop {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 15px 24px; border-radius: 999px;
  border: var(--line); background: #fff; color: var(--ink);
  font: 600 16px/1 var(--font); cursor: pointer;
  box-shadow: var(--lift);
  transition: transform .25s var(--spring), box-shadow .25s var(--spring), background-color .3s, translate .3s var(--spring);
}
.pop:hover { transform: translateY(-2px); box-shadow: 0 8px 0 var(--ink); }
.pop:active { transform: translateY(4px); box-shadow: 0 2px 0 var(--ink); }
.pop.dark { background: var(--ink); color: var(--cream); }
.pop.sm { padding: 9px 15px; font-size: 14px; border-width: 2px; box-shadow: 0 3px 0 var(--ink); }
.pop.sm:hover { box-shadow: 0 4px 0 var(--ink); }
.pop.sm:active { box-shadow: 0 1px 0 var(--ink); }

/* ---------- Floating stickers ---------- */
.floaters { position: absolute; inset: 0; z-index: 3; pointer-events: none; }
.floater {
  position: absolute; display: grid; place-items: center;
  width: 68px; height: 68px; border-radius: 50%;
  background: var(--cream); border: var(--line);
  font-size: 30px; color: var(--ink);
  box-shadow: 0 0 0 4px #fff, 0 16px 20px -4px var(--sombra);
  animation: flotar var(--fd, 6s) ease-in-out var(--fdel, 0s) infinite;
  transition: translate .1s linear;
}
html.intro-play .floater {
  animation:
    sticker-in .8s var(--spring) both calc(var(--D) + .85s + var(--n, 0) * 90ms),
    flotar var(--fd, 6s) ease-in-out var(--fdel, 0s) infinite;
}
.floater.pill { width: auto; height: auto; padding: 10px 18px; border-radius: 999px; font: 700 16px/1 var(--font); }
/* --n: entrance order · --fd / --fdel: float duration / offset */
.f1 { top: 18%; left: 8%; rotate: -10deg; --n: 0; }
.f2 { top: 14%; right: 12%; background: var(--accent); --n: 1; --fdel: -2s; --fd: 7s; }
.f3 { top: 58%; left: 5%; rotate: 8deg; --n: 2; --fdel: -4s; }
.f4 { bottom: 18%; left: 9%; --n: 3; --fdel: -1s; --fd: 8s; }
.f5 { top: 40%; right: 6%; rotate: -6deg; background: var(--ink); color: var(--cream); --n: 4; --fdel: -3s; }
@keyframes flotar {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50% { transform: translateY(-16px) rotate(6deg); }
}

/* Star sticker */
.burst {
  position: absolute; z-index: 6; right: 7%; bottom: 130px;
  width: 132px; height: 132px; display: grid; place-items: center;
  border: 0; cursor: pointer; background: var(--accent); color: var(--ink);
  font: 400 19px/1.05 var(--display); text-align: center;
  transform: rotate(12deg);
  filter: drop-shadow(4px 0 #fff) drop-shadow(-4px 0 #fff) drop-shadow(0 4px #fff) drop-shadow(0 -4px #fff) drop-shadow(0 18px 20px var(--sombra));
  clip-path: polygon(50% 0,61% 12%,76% 6%,79% 22%,95% 24%,89% 39%,100% 50%,89% 61%,95% 76%,79% 78%,76% 94%,61% 88%,50% 100%,39% 88%,24% 94%,21% 78%,5% 76%,11% 61%,0 50%,11% 39%,5% 24%,21% 22%,24% 6%,39% 12%);
  transition: transform .4s var(--spring), translate .3s var(--spring);
  animation: latido 3s ease-in-out infinite;
}
html.intro-play .burst {
  animation:
    burst-in .9s var(--spring) both calc(var(--D) + 1.15s),
    latido 3s ease-in-out calc(var(--D) + 2.1s) infinite;
}
.burst:hover { transform: rotate(0deg) scale(1.08); }
@keyframes latido { 0%, 100% { scale: 1; } 50% { scale: 1.05; } }

/* Moving wave.
   A cream block cut by a repeating wave-shaped mask; only the mask position
   moves, driven by Motion.wave() in motion.js (Safari doesn't animate
   mask-position from @keyframes). An SVG twice the screen width sliding
   sideways made Safari split it into tiles and skip some, so it flickered.
   The shape is one seamless period of 1440px. */
.wave {
  position: absolute; left: 0; right: 0; bottom: -1px; height: 80px; z-index: 4;
  background: var(--cream);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 80' preserveAspectRatio='none'%3E%3Cpath d='M0,40 C240,90 480,0 720,30 C960,60 1200,-10 1440,40 L1440,80 L0,80 Z'/%3E%3C/svg%3E") repeat-x 0 0 / 1440px 100%;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1440 80' preserveAspectRatio='none'%3E%3Cpath d='M0,40 C240,90 480,0 720,30 C960,60 1200,-10 1440,40 L1440,80 L0,80 Z'/%3E%3C/svg%3E") repeat-x 0 0 / 1440px 100%;
}

/* ---------- Marquee ---------- */
/* The band is tilted 2°. Drawing it on its own GPU layer (translateZ,
   backface-visibility, will-change) makes Safari and Chrome antialias the
   tilted edges instead of drawing them as a jagged "saw". It's 110vw wide so
   its corners never show on wide screens. Movement is driven by motion.js. */
.marquee {
  position: relative; z-index: 5; overflow: hidden;
  margin: -10px -5vw 0; padding: 16px 0;
  background: var(--ink); color: var(--cream);
  border-block: var(--line);
  transform: rotate(-2deg) translateZ(0);
  -webkit-backface-visibility: hidden; backface-visibility: hidden;
  will-change: transform;
  outline: 1px solid transparent;
}
.marquee-track { display: flex; width: max-content; will-change: transform; }
.marquee-track div { display: flex; align-items: center; flex: none; }
.marquee-track span { font: 400 26px/1 var(--display); padding: 0 22px; white-space: nowrap; }
.marquee-track i { font-style: normal; color: var(--accent); font-size: 20px; }

/* ---------- Stats ---------- */
.stats { display: flex; gap: 18px; flex-wrap: wrap; margin-bottom: 70px; }
.stat {
  flex: 1 1 180px; padding: 22px 24px; border: var(--line); border-radius: 24px;
  background: #fff; box-shadow: var(--lift);
  transition: transform .35s var(--spring);
}
.stat:hover { transform: translateY(-4px) rotate(-1deg); }
.stat.s0 { background: var(--accent); }
.stat.s2 { background: var(--ink); color: var(--cream); }
.stat b { display: block; font: 400 56px/1 var(--display); font-variant-numeric: tabular-nums; }
.stat span { display: block; margin-top: 6px; font-weight: 600; font-size: 15px; opacity: .8; }

/* ---------- Projects ---------- */
.block { padding: 110px 0; }
.section-head {
  display: flex; justify-content: space-between; align-items: end;
  gap: 24px; flex-wrap: wrap; margin-bottom: 40px;
}
.section-head h2 { font-size: clamp(36px, 5vw, 64px); line-height: 1.02; max-width: 9em; }
.section-head h2 span { color: var(--accent); }

.filters { display: flex; gap: 10px; flex-wrap: wrap; }
.chip {
  padding: 9px 16px; border-radius: 999px; cursor: pointer;
  border: 2px solid var(--ink); background: #fff; color: var(--ink);
  font: 600 14px/1 var(--font);
  box-shadow: 0 3px 0 var(--ink);
  transition: transform .2s var(--spring), box-shadow .2s var(--spring), background-color .2s;
}
.chip:hover { transform: translateY(-1px); box-shadow: 0 4px 0 var(--ink); }
.chip.active { background: var(--ink); color: var(--cream); transform: translateY(3px); box-shadow: 0 0 0 var(--ink); }

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(310px, 1fr)); gap: 26px; }

/* Card with 3D tilt */
.card { perspective: 900px; display: flex; }
.card-inner {
  position: relative; flex: 1; isolation: isolate;
  -webkit-backface-visibility: hidden; backface-visibility: hidden;
  display: flex; flex-direction: column; overflow: hidden;
  background: #fff; border: var(--line); border-radius: var(--radius);
  box-shadow: var(--lift);
  transform: rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  transition: transform .5s var(--spring), box-shadow .35s var(--spring);
}
.card.tilting .card-inner { transition: transform .08s linear, box-shadow .35s var(--spring); }
.card:hover .card-inner { box-shadow: 0 10px 0 var(--ink); }
.glare {
  position: absolute; inset: 0; pointer-events: none; opacity: 0;
  border-radius: inherit; /* Safari: keep the glare inside the rounded corners */
  background: radial-gradient(circle at var(--gx, 50%) var(--gy, 50%), #ffffff80, transparent 55%);
  mix-blend-mode: soft-light; transition: opacity .3s;
}
.card:hover .glare { opacity: 1; }

/* Safari doesn't clip transformed children to a rounded parent while the card
   tilts in 3D, so the cover rounds and clips itself. The mask forces WebKit
   to really clip the zooming canvas to these corners. */
.cover {
  position: relative; aspect-ratio: 16 / 9; border-bottom: var(--line); overflow: hidden; background: var(--deep);
  border-radius: calc(var(--radius) - 3px) calc(var(--radius) - 3px) 0 0;
  -webkit-mask-image: -webkit-radial-gradient(white, black);
  mask-image: radial-gradient(white, black);
  isolation: isolate;
}
.cover img, .cover canvas { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .6s var(--spring); }
.card:hover .cover canvas, .card:hover .cover img { transform: scale(1.08); }
.cover-letter {
  position: absolute; inset: 0; display: grid; place-items: center;
  font: 400 72px/1 var(--display); color: var(--cream);
  -webkit-text-stroke: 3px var(--ink); paint-order: stroke fill;
  text-shadow: 0 5px 0 var(--ink);
  transition: transform .5s var(--spring);
}
.card:hover .cover-letter { transform: scale(1.12) rotate(-6deg); }
.badge {
  position: absolute; top: 14px; left: 14px;
  padding: 6px 12px; border-radius: 999px; border: 2px solid var(--ink);
  font-size: 12px; font-weight: 700; box-shadow: 0 3px 0 var(--ink);
}
.badge.published { background: var(--accent); }
.badge.in-progress { background: #fff; }
.badge.upcoming { background: var(--ink); color: var(--cream); }
.badge.in-progress::before {
  content: ""; display: inline-block; width: 7px; height: 7px; margin-right: 6px;
  border-radius: 50%; background: var(--deep); animation: parpadeo 1.2s ease-in-out infinite;
}
@keyframes parpadeo { 50% { opacity: .2; } }

.card-body { padding: 22px 24px 26px; display: flex; flex-direction: column; gap: 12px; flex: 1; }
.card h3 { font: 400 26px/1.1 var(--display); }
.card p { font-size: 15px; line-height: 1.55; color: var(--suave); }
.tags { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; }
.tags li {
  font-size: 12px; font-weight: 600; padding: 4px 10px;
  border-radius: 8px; background: var(--tint); border: 1.5px solid color-mix(in srgb, var(--ink) 20%, transparent);
}
.actions { display: flex; gap: 10px; margin-top: auto; padding-top: 8px; }
.empty { font-weight: 600; opacity: .6; }
.empty a { text-decoration: underline; }
.stars {
  position: absolute; top: 14px; right: 14px;
  padding: 6px 11px; border-radius: 999px; border: 2px solid var(--ink);
  background: var(--cream); font-size: 12px; font-weight: 700;
  box-shadow: 0 3px 0 var(--ink);
}

/* ---------- Closing section ---------- */
.closer {
  position: relative; overflow: hidden; text-align: center;
  margin: 0 24px 24px; padding: 130px 24px;
  border: var(--line); border-radius: 44px; box-shadow: var(--lift);
  background: var(--deep);
  transition: color .5s, opacity .5s, translate .7s var(--spring);
}
.closer-copy { position: relative; z-index: 2; }
.closer h2 { font-size: clamp(40px, 6vw, 84px); line-height: 1.02; }

.footer { padding: 32px 24px 56px; text-align: center; font-size: 13px; opacity: .6; }

/* ---------- Reveal on scroll ---------- */
.reveal { opacity: 0; translate: 0 40px; scale: .97; transition: opacity .5s, translate .8s var(--spring), scale .8s var(--spring); }
.reveal.in { opacity: 1; translate: 0 0; scale: 1; }

@media (max-width: 720px) {
  /* The hero keeps 170px of bottom padding, so stickers placed below that
     line can never touch the buttons or the palette switcher. */
  .burst { width: 92px; height: 92px; font-size: 14px; right: 14px; bottom: 58px; }
  /* Phones: keep stickers out of the title — two small ones in the empty band
     under the top bar, one pill bottom-left next to the "New mesh" star. */
  .floater { width: 46px; height: 46px; font-size: 20px; box-shadow: 0 0 0 3px #fff, 0 10px 14px -4px var(--sombra); }
  .floater.pill { padding: 8px 14px; font-size: 14px; }
  .f3, .f4 { display: none; }
  .f1 { top: 84px; left: 18px; }
  .f2 { top: 80px; right: 20px; }
  .f5 { top: auto; bottom: 96px; right: auto; left: 18px; }
  .topbar nav { display: none; }
  .closer { margin: 0 12px 12px; padding: 90px 20px; border-radius: 32px; }
  .palettes button { padding: 9px 11px; }
  .palettes .txt { display: none; }
}

/* Hero fade on scroll, run by the browser's own scroll engine (scroll-driven
   animations: Safari 26+, Chrome 115+). It's tied to the real scroll position
   on the compositor thread, so it stays smooth during iOS momentum scrolling.
   Browsers without support fall back to Motion.scrollParallax() in JS. */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .hero-copy {
      animation: hero-out linear both;
      animation-timeline: scroll(root block);
      animation-range: 0 90vh;
    }
  }
}
@keyframes hero-out {
  0%, 11% { opacity: 1; transform: translate3d(0, 0, 0); }
  80%, 100% { opacity: 0; }
  100% { transform: translate3d(0, 22vh, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; translate: none; scale: none; }
  *, *::before { animation: none !important; transition: none !important; }
}
