/* ============================================================================
   Sweepy — product page styles
   Part of tinyyy studio. The design system (tokens, themes, brand letters,
   motion primitives, language toggle, footer, theme pill) is the studio's
   shared.css, hot-linked from https://tinyyy.studio/shared.css before this
   file so the two pages feel like one place; only the Sweepy-specific styles
   follow.
   ============================================================================ */

/* 0. Self-hosted fonts (SIL OFL) --------------------------------------------- */
/* Declared here (loaded after the hot-linked shared.css) against this site's
   own /fonts, so Sweepy never fetches fonts cross-origin from tinyyy.studio.
   Same families/weights as the studio — no third-party requests. */
@font-face { font-family: 'Schibsted Grotesk'; font-style: normal; font-weight: 400; font-display: swap; src: url('fonts/schibsted-grotesk-400.woff2') format('woff2'); }
@font-face { font-family: 'Schibsted Grotesk'; font-style: normal; font-weight: 500; font-display: swap; src: url('fonts/schibsted-grotesk-500.woff2') format('woff2'); }
@font-face { font-family: 'Schibsted Grotesk'; font-style: normal; font-weight: 700; font-display: swap; src: url('fonts/schibsted-grotesk-700.woff2') format('woff2'); }
@font-face { font-family: 'Bricolage Grotesque'; font-style: normal; font-weight: 600; font-display: swap; src: url('fonts/bricolage-grotesque-600.woff2') format('woff2'); }
@font-face { font-family: 'Bricolage Grotesque'; font-style: normal; font-weight: 700; font-display: swap; src: url('fonts/bricolage-grotesque-700.woff2') format('woff2'); }
@font-face { font-family: 'Bricolage Grotesque'; font-style: normal; font-weight: 800; font-display: swap; src: url('fonts/bricolage-grotesque-800.woff2') format('woff2'); }
@font-face { font-family: 'Caveat'; font-style: normal; font-weight: 400; font-display: swap; src: url('fonts/caveat-400.woff2') format('woff2'); }
@font-face { font-family: 'Caveat'; font-style: normal; font-weight: 600; font-display: swap; src: url('fonts/caveat-600.woff2') format('woff2'); }

/* 1. Page metrics (narrower rail than the studio) ----------------------------- */

:root {
  --page-max: 1040px;
  --page-pad: 32px;
  --nav-blur-h: 148px;   /* ~1.47x the 101px header; see shared.css §7 */
  /* Capped viewport-height unit for the hero + guided-tour system. Every vertical
     metric that spaces the folder, veil and copy is expressed as calc(N * var(--vph))
     instead of Nvh, so on very tall monitors the hero stops growing (it would
     otherwise float, lost, in a sea of whitespace) and the sections below peek in.
     min(1vh, 8.5px) == the layout an 850px-tall viewport would get, frozen above
     that. Below 850px it's exactly 1vh, so shorter screens are unchanged. app.js
     caps its own `vh` at the same 850px so the scroll choreography stays in sync. */
  --vph: min(1vh, 8.5px);
}

/* 2. Header ------------------------------------------------------------------ */

/* The header sticks so the compact Download CTA survives the scroll-locked tour.
   position:sticky always opens its own stacking context, so a z-index on a
   descendant (e.g. the button) can never escape it to out-rank a LATER sibling
   stacking context (.routine is also sticky) — that fight is decided by the
   header's OWN z-index. It needs one above both the notch overlay (200) and
   any later sticky/positioned section, or the header gets painted over and
   the Download button disappears once the page scrolls far enough. */
.site-header {
  position: sticky; top: 0; z-index: 220;
  max-width: 1040px; margin: 0 auto;
  display: flex; justify-content: space-between; align-items: center;
  padding: 26px 32px;
  transition: opacity .3s ease;
}

