/* ------------------------------------------------------------------
   SongGhost landing — page styles
   Direction: editorial cream chassis, cinematic dark interludes.
   See docs/DESIGN.md.
   ------------------------------------------------------------------ */

.skip {
  position: absolute;
  left: 50%;
  top: -4rem;
  transform: translateX(-50%);
  z-index: 100;
  background: var(--ink);
  color: var(--cream);
  padding: 0.65rem 1.1rem;
  border-radius: 0 0 10px 10px;
  text-decoration: none;
  font-weight: 600;
  transition: top 0.2s var(--ease-out);
}
.skip:focus { top: 0; }

/* ── Masthead ─────────────────────────────────────────────────────── */

.masthead {
  position: sticky;
  top: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.85rem var(--gutter);
  background: color-mix(in srgb, var(--cream) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(14px);
  -webkit-backdrop-filter: saturate(1.4) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s var(--ease-out), background 0.3s var(--ease-out);
}
.masthead[data-stuck='true'] { border-bottom-color: var(--rule-soft); }

/* The full logo is a thought-cloud lockup with "SONG GHOST" set inside it —
   at nav scale that text is ~8px and unreadable, and pairing the lockup with
   a wordmark said the name twice. Rudy alone is the mark; Unbounded says the
   name once, legibly. */
.masthead__mark {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  text-decoration: none;
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.0625rem;
  letter-spacing: -0.015em;
}
.masthead__mark { padding-block: 0.35rem; min-width: 0; }
.masthead__mark img { width: 34px; height: auto; flex: none; }

/* Below ~400px the wordmark and the nav CTA collide: .masthead__mark shrinks
   as a flex item but its span keeps painting past the shrunken box, over the
   nowrap button, and the button runs off the edge. Rudy alone is enough at
   that width — the name is in the <title> and the aria-label. */
@media (max-width: 374px) {
  .masthead__mark span { display: none; }
}

.masthead__nav {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2vw, 1.9rem);
  font-size: 0.9375rem;
  font-weight: 600;
}
.masthead__nav a:not(.btn) {
  text-decoration: none;
  color: var(--ink-soft);
  transition: color 0.18s var(--ease-out);
}
.masthead__nav a:not(.btn):hover { color: var(--ink); }

@media (max-width: 720px) {
  .masthead__nav a:not(.btn) { display: none; }
}

/* ── Buttons ──────────────────────────────────────────────────────── */

.btn {
  --btn-y: 0.9rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: var(--btn-y) 1.5rem;
  /* A floor, so shrinking a variant's padding can never take it back under
     the 44px touch target. */
  min-height: 44px;
  border: 0;
  border-radius: 999px;
  font-family: var(--body);
  font-weight: 700;
  font-size: 0.9375rem;
  letter-spacing: 0.005em;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: transform 0.2s var(--ease-out), box-shadow 0.25s var(--ease-out),
              opacity 0.2s var(--ease-out);
}
.btn__glyph { width: 18px; height: 18px; margin-top: -2px; }

.btn--primary {
  background: var(--cta);
  color: #fff;
  box-shadow: 0 1px 2px rgba(24, 33, 84, 0.28), 0 10px 26px -12px rgba(43, 91, 224, 0.85);
}
.btn--primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 2px 4px rgba(24, 33, 84, 0.3), 0 18px 38px -14px rgba(43, 91, 224, 0.95);
}
.btn--primary:active { transform: translateY(0); }

.btn--ghost {
  padding-inline: 0.25rem;
  background: none;
  color: var(--ink);
  border-radius: 4px;
  box-shadow: inset 0 -1px 0 0 var(--rule);
}
.btn--ghost:hover { box-shadow: inset 0 -2px 0 0 var(--accent); color: var(--accent); }
.btn--ghost span { transition: transform 0.2s var(--ease-out); display: inline-block; }
.btn--ghost:hover span { transform: translateX(3px); }

.btn--ghost-night { color: var(--night-ink); box-shadow: inset 0 -1px 0 0 var(--night-rule); }
.btn--ghost-night:hover { color: #fff; box-shadow: inset 0 -2px 0 0 var(--accent-bright); }

.btn--sm { --btn-y: 0.6rem; padding-inline: 1.1rem; font-size: 0.875rem; }
.btn--lg { --btn-y: 1.05rem; padding-inline: 1.9rem; font-size: 1rem; }

.cta-pair {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2vw, 1.75rem);
  flex-wrap: wrap;
}
.cta-pair--stack { justify-content: flex-start; }

