/* ── Per-section layout ───────────────────────────────────────────────── */

/* ── Hero ── */
.hero {
  position: relative;
  /* Clip so 3D-raked coverflow cards can peek to the phone edge without
     expanding the document's horizontal scroll width (iOS especially). */
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  /* pull up under the sticky nav so the dot halo sits behind it */
  margin-top: calc(var(--nav-h) * -1);
  padding-top: var(--nav-h);
}
/* Dot-field canvas — fixed to the viewport behind all content, which
   scrolls above it. Centred halo, painted over the page background. */
#dots {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  pointer-events: none;
}
.hero-inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  /* Top padding clears the nav and gives the hero air; bottom is 0 so the
     next section's top padding is the single, uniform section gap. */
  padding-block: clamp(96px, 12vh, 176px) clamp(var(--space-12), 6vh, var(--space-20));
  gap: var(--space-8);
}
.hero h1 {
  font-size: calc(var(--fs-title) + 4px);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -0.028em;
  color: var(--text-primary);
  max-width: 840px;
}
/* Rotating headline word — ported from the app's Studio headline. Each glyph
   is its own inline-block so it can flip on X independently; the outgoing word
   is lifted out of flow (position:absolute) so the incoming one doesn't wait
   for it, and the box's width is animated so the rest of the line slides. */
.slot {
  position: relative;
  display: inline-block;
  vertical-align: top;
  white-space: nowrap;
  perspective: 600px;
  transition: width 0.42s cubic-bezier(0.22, 1, 0.36, 1);
}
.slot-word {
  display: inline-block;
  white-space: nowrap;
  /* Persistent, subtle chromatic fringe — a hint of distorted chrome so the
     word never looks fully static. The split amplifies during each swap (see
     the keyframes below) and settles back to this at rest. */
  text-shadow:
    -0.012em 0 0 rgba(255, 46, 96, 0.3),
     0.012em 0 0 rgba(58, 214, 255, 0.3);
}
.slot-word.is-out { position: absolute; left: 0; top: 0; }
.slot-char { display: inline-block; transform-origin: 50% 50%; }
/* 0.34em ≈ the app's 12px offset at its headline size, so it scales with type */
.slot-char.enter { animation: slot-in 0.25s cubic-bezier(0.23, 1, 0.32, 1) both; }
.slot-char.exit  { animation: slot-out 0.25s cubic-bezier(0.23, 1, 0.32, 1) both; }
@keyframes slot-in {
  0% {
    transform: translateY(0.34em) rotateX(-90deg); opacity: 0;
    text-shadow: -0.012em 0 0 rgba(255, 46, 96, 0.3), 0.012em 0 0 rgba(58, 214, 255, 0.3);
  }
  /* Burst the RGB split while the glyph is actually on screen (opacity is high
     here), not at the flipped-away ends where the char is invisible. */
  55% {
    text-shadow: -0.1em 0 0 rgba(255, 46, 96, 0.9), 0.1em 0 0 rgba(58, 214, 255, 0.9);
  }
  100% {
    transform: none; opacity: 1;
    text-shadow: -0.012em 0 0 rgba(255, 46, 96, 0.3), 0.012em 0 0 rgba(58, 214, 255, 0.3);
  }
}
@keyframes slot-out {
  0% {
    transform: none; opacity: 1;
    text-shadow: -0.012em 0 0 rgba(255, 46, 96, 0.3), 0.012em 0 0 rgba(58, 214, 255, 0.3);
  }
  35% {
    text-shadow: -0.1em 0 0 rgba(255, 46, 96, 0.9), 0.1em 0 0 rgba(58, 214, 255, 0.9);
  }
  100% {
    transform: translateY(-0.34em) rotateX(90deg); opacity: 0;
    text-shadow: -0.012em 0 0 rgba(255, 46, 96, 0.3), 0.012em 0 0 rgba(58, 214, 255, 0.3);
  }
}

.hero-sub {
  font-size: var(--fs-reading);
  line-height: 1.5;
  color: var(--text-secondary);
  max-width: 64ch;
  text-wrap: balance;
}
/* Fixed two-line split, broken near the middle. Dropped on narrow screens,
   where the line wraps on its own and a hard break just goes ragged. */