/* The expanded toast is centered and min(560px, 62vw) wide; its artwork stops ~4%
   short of each canvas edge, so it paints out to center ± .46 * that width. The
   header's actions are pinned --page-pad in from the right of a --page-max rail,
   which stops widening once the rail caps out at 1040px. Run the two together and
   the gap between the Download button and the toast is zero at ~988px, opens to
   its full 27px at 1040px, and stays there forever after — so 1040px is the first
   width where the tour and the header can share the top of the screen (below it
   the button's drop shadow washes over the toast well before they truly touch).
   Under that, the header steps aside for as long as the toast is out: app.js flags
   it with .tour-busy, and this decides whether the flag costs it its place. Wide
   viewports keep the Download CTA pinned through the whole tour, as intended. */
@media (max-width: 1040px) {
  .site-header.tour-busy { opacity: 0; pointer-events: none; }
}

.header-actions { display: flex; align-items: center; gap: 16px; }
/* Compact variant of .download-btn for the header rail */
.download-btn-mini {
  position: relative;
  flex-direction: row; padding: 8px 16px; border-radius: 10px;
  font-size: 13px; box-shadow: 0 4px 12px rgba(0, 0, 0, .14);
}
.brand-nav { font-family: var(--font-display); font-weight: 800; font-size: 21px; letter-spacing: -0.5px; }

/* Back-to-the-studio affordance: an arrow slides in from the left on hover
   (the header wordmark drops the studio's 🤏 pinch; the footer keeps it). */
.brand-back .yyy-pinch { display: none; }
.back-arrow {
  display: inline-block; max-width: 0; opacity: 0; overflow: hidden;
  transform: translateX(4px); font-weight: 700; color: var(--muted);
  transition: all .35s cubic-bezier(.34, 1.8, .5, 1);
}
.brand-back:hover .back-arrow { max-width: 1.2em; opacity: 1; transform: translateX(0); margin-right: 6px; }

/* 3. Section headers ----------------------------------------------------------- */

.section-head { text-align: center; margin-bottom: 40px; }
.section-head h2 {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(30px, 5vw, 44px); letter-spacing: -1.4px; margin: 0 0 6px;
}
.section-head p { font-size: 15px; color: var(--muted); margin: 0; }
/* An optional framing line under a section subtitle (the routine's "why"):
   a touch larger than the subtitle, kept to a comfortable reading measure. */
.section-head .routine-intro {
  max-width: 600px; margin: 16px auto 0;
  font-size: 16px; line-height: 1.6; color: var(--muted);
}

/* 4. Hero — a drop stage + a fixed top notch overlay ------------------------- */

/* Notch notification: fixed at the very top of the viewport (over the header),
   half-scale and centered. app.js scrubs the frames as the page scrolls and
   fades the whole overlay out once the lifecycle finishes. */
.notch-overlay {
  position: fixed; top: 0; left: 50%; transform: translateX(-50%);
  width: min(560px, 62vw); z-index: 200;
  pointer-events: none; will-change: transform;
}
.notch-canvas {
  display: block; width: 100%; height: auto; aspect-ratio: 2680 / 580;
}

/* The hero section is just the scrolling copy now — the folder and the dissolve
   veil are fixed overlays (below), so the copy and the whole page scroll up
   behind them. Its natural height gives the copy its scroll distance. */
.hero-scroll { position: relative; max-width: none; margin: 0; padding: 0; }

/* Fixed dissolve veil: a page-colored curtain that feathers to transparent just
   below the folder. Content scrolling up behind it fades into the background. It
   stays put for the whole tour (JS fades it out at the very end). */
.hero-veil {
  position: fixed; left: 0; right: 0; top: 0; height: calc(64 * var(--vph));
  background: linear-gradient(to bottom, var(--bg) 0, var(--bg) 74%, transparent 100%);
  pointer-events: none; z-index: 4; will-change: transform;
}
/* Progressive blur, co-located with the veil's feather. Three fixed bands the
   SAME height as the veil, so their mask percentages line up with the gradient's
   stops. Each band is solid (#000) from the top down to the veil's opaque edge
   (74%), then fades to transparent lower down — so the blur is strongest right at
   the opaque edge and tapers to crisp below, and NEVER un-blurs before the veil
   hides it. Staggered fade-out points make the blur compound toward the top:
   band 1 spans the whole feather (light), band 3 only its top sliver (heavy).
   They sit behind the veil (z 3 < 4), so its opaque upper part hides them and
   they only read where the curtain is going transparent. */