/* ── Hero ─────────────────────────────────────────────────────────── */

.hero {
  display: grid;
  grid-template-columns: minmax(0, 1.14fr) minmax(0, 0.86fr);
  align-items: center;
  gap: clamp(2rem, 4vw, 4rem);
  padding: clamp(3rem, 7vh, 6rem) 0 clamp(4rem, 9vh, 7.5rem) var(--gutter);
  min-height: min(88vh, 900px);
}

.hero__type { max-width: 44rem; min-width: 0; }
/* The three lines are authored breaks — size the face so each one actually
   fits its column, or the browser re-breaks them and the rag falls apart. */
.hero__type h1 {
  margin: 1.1rem 0 0;
  font-size: clamp(2.2rem, 3.5vw + 0.75rem, 4.6rem);
}
.hero__type h1 .line { display: block; }
@media (min-width: 901px) {
  /* Only hold the authored breaks where the column is wide enough to honour
     them. On a phone, nowrap would make the h1's min-content width exceed the
     viewport and drag the whole grid column out with it. */
  .hero__type h1 { text-wrap: nowrap; }
}
@media (max-width: 420px) {
  .hero__type h1 { font-size: clamp(1.8rem, 7.6vw, 2.2rem); }
}

.rule {
  border: 0;
  border-top: 1px solid var(--rule);
  margin: clamp(1.5rem, 3vh, 2.25rem) 0;
}
.rule--short { width: 5.5rem; margin-bottom: clamp(1.25rem, 2.5vh, 1.75rem); }

.hero__type .lede { margin-bottom: clamp(1.75rem, 3.5vh, 2.5rem); }

/* The film bleeds off the right edge of the page — cinema scale, editorial
   composition. Aspect is pinned so nothing reflows when the video loads. */
.hero__film {
  position: relative;
  margin: 0;
  border-radius: var(--radius-lg) 0 0 var(--radius-lg);
  overflow: hidden;
  /* The still is painted here rather than by a poster attribute: a video
     element that never gets to paint — autoplay refused, decode failed, file
     404, reduced-motion — would otherwise leave a black hole where the hero
     should be, and this way the still is breakpoint-aware. */
  background: var(--night) url('/media/hero-rudy-poster-v2.jpg') 50% 46% / cover no-repeat;
  box-shadow: 0 40px 80px -50px rgba(11, 10, 9, 0.85);
}
.hero__film .film {
  width: 100%;
  /* Square, not 4:5. The shot is now a narrative — Rudy floats, a request
     arrives, he crosses to the desk — so it has real horizontal composition.
     A 4:5 crop of a 16:9 frame keeps only ~42% of the width and guillotined
     the lamp and the desk he moves to; 1:1 keeps ~56% and holds the action. */
  aspect-ratio: 1 / 1;
  object-fit: cover;
  object-position: 50% 46%;
}
.film__cap {
  position: absolute;
  left: clamp(1rem, 2vw, 1.5rem);
  bottom: clamp(0.9rem, 2vw, 1.25rem);
  font-family: var(--display);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: rgba(244, 241, 234, 0.72);
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.7);
}

@media (max-width: 900px) {
  .hero {
    /* minmax(0,…) not 1fr: a plain 1fr floors at min-content, so one long
       unbreakable word or a nowrap heading can widen the whole page. */
    grid-template-columns: minmax(0, 1fr);
    padding-inline: var(--gutter);
    min-height: 0;
    gap: clamp(2rem, 5vw, 3rem);
  }
  .hero__film { border-radius: var(--radius-lg); }
  .hero__film .film { aspect-ratio: 16 / 11; object-position: 50% 38%; }
}
@media (max-width: 760px) {
  /* Phones get the 9:16 cut, so the fallback poster has to match it. */
  .hero__film {
    background-image: url('/media/hero-rudy-mobile-poster-v2.jpg');
    /* The 9:16 cut is an outpaint, so it gained ceiling and studio floor.
       Centre on Rudy rather than on the frame, or the crop is mostly empty
       light beam. */
    background-position: 50% 54%;
  }
  .hero__film .film { aspect-ratio: 4 / 5; object-position: 50% 54%; }
}

/* ── Section scaffolding ──────────────────────────────────────────── */

.section { padding-block: clamp(4.5rem, 11vh, 9rem); }
.section--tight { padding-block: clamp(3.5rem, 8vh, 6.5rem); }