@media (max-width: 640px) { .hero-sub .sub-br { display: none; } }
.hero-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); justify-content: center; margin-top: var(--space-1); }

/* This-week gallery, folded into the hero. Its own header + card row sit
   below the pitch and CTA, separated by generous space so the fold still
   reads as hero first, proof second. */
.hero-gallery {
  /* Sits at the content-column width (same container the mood tiles use below),
     so the two showcases read at the same scale rather than spanning the whole
     viewport. */
  width: 100%;
  margin-top: clamp(var(--space-20), 10vh, 128px);
  text-align: left;
}
@media (max-width: 640px) { .hero-gallery { margin-top: clamp(var(--space-12), 8vh, var(--space-20)); } }

/* ── The boring parts, quietly handled — a minimal, image-free spec sheet ── */
.handled-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(var(--space-12), 6vw, var(--space-20)) clamp(var(--space-8), 5vw, var(--space-16));
}
/* Drop to 2-up (→ 3 rows of 2) as soon as three columns start to feel tight. */
@media (max-width: 1080px) { .handled-grid { grid-template-columns: repeat(2, 1fr); } }
.handled-item h3 {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--space-3);
  font-family: var(--font);
  font-size: var(--text-3);
  font-weight: 500;
  letter-spacing: -0.012em;
  color: var(--text-primary);
}
/* Filled circular check, sitting to the left of each title */
.handled-check { order: -1; width: 18px; height: 18px; flex: none; color: var(--text-primary); }
.handled-check circle { fill: currentColor; }
.handled-check path { stroke: var(--bg); }
.handled-item p {
  margin-top: var(--space-2);
  font-family: var(--font);
  /* Same reading size as .faq-body — midpoint of the former FAQ (~20.75)
     and capabilities (16) sizes. */
  font-size: var(--text-3);
  line-height: 1.55;
  color: var(--text-secondary);
  text-wrap: balance;   /* even two-line split, consistent across all six */
  max-width: 34ch;
}
/* Phone: single column, check + title row + body all centred. Media query must
   follow the base h3 rule so justify-content:center wins over flex-start. */
@media (max-width: 640px) {
  .handled-grid { grid-template-columns: 1fr; }
  .handled-item {
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
  }
  .handled-item h3 {
    justify-content: center;
    width: 100%;
  }
  .handled-item p { margin-inline: auto; }
}

/* ── Closing CTA — full-bleed image band with tinted ends ── */
.cta {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Fluid band: ~300px on phones up to 420px on desktop (380px — the old fixed
     height — lands near 1050px wide), so the panel keeps one proportion at
     every width instead of towering on small screens. */
  height: clamp(300px, 36vw, 420px);
  /* Inset from the screen edge by the site's own gutter (24px on a phone,
     scaling up on desktop like every other section) and round the band, so it
     reads as a contained panel rather than full-bleed. */
  margin-inline: var(--page-pad);
  border-radius: var(--radius-lg);
}
.cta .hero-actions { margin-top: var(--space-6); }
/* Match the hero headline's bump — these two animating titles only */
.cta h2 { font-size: calc(var(--fs-title) + 4px); }
.cta-bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  display: flex;
  opacity: 0.5;
  /* soft-focus the filmstrip so the tiles read as one dreamy wash of colour,
     not a row of hard-seamed photos; scale up to hide the blur's edge bleed */
  filter: blur(3px) saturate(1.12);
  transform: scale(1.06);
}
.cta-tile {
  flex: 1;
  min-width: 0;
  height: 100%;
  object-fit: cover;
}
@media (max-width: 720px) { .cta-tile:nth-child(n+5) { display: none; } }
/* Live WebGL "ribbed glass" shader (cta-shader.js) fills the band edge-to-edge,
   replacing the raw filmstrip. Full-bleed, no vignette / soft edge. */
.cta-canvas {
  position: absolute;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  display: block;
}
/* Fallback only (no WebGL): a flat, even dim over the filmstrip for legible copy. */
.cta.no-shader::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: rgba(6, 6, 6, 0.34);
}