.veil-blur {
  position: fixed; left: 0; right: 0; top: 0; height: calc(64 * var(--vph));
  pointer-events: none; z-index: 3; will-change: transform;
}
.veil-blur-1 {
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 74%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 0%, #000 74%, transparent 100%);
}
.veil-blur-2 {
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 74%, transparent 89%);
          mask-image: linear-gradient(to bottom, #000 0%, #000 74%, transparent 89%);
}
.veil-blur-3 {
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 74%, transparent 83%);
          mask-image: linear-gradient(to bottom, #000 0%, #000 74%, transparent 83%);
}

/* The folder: fixed and centered while the file drops, then app.js scrolls it (and
   the veil) up toward the explainer, holds it for the beats, and finally scrolls it
   off the top — all via a shared translateY. Content scrolls up behind it. */
.hero-focus {
  position: fixed; left: 0; right: 0; top: 0; height: calc(100 * var(--vph));
  display: flex; align-items: center; justify-content: center;
  padding-bottom: calc(8 * var(--vph));       /* nudge the folder just above center */
  pointer-events: none; z-index: 6; will-change: transform;
}

/* The scrolling copy — sits below the veil at rest, scrolls up into it. The big
   top padding drops it below the folder/veil so the whole hero reads at rest. */
.hero-stage {
  display: flex; flex-direction: column; align-items: center;
  gap: clamp(12px, 2.4vh, 22px);
  padding: calc(54 * var(--vph)) 32px clamp(40px, calc(8 * var(--vph)), 80px);
  text-align: center;
}

/* Folder + dropping file, layered back → front:
   app icon (back) · the file · folder front. The file's z-index sits between
   back and front, so it slides "into" the folder as it descends. */
.hero-drop {
  position: relative; z-index: 5;
  width: clamp(186px, 22vw, 248px); aspect-ratio: 1 / 1;
  animation: heroFadeIn .8s ease both;      /* opacity only — safe with JS transforms */
}
@keyframes heroFadeIn { from { opacity: 0; } to { opacity: 1; } }

/* Blue highlight behind the folder: two overlapping circles (a deeper blue
   upper-left, a lighter blue lower-right) under one big blur, so they read as a
   soft glow. The group is sized/anchored to the folder box (inset:0); app.js
   scales it down about its centre as the file drops, so the glow shrinks from a
   wide wash to a small halo but stays put behind the folder. */