.section__head {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(1rem, 3vw, 3rem);
  align-items: end;
  margin-bottom: clamp(2.25rem, 5vh, 3.75rem);
}
.section__head h2 { margin-top: 0.85rem; max-width: 18ch; }
.section__note {
  color: var(--ink-muted);
  font-size: 0.9375rem;
  max-width: 32ch;
  padding-bottom: 0.4rem;
}
@media (max-width: 760px) {
  .section__head { grid-template-columns: 1fr; align-items: start; }
}

/* ── Prompts ──────────────────────────────────────────────────────── */

.prompts { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--rule); }

.prompt {
  position: relative;
  display: grid;
  grid-template-columns: 5.5rem minmax(0, 1fr);
  gap: 0 clamp(1rem, 3vw, 2.5rem);
  padding: clamp(1.5rem, 3.5vh, 2.35rem) 0;
  border-bottom: 1px solid var(--rule);
}
.prompt__num {
  font-family: var(--display);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--accent);
  padding-top: 0.45rem;
}
.prompt__text {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(1.15rem, 1.5vw + 0.75rem, 1.75rem);
  line-height: 1.32;
  letter-spacing: -0.005em;
  max-width: 26ch;
}

.prompt__struck {
  display: block;
  color: var(--ink-faint);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  font-size: 0.82em;
  margin-bottom: 0.35rem;
}
.prompt__typed { color: var(--accent); }

.caret {
  display: inline-block;
  width: 2px;
  height: 0.95em;
  margin-left: 2px;
  vertical-align: -0.1em;
  background: var(--accent);
  animation: blink 1.05s steps(1, end) infinite;
}
@keyframes blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }

.prompt__mark {
  position: absolute;
  right: 0;
  bottom: clamp(1.5rem, 3.5vh, 2.35rem);
  font-family: var(--display);
  font-size: 0.8125rem;
  font-weight: 500;
  font-style: italic;
  color: var(--accent);
  opacity: 0.75;
  transform: rotate(-3deg);
}
@media (max-width: 720px) {
  .prompt { grid-template-columns: 2.75rem minmax(0, 1fr); }
  .prompt__text { max-width: none; }
  .prompt__mark { position: static; display: block; margin: 0.6rem 0 0 2.75rem; transform: none; }
}

/* ── Dark interlude ───────────────────────────────────────────────── */

/* The generated frame puts Rudy right-of-centre and his ribbon of light
   through the middle — both worth seeing. So the type takes the bottom band,
   where the shot is just a dark desk, rather than sitting on top of the art. */
/* Overlaying the headline on the footage was a losing fight — Rudy is large
   and centred in every frame, so any scrim strong enough to make type legible
   also killed the shot. The film takes the right of the section and the type
   sits on true black, with a wide gradient seam so the boundary reads as
   lighting falloff rather than a hard edge. */
.interlude {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  display: grid;
  align-items: center;
  min-height: min(84vh, 820px);
  background: var(--night);
  color: var(--night-ink);
  padding-block: clamp(4rem, 10vh, 7rem);
}
.interlude__film {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: -2;
  width: 64%;
  height: 100%;
  object-fit: cover;
  object-position: 44% 64%;
  background: var(--night) url('/media/rudy-writing-poster-v2.jpg') 44% 64% / cover no-repeat;
}
.interlude__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(to right, #060608 0%, #060608 30%, rgba(6, 6, 8, 0.94) 40%,
                    rgba(6, 6, 8, 0.45) 52%, rgba(6, 6, 8, 0.08) 64%, transparent 74%),
    linear-gradient(to bottom, rgba(6, 6, 8, 0.5) 0%, transparent 24%,
                    transparent 74%, rgba(6, 6, 8, 0.6) 100%);
}
/* The shell keeps its own centred page width; the text inside is what gets
   constrained, so the column sits at the left margin instead of the auto
   margins swallowing the free space and centring the block. */