/* ── Gallery preview ── */
/* Three cards in a single row on desktop, sized to match the mood tiles below
   (same container width, same gap). Below 1080 it becomes the Cover Flow deck. */
.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-5);
}
/* Below 1080 the four-up grid gives way to the Cover Flow deck (coverflow.js
   adds .is-coverflow). Without JS / with reduced motion it degrades to a
   horizontal scroll-snap strip — the :not(.is-coverflow) rules below. */
@media (max-width: 1080px) {
  /* Full-bleed the stage past the container gutter so cards can kiss the phone
     edge and peek off-screen — only this track scrolls/overflows sideways. */
  .hero-gallery .card-grid {
    width: calc(100% + 2 * var(--page-pad));
    max-width: none;
    margin-inline: calc(var(--page-pad) * -1);
  }
  .card-grid:not(.is-coverflow) {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    gap: var(--space-4);
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    /* Pad so the first/last card can centre without being hard against the glass. */
    padding-inline: var(--page-pad);
    scroll-padding-inline: var(--page-pad);
  }
  .card-grid:not(.is-coverflow)::-webkit-scrollbar { display: none; }
  .card-grid:not(.is-coverflow) > .card {
    flex: 0 0 min(78vw, 300px);
    scroll-snap-align: center;
  }
}
.gallery-card {
  gap: var(--space-2);
  padding: var(--space-4); /* 16px — matches the 3-step cards */
  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* concentric with the inner image: its 18px radius + the 8px inset */
  border-radius: calc(var(--radius-lg) + var(--space-2));
}
/* Image-aware color wash on the card body — a heavily blurred, saturated copy
   of the card's own cover (--glow-img), same technique as the mood tiles. The
   opaque cover photo sits above it, so the glow only reads in the lower body. */
.gallery-card::before {
  content: '';
  position: absolute;
  inset: -20%;
  z-index: 0;
  background-image: var(--glow-img);
  background-size: cover;
  background-position: center;
  filter: blur(46px) saturate(1.9);
  opacity: 0.55;
  pointer-events: none;
}
/* dark-glass tint over the wash — keeps the footer rich and the copy crisp */
.gallery-card::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(to bottom, transparent 42%, rgba(var(--bg-rgb),0.4) 66%, rgba(var(--bg-rgb),0.72) 100%);
  pointer-events: none;
}
/* brighter description over the darker footer */
.gallery-card p { color: var(--text-primary); }
.gallery-card > * { position: relative; z-index: 1; }
.gallery-card .media {
  /* tall, immersive portrait frame — the app's cover is the hero of the card,
     with the title laid straight over it (see .card-title). Inset 8px from the
     card top and sides; fully rounded so it reads as a framed image. */
  aspect-ratio: 4 / 5;
  margin: calc(var(--space-2) * -1) calc(var(--space-2) * -1) var(--space-2);
  width: auto;
  border-radius: var(--radius-lg);
  overflow: hidden;
}
/* Real cover photo as an <img> so it can gently zoom on hover
   (a background-image can't be transformed). */