.hero-glow {
  position: absolute; inset: 0; z-index: 0;
  transform-origin: 50% 50%;                 /* JS overrides transform to shrink it */
  filter: blur(var(--glow-blur, 100px));
  will-change: transform; pointer-events: none;
}
.hero-glow-a,
.hero-glow-b { position: absolute; border-radius: 50%; }
.hero-glow-a { left: -95%; top: -33%; width: 230%; height: 135%; background: #0086FF; }
.hero-glow-b { left: -5%;  top: 6%;   width: 200%; height: 125%; background: #7FBBFF; }

/* Both folder layers share the same size + position so they overlay exactly:
   the app icon (with its folder) sits behind, the bare folder front sits in
   front, both scaled down 25% and tucked into the pocket, with the file between
   them so it reads as dropped inside the folder. */
.folder-back,
.folder-front {
  position: absolute;
  left: 50%; top: 15%;
  width: 65%; height: auto;
  transform: translateX(-50%);
}
.folder-back { z-index: 1; filter: drop-shadow(0 16px 30px rgba(0, 0, 0, .16)); }
.folder-front { z-index: 3; }

/* The file rests deep between the two layers, only a sliver of its top peeking
   above the folder's front rim (~32% down the box). It rests 20% larger than its
   natural size (scale 1.2) and pops in from 30% larger (scale 1.3).
   app.js scrubs its transform from translate3d(0,-travel,0) rotate(-12deg) scale(1.3)
   → scale(1.2). */
.drop-file {
  position: absolute; z-index: 2; left: 50.5%; top: 25%;
  width: 46%; height: auto; margin-left: -23%;
  transform: translate3d(0, -200px, 0) rotate(-12deg) scale(1.3);   /* pre-JS start pose (JS refines) */
  transform-origin: 50% 70%;
  filter: drop-shadow(0 9px 15px rgba(0, 0, 0, .16));
  will-change: transform;
}

/* The hero copy. No mask or transform — it simply scrolls up behind the fixed
   folder and dissolves into the veil above. Sits below the veil (z 4) so it stays
   crisp and clickable at rest, then passes behind it on scroll. */
.hero-copy { max-width: 640px; margin: 0 auto; }

/* Hero type is scoped down inside the pinned stage so folder + copy fit one
   viewport (the un-pinned page keeps the larger display sizes). */
.hero-stage .hero-name { font-size: clamp(40px, 6.8vw, 72px); margin-bottom: 12px; }
.hero-stage .hero-tagline { font-size: clamp(15px, 1.9vw, 18px); max-width: 520px; margin-bottom: 18px; }
.hero-stage .hero-cta { gap: 10px; }
.hero-stage .hero-ethos { font-size: 19px; margin-top: 14px; }

@media (max-height: 760px) {
  .hero-drop { width: clamp(158px, 18vw, 196px); }
  .hero-stage .hero-name { font-size: clamp(34px, 5.4vw, 54px); }
  .hero-stage .hero-tagline { margin-bottom: 12px; }
  .hero-stage .hero-ethos { margin-top: 8px; }
}

/* The base display sizes (used when hero copy is not inside the pinned stage) */
.hero-name {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(60px, 12vw, 104px); line-height: 1; letter-spacing: -2px;
  margin: 0 0 20px;
  display: flex; flex-direction: column; align-items: center;
}
/* Two-line name lockup: a small "tinyyy" sits almost touching a large "sweep",
   both plain --ink (no tri-color y's, no muted grey) — sized in em so the two
   responsive overrides above (which only set .hero-name's own font-size) keep
   scaling both lines together. */
.hero-name-sub { font-size: .4em; line-height: 1; }
.hero-name-main { font-size: 1em; line-height: .76; margin-top: -.12em; }

.hero-tagline {
  font-size: clamp(17px, 2.4vw, 21px); line-height: 1.55; color: var(--muted);
  max-width: 560px; margin: 0 auto 34px;
}

.hero-cta { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.download-btn {
  display: inline-flex; flex-direction: column; align-items: center; gap: 0;
  background: var(--ink); color: var(--btnfg); font-weight: 700; font-size: 15.5px;
  padding: 15px 30px; border-radius: 14px; cursor: pointer; text-decoration: none;
  box-shadow: 0 8px 22px rgba(0, 0, 0, .16); font-family: var(--font-body);
}
/* The macOS requirement can tuck inside the button and unfurl a beat below the
   label on hover/focus (used on the closing CTA, where no static meta line sits
   underneath). Collapsed it adds no height, so buttons without it are unchanged. */
.download-btn-sub {
  max-height: 0; opacity: 0; overflow: hidden;
  font-size: 11.5px; font-weight: 600; letter-spacing: -0.1px;
  transition: max-height .28s ease, opacity .28s ease, margin-top .28s ease;
}
.download-btn:hover .download-btn-sub,
.download-btn:focus-visible .download-btn-sub {
  max-height: 1.4em; opacity: .78; margin-top: 3px;
}
.hero-meta { font-size: 13px; color: var(--muted2); margin: 0; }

/* Price line: a little trial badge, then the one-time price. The buy-once
   ethos below carries the "keep forever" part, so this stays short. */
.hero-price {
  display: inline-flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 10px; margin: 0; font-size: 14.5px;
}
.trial-badge {
  font-weight: 700; font-size: 12.5px; padding: 5px 12px; border-radius: 99px;
  border: 1.5px solid var(--y); color: var(--y); letter-spacing: -0.1px;
}
.price-amount { font-weight: 700; color: var(--ink); }

.hero-ethos {
  font-family: var(--font-hand); font-size: 21px; font-weight: 600;
  color: var(--muted); margin: 26px 0 0;
}

/* 5. Guided tour — captions + hand-drawn arrows below the notch ---------------- */

/* Everything is positioned in the notch overlay's own box (percent coordinates),
   so arrows keep pointing at the right toast buttons at any overlay width.
   Measured anchors (fractions of the frame): Mark temporary 0.306 · Move 0.524 ·
   countdown ring 0.886 · toast bottom edge 85.6% of the canvas height. */
.tour-captions {
  position: absolute; left: 0; right: 0; top: 0; height: 100%;
  pointer-events: none;
  --toast-bottom: 85.6%;
}
/* Discrete, self-timed caption swaps: app.js flips .is-active the moment scroll
   crosses a beat boundary and CSS times the cross-fade on its own clock — so a fast
   scrub can never freeze two half-faded captions on top of each other. */
.tour-beat {
  position: absolute; inset: 0;
  opacity: 0; visibility: hidden; transform: translateY(10px);
  transition: opacity .3s ease, transform .3s ease, visibility 0s linear .3s;
}
.tour-beat.is-active {
  opacity: 1; visibility: visible; transform: none;
  transition: opacity .3s ease, transform .3s ease;
}
.tour-cap {
  position: absolute; top: calc(var(--toast-bottom) + 62px);
  left: 50%; transform: translateX(-50%);
  margin: 0; width: max-content; max-width: min(78vw, 470px);
  font-family: var(--font-hand); font-weight: 600;
  font-size: clamp(17px, 2.3vw, 22px); line-height: 1.3;
  color: var(--ink); text-align: center; text-wrap: balance;
}
/* Beats 1-2 carry no arrow, so the caption tucks up close under the toast
   (nearer the notch/video) instead of leaving arrow room below it. */
.tour-beat[data-beat="b1"] .tour-cap,
.tour-beat[data-beat="b2"] .tour-cap { top: calc(var(--toast-bottom) + 18px); }
.tour-arrow {
  position: absolute; top: calc(var(--toast-bottom) + 6px);
  width: clamp(36px, 10.5%, 56px); height: auto;
}
/* The artwork's head tip sits at (13%, 11%) of its own box; translate(-13%, -11%)
   plants the tip exactly on the left/top anchor. Tweak rotate() to taste. */
.arrow-temp { left: 30.6%; transform: translate(-13%, -11%) rotate(-8deg); }
.arrow-move { left: 52.4%; transform: translate(-13%, -11%) rotate(8deg); }
/* Flipped to point up-right at the ring; the tip lands at 87% of its own width */
.arrow-ring { left: 88.6%; transform: translate(-87%, -11%) scaleX(-1); }

/* Spanish toast buttons ("Temporal/Mover/Más") are narrower and sit further left
   than the English ones, so the anchors shift. Measured on es f0090 (frame_91):
   Temporal 0.255 · Mover 0.438 · countdown ring 0.891. Only left changes. */
html[lang="es-419"] .arrow-temp { left: 25.5%; }
html[lang="es-419"] .arrow-move { left: 43.8%; }
html[lang="es-419"] .arrow-ring { left: 89.1%; }

/* "the quiet routine" scrolls up in sync with the folder, pins just below the risen
   veil for the beats, then releases to scroll away with it. app.js sets the wrapper's
   top margin (to line the pin-start up with the folder's rise) and its height (natural
   height + hold distance), and refines the sticky top from CONFIG. */
.routine-pin { position: relative; }
.routine { position: sticky; top: calc(52 * var(--vph)); }   /* vh-relative; JS refines (baseline − riseDist) */

/* Static tour for reduced motion (shown by the media block below) */
.tour-static { display: none; max-width: 720px; margin: 0 auto; padding: 8px 32px 44px; text-align: center; }
.tour-static-title {
  font-family: var(--font-display); font-weight: 800;
  font-size: clamp(24px, 4vw, 34px); letter-spacing: -1px; margin: 0 0 18px;
}
.tour-static-toast { width: min(560px, 86vw); height: auto; }
.tour-static-list {
  margin: 20px auto 0; padding: 0 0 0 1.5em; max-width: 460px;
  text-align: left; display: grid; gap: 10px;
  font-size: 15px; line-height: 1.55; color: var(--muted);
}

/* 6. The quiet routine ------------------------------------------------------- */

.routine { max-width: 1040px; margin: 0 auto; padding: 54px 32px; }
.beats {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 30px;
}
.beat {
  position: relative; text-align: center;
  display: flex; flex-direction: column; align-items: center;
  padding: 30px 22px 32px; background: var(--card); border-radius: 22px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .06);
}
.beat-num {
  position: absolute; top: 8px; right: 18px;
  font-family: var(--font-display); font-weight: 800; font-size: 62px;
  line-height: 1; color: var(--ink); opacity: .07; z-index: 0; pointer-events: none;
}
.beat-blob {
  position: relative; z-index: 1; flex: none;
  width: 62px; height: 62px; margin-bottom: 18px;
  display: flex; align-items: center; justify-content: center;
}
.beat-blob svg { width: 30px; height: 30px; }
.beat h3 {
  position: relative; z-index: 1;
  font-family: var(--font-display); font-weight: 800; font-size: 21px;
  letter-spacing: -0.4px; margin: 0 0 8px;
}
.beat p { font-size: 14px; line-height: 1.6; color: var(--muted); margin: 0; max-width: 260px; }
.beat p kbd {
  display: inline-block; font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 11.5px; font-weight: 700; line-height: 1; color: var(--ink);
  padding: 3px 6px; margin: 0 1px; border-radius: 6px; vertical-align: -1px;
  background: var(--panel); border: 1px solid var(--line); border-bottom-width: 2px;
}

/* 6b. Screenshots ------------------------------------------------------------ */

/* Full-width like .routine / .features so the shots sit in line with the rest. */
.shots { max-width: 1040px; margin: 0 auto; padding: 44px 32px 40px; }
.shots-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; }
.shot { margin: 0; }
.shot img {
  display: block; width: 100%; height: auto;
  border-radius: 18px; border: 1px solid var(--line);
  box-shadow: 0 4px 16px rgba(0, 0, 0, .06);
}

/* 7. Features --------------------------------------------------------------- */

.features { max-width: 1040px; margin: 0 auto; padding: 40px 32px 92px; }
.feature-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; }
.feature {
  display: flex; gap: 18px; align-items: flex-start;
  background: var(--card); border-radius: 20px; padding: 30px 32px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .06);
}
.feature-title { font-weight: 700; font-size: 16px; margin-bottom: 5px; letter-spacing: -0.2px; }
.feature-desc { font-size: 14px; line-height: 1.62; color: var(--muted); }