.interlude__body > * { max-width: 29rem; }
.interlude__body h2 {
  margin: 1rem 0 1.35rem;
  font-size: clamp(1.7rem, 2.1vw + 1rem, 2.7rem);
}
.eyebrow--night { color: var(--night-ink-60); }
.interlude__copy {
  color: rgba(244, 241, 234, 0.82);
  font-size: clamp(1.0625rem, 0.5vw + 0.95rem, 1.1875rem);
  line-height: 1.62;
  max-width: 46ch;
}
@media (max-width: 900px) {
  /* No room for a side-by-side split: the film takes the top of the section
     and the type sits beneath it on solid black. */
  .interlude {
    align-items: flex-end;
    min-height: min(86vh, 780px);
    padding-block: clamp(3rem, 8vh, 5rem);
  }
  .interlude__film {
    width: 100%;
    height: 58%;
    bottom: auto;
    object-position: 46% 62%;
    background-position: 46% 62%;
  }
  .interlude__scrim {
    background:
      linear-gradient(to bottom, rgba(6, 6, 8, 0.45) 0%, transparent 18%,
                      rgba(6, 6, 8, 0.75) 46%, #060608 58%);
  }
  .interlude__body > * { max-width: none; }
}

/* ── Steps (real product footage) ─────────────────────────────────── */

/* ── How it works ─────────────────────────────────────────────────── */

.steps {
  list-style: none;
  margin: 0 0 clamp(2.5rem, 6vh, 4rem);
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 4vw, 3.5rem);
}
.step { padding-top: 1.15rem; border-top: 1px solid var(--rule); }
.step__num {
  display: block;
  font-family: var(--display);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--accent);
  margin-bottom: 0.55rem;
}
.step h3 { margin-bottom: 0.4rem; }
.step p { color: var(--ink-soft); font-size: 0.9375rem; max-width: 34ch; }

/* Five real captures. On desktop they sit in a row with a gentle stagger so
   the band reads as a strip of film rather than a tidy icon grid; on narrow
   screens it becomes a swipeable rail rather than five stacked phones. */
.gallery {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: clamp(0.75rem, 1.6vw, 1.5rem);
  align-items: start;
}

/* The gallery sits outside .shell: inside the 1240px text column each phone
   was only ~230px wide and the screens stopped being readable. Its own wider
   container avoids any 100vw/scrollbar arithmetic. */
.gallery-wrap {
  width: min(100% - (var(--gutter) * 2), 1680px);
  margin-inline: auto;
}
.shot { margin: 0; }
.shot:nth-child(even) { margin-top: clamp(1rem, 3vw, 2.5rem); }
.shot__screen {
  border-radius: clamp(12px, 1.6vw, 22px);
  overflow: hidden;
  background: var(--night);
  padding: 4px;
  box-shadow:
    0 0 0 1px rgba(26, 26, 26, 0.14),
    0 26px 46px -34px rgba(11, 10, 9, 0.75);
}
.shot__screen img {
  width: 100%;
  aspect-ratio: 9 / 19.5;
  object-fit: cover;
  object-position: 50% 0;
  border-radius: clamp(9px, 1.3vw, 18px);
}
/* This capture is a crop (its clipped title band was trimmed), so it keeps its
   own ratio rather than being cover-cropped sideways to match the others. The
   shorter frame reads fine against the row's stagger. */
.shot--short .shot__screen img { aspect-ratio: 560 / 1012; object-position: 50% 0; }
.shot figcaption {
  margin-top: 0.7rem;
  text-align: center;
  font-family: var(--display);
  font-size: 0.625rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
}

@media (max-width: 900px) {
  .steps { grid-template-columns: 1fr; gap: 0; }
  .step { padding-block: 1.15rem; }
  .step p { max-width: none; }
  /* A rail, not a stack: five full-width phones would be a scroll marathon. */
  .gallery {
    display: flex;
    gap: 0.9rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 0.5rem;
    /* Bleed the rail to the screen edges so it reads as scrollable. */
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    scrollbar-width: none;
  }
  .gallery::-webkit-scrollbar { display: none; }
  .shot { flex: 0 0 clamp(9.5rem, 46vw, 13rem); scroll-snap-align: center; }
  .shot:nth-child(even) { margin-top: 0; }
}

/* ── Mid band ─────────────────────────────────────────────────────── */

.band {
  border-block: 1px solid var(--rule);
  background: var(--paper-sunk);
  padding-block: clamp(2.25rem, 5vh, 3.25rem);
}
.band__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(1.25rem, 3vw, 2.5rem);
  flex-wrap: wrap;
}
.band__text {
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(1.125rem, 1vw + 0.9rem, 1.5rem);
  letter-spacing: -0.005em;
}

/* ── Craft grid ───────────────────────────────────────────────────── */