.gallery-card .media .cover {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.01);
  transition: transform 0.7s cubic-bezier(0.22, 1, 0.36, 1), filter 0.4s ease;
}
/* Legibility scrim for the overlaid title — deeper than the old caption seam. */
.gallery-card .media::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  background: linear-gradient(180deg, transparent 34%, rgba(var(--bg-rgb),0.34) 62%, rgba(var(--bg-rgb),0.88) 100%);
  pointer-events: none;
}
/* App name, laid over the lower cover. */
.gallery-card .card-title {
  position: absolute;
  z-index: 3;
  left: var(--space-3);
  right: var(--space-3);
  bottom: var(--space-3);
  margin: 0;
  color: #fff;
  font-size: var(--text-4);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: -0.02em;
  text-shadow: 0 1px 14px rgba(0, 0, 0, 0.5);
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}
@media (hover: hover) {
  a.gallery-card:hover .cover { transform: scale(1.07); }
  a.gallery-card:hover .card-title { transform: translateY(-2px); }
  /* Category chip stays hidden until the card is hovered (or focused). */
  .gallery-card .cat-pill {
    opacity: 0;
    transform: translateY(-4px);
    transition: opacity 0.25s ease, transform 0.25s cubic-bezier(0.22, 1, 0.36, 1);
  }
  a.gallery-card:hover .cat-pill,
  a.gallery-card:focus-visible .cat-pill { opacity: 1; transform: translateY(0); }
}
/* Category pill — monochrome glass chip, pinned to the cover's top-right. */
.cat-pill {
  position: absolute;
  right: var(--space-3);
  top: var(--space-3);
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: 5px 10px;
  border-radius: var(--radius-sm);
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  font-size: var(--text-1);
  font-weight: 500;
  line-height: 1;
  color: rgba(255, 255, 255, 0.92);
}
/* Category icon — the app's own Phosphor glyph, monochrome to match the label. */
.cat-ico {
  flex: none;
  width: 14px;
  height: 14px;
  fill: currentColor;
}
/* ── Footer — solid panel, brand left, link columns right-aligned ── */
.footer {
  background: #0a0a0b;
  padding-block: clamp(96px, 10vw, 140px) var(--space-12);
}
.footer-cols {
  display: flex;
  justify-content: space-between;
  gap: clamp(var(--space-10), 8vw, 120px);
  flex-wrap: wrap;
}
.footer-lockup { display: flex; align-items: center; gap: var(--space-3); }
.footer-brand .logo-lockup { height: 38px; width: auto; display: block; }
.footer-links { display: flex; gap: clamp(var(--space-10), 6vw, 80px); }
.footer-col { text-align: left; }
.footer-col h4 {
  font-family: var(--font-mono);
  font-size: var(--text-1);
  font-weight: 500;
  color: var(--text-muted);
  margin-bottom: var(--space-4);
}
.footer-col ul { list-style: none; display: flex; flex-direction: column; gap: var(--space-3); }
.footer-col a { font-size: var(--text-2); color: var(--text-secondary); text-decoration: none; transition: color 0.15s ease; }
.footer-col a:hover { color: var(--text-primary); }
.footer-legal {
  margin-top: clamp(var(--space-12), 6vw, 72px);
  padding-top: var(--space-6);
  border-top: 1px solid var(--overlay-7);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  font-family: var(--font-mono);
  font-size: 13px;
  flex-wrap: wrap;
}
.footer-legal a, .footer-legal span { color: var(--text-muted); text-decoration: none; transition: color 0.15s ease; }
.footer-legal a:hover { color: var(--text-primary); }
.footer-legal .legal-links { display: flex; gap: var(--space-5); flex-wrap: wrap; }

/* ── Responsive ──────────────────────────────────────────────────────── */

/* Mobile nav panel */
.nav-menu-backdrop { display: none; }

@media (max-width: 900px) {
  .nav-center, .nav-right .nav-login { display: none; }
  .nav-toggle { display: inline-flex; }

  .nav-menu {
    display: flex;
    position: fixed;
    inset: var(--nav-h) 0 auto 0;
    display: flex;
    flex-direction: column;
    gap: var(--space-1);
    padding: 16px var(--page-pad) 28px;
    background: rgba(var(--bg-rgb), 0.96);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--overlay-10);
    transform: translateY(-8px);
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.2s ease, transform 0.2s ease, visibility 0.2s;
    z-index: 49;
  }
  .nav.open .nav-menu { opacity: 1; visibility: visible; transform: none; }
  .nav-menu a { padding: var(--space-4) var(--space-1); font-size: var(--text-3); color: var(--heading); text-decoration: none; border-bottom: 1px solid var(--overlay-7); }

  .feature-row { grid-template-columns: 1fr; gap: var(--space-6); }
  /* media always leads so the stacked rhythm is consistent */
  .feature-row .feature-text, .feature-row:nth-child(even) .feature-text { order: 2; }
  .feature-row .media { order: 1; }

  .footer-cols { flex-direction: column; gap: var(--space-10); }
  .footer-links { gap: clamp(var(--space-8), 12vw, 80px); }
}