/* Keyboard-shortcuts card: keycap chips.
   The row wraps on narrow cards; each chip pairs a soft keycap with a one-word label. */
.feature-keys { display: flex; flex-wrap: wrap; gap: 7px 8px; margin-top: 14px; }
.keychip {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600; color: var(--muted);
  padding: 6px 13px 6px 7px; border-radius: 11px; border: 1.5px solid var(--line);
}
.keychip kbd {
  font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: 11px; font-weight: 700; line-height: 1; color: var(--ink);
  padding: 4px 6px; border-radius: 6px;
  background: var(--panel); border: 1px solid var(--line); border-bottom-width: 2.5px;
}
.keychip-more { padding: 6px 13px; color: var(--muted2); border-style: dashed; }

/* Blob icons — the studio's info-blob shape, one accent per feature */
.info-blob {
  flex: none; width: 42px; height: 42px;
  display: flex; align-items: center; justify-content: center;
}
.info-blob svg { width: 21px; height: 21px; }

.blob-gold   { background: #FFC933; color: #7a5b00; border-radius: 46% 54% 55% 45% / 52% 46% 54% 48%; }
.blob-teal   { background: #9FD6D2; color: #1e5450; border-radius: 48% 52% 42% 58% / 54% 46% 58% 42%; }
.blob-green  { background: #BAD29C; color: #3f5323; border-radius: 44% 56% 46% 54% / 56% 44% 56% 44%; }
.blob-coral  { background: #F0938C; color: #6e1d1d; border-radius: 52% 48% 58% 42% / 44% 54% 46% 56%; }
.blob-purple { background: #C6B5F2; color: #432b7a; border-radius: 58% 42% 48% 52% / 46% 56% 44% 54%; }

/* The closing card is a call to action, not a feature */
.feature-cta {
  background: var(--panel); align-items: center; justify-content: center; text-align: center;
}
.feature-cta-inner { display: flex; flex-direction: column; align-items: center; gap: 14px; }
.feature-cta .feature-title { font-family: var(--font-display); font-size: 19px; max-width: 240px; }

/* 8. Footer ------------------------------------------------------------------ */

.site-footer { margin-top: 20px; }

/* Legal links — understated, muted; sits opposite the wordmark in the footer
   row and stacks under it on small screens (shared.css switches to a column). */
.footer-legal { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; }
.footer-legal a { font-size: 12px; color: var(--muted2); text-decoration: none; }
.footer-legal a:hover { color: var(--ink); }

/* 9. Responsive ------------------------------------------------------------- */

@media (max-width: 860px) {
  .beats { grid-template-columns: 1fr; gap: 20px; max-width: 440px; margin: 0 auto; }
  .beat-num { font-size: 54px; top: 10px; right: 20px; }
  .feature-grid { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  .shots-grid { grid-template-columns: 1fr; gap: 18px; max-width: 440px; margin: 0 auto; }
}

@media (max-width: 560px) {
  :root { --nav-blur-h: 102px; }   /* the header is 69px tall here */
  .site-header { padding: 20px 22px; }
  .brand-nav { font-size: 18px; }
  .notch-overlay { width: min(360px, 78vw); }
  .hero-stage { padding-left: 20px; padding-right: 20px; padding-top: calc(54 * var(--vph)); }
  .hero-drop { width: clamp(160px, 46vw, 210px); --glow-blur: 64px; }
  .routine, .features, .shots { padding-left: 22px; padding-right: 22px; }
  .tour-static { padding-left: 22px; padding-right: 22px; }
  .feature { padding: 24px 24px; }
  .download-btn-mini { padding: 7px 12px; font-size: 12px; }
  .tour-cap { top: calc(var(--toast-bottom) + 48px); font-size: 16px; max-width: 84vw; }
  .tour-arrow { width: clamp(30px, 12%, 44px); }
}

/* Touch can't hover, so the macOS requirement tucked inside the closing CTA would
   never unfurl. Show it outright there. */
@media (hover: none) {
  .download-btn .download-btn-sub { max-height: 1.4em; opacity: .78; margin-top: 3px; }
}

/* Reduced motion: no scroll-jacking — collapse to a normal, static hero with the
   folder in flow above the copy, the fixed veil and notch hidden. shared.css
   already neutralizes the .rise reveals. */
@media (prefers-reduced-motion: reduce) {
  .hero-veil, .veil-blur { display: none; }
  .hero-focus {
    position: static; height: auto; display: block; padding: 0;
  }
  .hero-drop { margin: 0 auto; }
  .hero-stage {
    padding: 24px 32px 44px; gap: clamp(16px, 3vh, 28px);
  }
  .notch-overlay { display: none; }
  .hero-drop { animation: none; }
  .drop-file { transform: scale(1.2); }   /* no scrub — sit at the 20%-larger rest size */
  .hero-glow { transform: scale(.5); }   /* no scrub — sit at the small halo state */
  .tour-static { display: block; }
  .routine { position: static; }
}