.craft {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(2rem, 5vw, 4.5rem);
}
.craft__item {
  padding: clamp(1.35rem, 3vh, 1.9rem) 0;
  border-top: 1px solid var(--rule);
}
.craft__item:last-child, .craft__item:nth-last-child(2) { border-bottom: 1px solid var(--rule); }
.craft__num {
  display: block;
  font-family: var(--display);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  color: var(--accent);
  margin-bottom: 0.6rem;
}
.craft__item h3 { margin-bottom: 0.45rem; }
.craft__item p { color: var(--ink-soft); font-size: 0.9375rem; max-width: 46ch; }

@media (max-width: 760px) {
  .craft { grid-template-columns: 1fr; }
  .craft__item:nth-last-child(2) { border-bottom: 0; }
}

/* ── Who it's for ─────────────────────────────────────────────────── */

.who {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 3vw, 3rem);
}
.who__item { border-top: 2px solid var(--ink); padding-top: 1.15rem; }
.who__item h3 { margin-bottom: 0.5rem; max-width: 16ch; }
.who__item p { color: var(--ink-soft); font-size: 0.9375rem; }
@media (max-width: 820px) { .who { grid-template-columns: 1fr; } }

/* ── Closing ──────────────────────────────────────────────────────── */

.closing {
  position: relative;
  overflow: hidden;
  background: var(--night);
  color: var(--night-ink);
  padding-block: clamp(4rem, 11vh, 7.5rem);
}
.closing__inner {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  align-items: center;
  gap: clamp(2rem, 5vw, 4.5rem);
}
.closing__rudy {
  width: 100%;
  max-width: 30rem;
  /* The portrait was generated on near-black, but "near" is the problem: on a
     true black section the plate reads as a lighter rectangle. Screen blending
     drops the darks out, and the radial mask feathers what's left so Rudy sits
     IN the dark rather than on a card floating over it. */
  mix-blend-mode: screen;
  opacity: 0.97;
  /* Feather well inside the image bounds — a mask that reaches the edge still
     shows the plate corner where the render's "near black" meets true black. */
  -webkit-mask-image: radial-gradient(ellipse 58% 56% at 50% 46%, #000 34%, transparent 86%);
  mask-image: radial-gradient(ellipse 58% 56% at 50% 46%, #000 34%, transparent 86%);
}
.closing__type h2 { margin-bottom: clamp(1.5rem, 3.5vh, 2.25rem); max-width: 13ch; }

@media (max-width: 860px) {
  .closing__inner { grid-template-columns: 1fr; text-align: left; }
  .closing__rudy { max-width: 19rem; margin-inline: auto; }
}

/* ── Footer ───────────────────────────────────────────────────────── */

.foot {
  background: var(--night);
  color: var(--night-ink-60);
  border-top: 1px solid var(--night-rule);
  padding-block: clamp(2rem, 4vh, 2.75rem);
  font-size: 0.875rem;
}
.foot__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  flex-wrap: wrap;
}
/* Same reasoning as the masthead: the cloud lockup's own wordmark is
   unreadable at footer scale, so Rudy is the mark and the name is set. */
.foot__mark {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  text-decoration: none;
  font-family: var(--display);
  font-weight: 600;
  font-size: 0.9375rem;
  letter-spacing: -0.015em;
  color: var(--night-ink);
  padding-block: 0.6rem;
}
.foot__mark img { width: 26px; height: auto; opacity: 0.95; }
.foot__links { display: flex; gap: clamp(0.5rem, 2vw, 1.25rem); margin-inline: -0.6rem; }
.foot__links a {
  color: var(--night-ink-60);
  text-decoration: none;
  transition: color 0.18s var(--ease-out);
  /* The links measured 22px tall — under even the 24px WCAG 2.2 floor. The
     padding is what makes them tappable; the negative margin above keeps the
     row optically aligned with the rest of the footer. */
  padding: 0.7rem 0.6rem;
}
.foot__links a:hover { color: var(--night-ink); }
.foot__legal { order: 3; flex-basis: 100%; color: var(--night-ink-muted); }
@media (min-width: 700px) { .foot__legal { order: 0; flex-basis: auto; } }

/* ── Reveal ───────────────────────────────────────────────────────── */

[data-reveal] {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.7s var(--ease-out), transform 0.7s var(--ease-out);
  transition-delay: calc(var(--d, 0) * 90ms);
}
[data-reveal].is-in { opacity: 1; transform: none; }

/* If JS never runs, nothing should stay invisible. */
.no-js [data-reveal] { opacity: 1; transform: none; }