@media (max-width: 560px) {
  .footer-links { flex-wrap: wrap; gap: var(--space-8) var(--space-10); }
  .footer-col { text-align: left; }
  .footer-legal { flex-direction: column; align-items: flex-start; gap: var(--space-3); }
  .hero-actions { width: 100%; }
}

/* ── Explore-style rails (moods / picked-for-you / top templates) ──────── */

/* Left-aligned rail header: title + optional "See all" */
.rail-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-4);
  margin-bottom: clamp(var(--space-10), 4vw, var(--space-16));
}
.rail-head h2 { font-size: clamp(var(--text-4), calc(15px + 1.1vw), var(--text-5)); }
.see-all {
  flex: none;
  font-size: var(--text-1);
  color: var(--text-muted);
  text-decoration: none;
  transition: color 0.15s ease;
}
.see-all:hover { color: var(--text-primary); }

/* Moods — fanned cover stacks that spring open on hover */
.moods { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--space-5); max-width: 1080px; margin-inline: auto; }
.mood {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  /* Taller than square with trimmed side padding, so the fan fills more of the
     tile. mood-fan is flex:1, so the extra height flows straight to the fan. */
  aspect-ratio: 4 / 5;
  padding: var(--space-6) var(--space-1) var(--space-8);
  background: var(--surface-1);
  border-radius: 32px;
  text-decoration: none;
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
/* color wash — a heavily blurred copy of the tile's own cover, so the glow
   responds to the imagery's colours (app-card footer technique) */
.mood::before {
  content: '';
  position: absolute;
  inset: -30%;
  z-index: 0;
  background-image: var(--glow-img);
  background-size: cover;
  background-position: center;
  filter: blur(48px) saturate(1.8);
  opacity: 0.62;
  transition: opacity 0.35s ease;
}
/* dark glass tint over the wash — depth + keeps the label legible */
.mood::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(to bottom, rgba(var(--bg-rgb),0.18) 0%, rgba(var(--bg-rgb),0.72) 100%);
}
.mood > * { position: relative; z-index: 2; }
@media (hover: hover) {
  .mood:hover { transform: translateY(-4px); }
  .mood:hover::before { opacity: 0.72; }
}
.mood-fan { position: relative; flex: 1; display: flex; align-items: center; justify-content: center; }
.mood-fan img {
  position: absolute;
  width: 54%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: var(--radius-card);
  background: var(--surface-2);
  box-shadow: var(--shadow-md);
  transform: translateX(calc(var(--tx) * 1.6)) rotate(var(--rot));
  transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
  /* smooth the rounded corners on the rotated covers (transform + radius
     otherwise rasterises with visible stair-stepping) */
  outline: 1px solid transparent;
  backface-visibility: hidden;
}
/* Side covers are slimmer sleeves — same height as the square centre card
   (38% × 5/4 ≈ 48%), just narrower, so they peek out without competing. */
.mood-fan img:first-child,
.mood-fan img:last-child { width: 44%; aspect-ratio: 4 / 5; }
@media (hover: hover) {
  .mood:hover .mood-fan img {
    transform: translateX(calc(var(--tx) * 2.4)) translateY(-6px) rotate(calc(var(--rot) * 1.3));
  }
}
/* In the carousel, the tile resting at centre fans its stack open (coverflow.js
   toggles .cf-center); it eases back in as it leaves the middle. */
.mood.cf-center .mood-fan img {
  transform: translateX(calc(var(--tx) * 2.4)) translateY(-6px) rotate(calc(var(--rot) * 1.3));
}
.mood.cf-center::before { opacity: 0.72; }
.mood-label { text-align: center; }
.mood-label b {
  display: block;
  font-weight: 500;
  font-size: var(--text-3);
  line-height: 1.25;
  letter-spacing: -0.012em;
  color: var(--text-primary);
}
.mood-label span {
  display: block;
  margin-top: var(--space-1);
  font-size: var(--text-1);
  letter-spacing: 0.01em;
  color: var(--text-muted);
}

/* Picked for you — three curated community columns.
   The sharing-loop steps reuse this grid + column shell. */
.picks {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(var(--space-5), 2.2vw, var(--space-8));
  /* Keep overflow visible so the step cards' inset top shine isn't clipped
     (overflow-x on an ancestor forces overflow-y to clip too — that was
     shaving the crown of the first/last cards on mobile). */
  overflow: visible;
}
/* Sharing loop — numbered steps inside a .pick-col shell. Frosted glass:
   translucent tint + backdrop blur so the starfield diffuses behind each card,
   with a hairline edge and top highlight to catch the light. */
.pick-col.step {
  position: relative;
  padding: calc(var(--space-5) - 4px); /* 16px — matches the app/gallery cards */
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.045), rgba(255, 255, 255, 0.02));
  box-shadow: inset 0 1px 0 var(--overlay-5);
  backdrop-filter: blur(16px) saturate(1.3);
  -webkit-backdrop-filter: blur(16px) saturate(1.3);
}
/* Steps section: don't clip card crowns (same overflow-x → overflow-y trap). */
#how {
  overflow: visible;
}
.step-ico {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius-sm);
  background: var(--overlay-7);
  color: var(--text-primary);
}
.step-ico svg { width: 22px; height: 22px; fill: currentColor; }
.step-num { font-family: var(--font-mono); font-size: var(--text-1); color: var(--text-dim); font-variant-numeric: tabular-nums; }
.step .step-num {
  position: absolute;
  color: oklch(0.36 0.006 265); /* dimmer than the default step number */
  top: calc(var(--space-5) - 4px);
  right: calc(var(--space-5) - 4px);
  margin: 0;
}
.step-body {
  font-family: var(--font);
  font-size: var(--text-2);
  line-height: 1.5;
  letter-spacing: -0.01em;
  color: var(--text-secondary);
  text-wrap: pretty; /* no single-word orphan on the last line */
}
.pick-col {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-5);
  background: var(--surface-1);
  border-radius: var(--radius-lg);
}
.pick-reason { font-size: var(--text-1); color: var(--text-muted); }
.pick-title { font-size: var(--text-3); font-weight: 500; letter-spacing: -0.012em; color: var(--text-primary); margin-top: 2px; }
.pick-rows { display: flex; flex-direction: column; gap: var(--space-1); flex: 1; margin-top: var(--space-2); }
.pick-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2);
  border-radius: var(--radius-sm);
  text-decoration: none;
  transition: background-color 0.15s ease;
}
@media (hover: hover) { .pick-row:hover { background: var(--overlay-5); } }
.pick-row img { width: 38px; height: 38px; border-radius: var(--radius-sm); object-fit: cover; flex: none; background: var(--surface-2); }
.pick-info { min-width: 0; display: flex; flex-direction: column; }
.pick-name { font-size: var(--text-2); font-weight: 500; color: var(--text-primary); }
.pick-online { font-size: var(--text-1); color: var(--text-muted); }

/* Top templates — App-Store-style ranked list, 9 items across 3 columns */
.templates {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, auto);
  grid-auto-flow: column;
  column-gap: clamp(var(--space-6), 3vw, var(--space-12));
}
.tpl-row {
  min-width: 0; /* let the grid track shrink so the subtitle ellipsis engages */
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-5) var(--space-2);
  border-bottom: 1px solid var(--overlay-7);
  text-decoration: none;
  transition: background-color 0.15s ease;
}
@media (hover: hover) { .tpl-row:hover { background: var(--overlay-5); } }
.tpl-rank { flex: none; width: 18px; text-align: center; font-size: var(--text-1); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.tpl-thumb { flex: none; width: 48px; height: 48px; border-radius: var(--radius-sm); object-fit: cover; background: var(--surface-2); }
.tpl-body { min-width: 0; flex: 1; }
.tpl-body b { display: block; font-weight: 500; font-size: var(--text-2); color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tpl-body span { display: block; font-size: var(--text-1); color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Author row (replaces the subtitle) — avatar photo + name */
.tpl-body .tpl-author { display: flex; align-items: center; gap: var(--space-2); white-space: nowrap; }
.tpl-avatar { flex: none; width: 18px; height: 18px; border-radius: 50%; object-fit: cover; }
.tpl-view {
  flex: none;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-sm);
  background: var(--surface-2);
  font-family: var(--font-mono);
  font-size: var(--text-1);
  font-weight: 500;
  color: var(--text-primary);
  text-decoration: none;
  transition: background-color 0.15s ease;
}
@media (hover: hover) {
  .tpl-view { opacity: 0; transition: opacity 0.2s ease, background-color 0.15s ease; }
  .tpl-row:hover .tpl-view, .tpl-row:focus-visible .tpl-view { opacity: 1; }
  .tpl-view:hover { background: oklch(0.26 0.006 265); }
}

@media (max-width: 900px) {
  /* Steps keep their desktop card width and simply stack, centred — rather
     than stretching to the full container width. */
  .picks { grid-template-columns: min(340px, 100%); justify-content: center; }
  .templates { grid-template-columns: 1fr; grid-template-rows: none; grid-auto-flow: row; }

  /* Moods → Cover Flow deck (coverflow.js). No-JS / reduced-motion fallback is
     the scroll-snap strip below. Full-bleed past the container gutter. */
  .moods {
    width: calc(100% + 2 * var(--page-pad));
    max-width: none;
    margin-inline: calc(var(--page-pad) * -1);
  }
  .moods:not(.is-coverflow) {
    display: flex;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    gap: var(--space-4);
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    padding-inline: var(--page-pad);
    scroll-padding-inline: var(--page-pad);
  }
  .moods:not(.is-coverflow)::-webkit-scrollbar { display: none; }
  .moods:not(.is-coverflow) > .mood {
    flex: 0 0 min(78vw, 320px);
    scroll-snap-align: center;
  }
}

/* ── Cover Flow deck (shared stage for .card-grid + .moods) ──────────────
   coverflow.js sets each child's transform/opacity/z every frame; the track
   just supplies perspective, the edge fade, and the absolute layout box. Only
   ever applied within each section's breakpoint band, and never under
   prefers-reduced-motion (JS gate), so no media query is needed here. */
.is-coverflow {
  position: relative;
  display: block;
  /* Visible so side cards can peek past the stage; page-level overflow-x:clip
     is what stops that from becoming a document-level horizontal scroll. */
  overflow: visible;
  max-width: none;
  perspective: 2000px;                 /* deeper = gentler foreshortening, less lens distortion */
  -webkit-perspective: 2000px;
  perspective-origin: 50% 50%;
  touch-action: pan-y;                 /* horizontal drag drives the deck, vertical scrolls the page */
  -webkit-user-select: none;
  user-select: none;
  outline: none;
  cursor: grab;
}
.is-coverflow:active { cursor: grabbing; }
/* Far cards recede and fade out via opacity (see coverflow.js) so they melt into
   the page on their own — no edge-gradient overlay that would cut off mid-deck. */

/* ── Prev/next arrows — injected by coverflow.js, shown only on non-touch
   (hover-capable, fine-pointer) devices. ── */
.cf-arrow {
  display: none;
  position: absolute;
  top: 50%;
  z-index: 200;
  width: 46px;
  height: 46px;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: var(--overlay-5);              /* barely-there glass */
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--text-secondary);
  cursor: pointer;
  transform: translateY(-50%);
  transition: background-color 0.25s ease, color 0.25s ease, opacity 0.25s ease;
}
.cf-arrow svg { width: 10px; height: 16px; } /* 16px tall — matches the Get started arrow */
/* Track is full-bleed (negative margin cancels the container gutter), so pin the
   arrows at the app margin (--page-pad) from the screen edge: 24px on a phone,
   scaling out into the gutter beside the deck on wider widths. z-index keeps
   them above any card they sit over on the narrowest screens. */
.cf-arrow--prev { left: var(--page-pad); }
.cf-arrow--next { right: var(--page-pad); }
.cf-arrow.is-disabled { opacity: 0; pointer-events: none; }
/* The icon's one-shot x-nudge (on hover + click, easing back to rest) is driven
   by coverflow.js; the button itself never scales. */
@media (hover: hover) and (pointer: fine) {
  .is-coverflow .cf-arrow { display: inline-flex; }
  .cf-arrow:hover { background: var(--overlay-10); color: var(--text-primary); }
  .cf-arrow:focus-visible { background: var(--overlay-10); color: var(--text-primary); box-shadow: 0 0 0 2px var(--overlay-20); }
}
/* Slightly wider on phones so the centre card reads bigger and neighbours
   still peek past the screen edge. */
.card-grid.is-coverflow { --cf-card-w: min(78vw, 300px); }
.moods.is-coverflow    { --cf-card-w: min(80vw, 340px); }
.is-coverflow > *:not(.cf-arrow) {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--cf-card-w, min(76vw, 320px));
  margin: 0 !important;
  transform-origin: 50% 50%;
  transform-style: preserve-3d;
  -webkit-transform-style: preserve-3d;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transition: none;                    /* JS owns transform/opacity */
  will-change: transform, opacity;
}
.is-coverflow img { -webkit-user-drag: none; user-select: none; }

/* ── Mobile corner AA for 3D-raked cards ─────────────────────────────────
   Mobile GPUs rasterise overflow:hidden + border-radius at the layer's flat
   resolution, then apply rotateY — which leaves stair-stepped corners at high
   DPR. Fix stack:
     1. clip-path (smooth mask, not overflow clip) on the whole card shell
     2. hairline transparent outline → compositor antialiases the edge
     3. -webkit-mask-image radial hack (Safari) forces AA on the layer
     4. no cover scale(1.01) inside the deck (scale fights the rounded clip) */
.is-coverflow > *:not(.cf-arrow) {
  outline: 1px solid transparent;
  /* Safari: radial mask forces antialiased layer edges under 3D transforms */
  -webkit-mask-image: -webkit-radial-gradient(white, black);
  mask-image: radial-gradient(white, black);
}
/* Outer shell — match each card family's border-radius exactly. */
.is-coverflow > .gallery-card {
  clip-path: inset(0 round calc(var(--radius-lg) + var(--space-2)));
  -webkit-clip-path: inset(0 round calc(var(--radius-lg) + var(--space-2)));
}
.is-coverflow > .mood {
  clip-path: inset(0 round 32px);
  -webkit-clip-path: inset(0 round 32px);
}
/* Inner framed media / fan thumbs — concentric clips. */
.is-coverflow .gallery-card .media {
  outline: 1px solid transparent;
  -webkit-backface-visibility: hidden;
  backface-visibility: hidden;
  clip-path: inset(0 round var(--radius-lg));
  -webkit-clip-path: inset(0 round var(--radius-lg));
  /* Contain any child transforms inside the smooth clip. */
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
}
.is-coverflow .mood-fan img {
  /* No clip-path here: it would clip the box-shadow (shadows paint outside the
     border box), which dropped the fan thumbs' shadow in the deck. border-radius
     already rounds them, and the centre card sits flat so its corners don't
     alias — the outer .mood shell keeps its clip for the raked corners. */
  outline: 1px solid transparent;
}
/* The resting 1.01 cover scale bleeds past the clip and reintroduces jaggies
   under rotateY — kill it while the deck is live. */
.is-coverflow .gallery-card .media .cover {
  transform: none;
}
.is-coverflow:focus-visible {
  box-shadow: 0 0 0 2px var(--bg), 0 0 0 4px var(--overlay-20);
  border-radius: var(--radius-lg);
}

/* Extra polish on coarse pointers (phones): slightly stronger edge AA via a
   0.5px ring that sits under the content and softens the clip silhouette. */
@media (pointer: coarse) {
  .is-coverflow > .gallery-card,
  .is-coverflow > .mood {
    box-shadow: 0 0 0 0.5px rgba(255, 255, 255, 0.06);
  }
  /* Non-coverflow cards on mobile still get a touch of AA help. */
  .gallery-card,
  .mood {
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
    outline: 1px solid transparent;
    transform: translateZ(0);
  }
  .gallery-card .media {
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
    outline: 1px solid transparent;
    transform: translateZ(0);
  }
  .gallery-card .media .cover {
    /* Avoid subpixel bleed past the radius on static cards too. */
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .slot { transition: none; }
  .slot-char.enter, .slot-char.exit { animation: none; }
  .nav, .nav-menu, .card, .btn-pill, .arrow-swap svg, .mood, .mood-fan img { transition: none; }
}
