/* ============================================================
   StoryLink — site design system v3, "Two homes, one thread"
   Built 16 Aug 2026 from the approved hero footage (Variation B:
   the golden river between two houses on a sea of moonlit cloud).
   Palette is sampled from that frame. New file on purpose: pages
   migrate to it as they are rebuilt, and the old style.css retires
   when all 32 have.

   TYPE SYSTEM updated 17 Aug 2026, on evidence not habit. Same three
   families, jobs reassigned:
     Fraunces  — headings only, never below an 18px floor (20px on
                 the dark canvas). Serif vs sans is a wash for
                 legibility, but Shaikh/Chaparro/Fox (2006) found
                 serif scores highest on Stable/Practical/Mature/
                 Formal, which is what a one-person company selling
                 trust to strangers needs from its headline face.
     Inter     — every human sentence: body copy, price qualifiers,
                 labels, credential lines. Measured x-height 0.546em,
                 the largest of any free candidate checked, and it
                 is the dominant legibility variable, doubly so
                 light-on-dark where halation eats thin counters.
     Plex Mono — confined to kickers and genuinely machine-ish data
                 (ABN, order/ref numbers, dates, dimensions). The
                 same 2006 study found monospace tops Dull/Plain/
                 Unimaginative/Conforming of all five families; it
                 was previously carrying the site's trust copy and
                 form labels, which is exactly backwards.
   Scale is a 1.25 minor third off a 16px base. Line-height floors
   at 1.5 everywhere (WCAG 1.4.12). Purchase-relevant text floors at
   14px; body floors at 16px; inputs floor at 16px so iOS never
   zooms mid-form. Prices get tabular numerals via the .num-tabular
   utility, because Fraunces has no figure features (GSUB is
   case/liga/rvrn/ss01 only, verified against the upstream variable
   font) and cannot line up a decimal.
   ============================================================ */

:root{
  /* the footage's world */
  --canvas:#070A1E;          /* midnight sky, never pure black */
  --canvas2:#0B1030;         /* the deep beneath the cloud sea */
  --panel:rgba(255,255,255,.055);
  --panel2:rgba(255,255,255,.085);
  --accent:#FFC966;          /* the lit window: CTA and rare emphasis only */
  --accent-hover:#F2A65A;
  --accent-ink:#241500;      /* text on gold */
  --accent-muted:rgba(255,201,102,.16);
  --violet:#8B72E3;
  --cloud:rgba(180,185,220,.14);   /* the cloud sea as a border colour */
  --cloud2:rgba(180,185,220,.24);
  --text-primary:#F5F3FC;
  --text-secondary:#B7BCDA;
  --text-faint:#8489AB;
  /* the storybook page (daylight bands) */
  --cream:#F6EAD3;
  --cream2:#EFE0C4;
  --day-ink:#241F3D;
  --day-muted:#5A5478;
  --day-line:rgba(36,31,61,.12);
  /* type: families */
  --serif:"Fraunces","Iowan Old Style",Palatino,Georgia,serif;
  --sans:"Inter","Inter Fallback",-apple-system,"Segoe UI",Roboto,system-ui,sans-serif;
  --mono:"IBM Plex Mono",ui-monospace,"SF Mono",Menlo,monospace;

  /* type: scale — 1.25 minor third off a 16px base */
  --t-legal:14px;                 /* HARD FLOOR for purchase-relevant text */
  --t-small:15px;
  --t-body:16px;
  --t-lede:clamp(17px,1.6vw,19px);
  --t-h3:clamp(19px,2vw,24px);
  --t-h2:clamp(26px,3.6vw,44px);
  --t-h1:clamp(30px,5.2vw,58px);
  --t-display:clamp(32px,5.2vw,64px);
  --t-kicker:13px;                /* mono, uppercase, 2-4 words only */
  --t-serif-min:18px;             /* Fraunces never smaller. 20px on canvas. */

  /* type: line-height — 1.5 is the floor everywhere (WCAG 1.4.12) */
  --lh-body:1.6;
  --lh-lede:1.55;
  --lh-ui:1.5;
  --lh-h3:1.25;
  --lh-h2:1.15;
  --lh-h1:1.12;

  /* type: weight pairs — light-on-dark reads optically bolder */
  --w-body:380;                   /* Inter body on --canvas */
  --w-body-day:400;               /* Inter body on --cream */
  --w-ui:500;
  --w-strong:600;
  --w-head:500;                   /* Fraunces headings on canvas */
  --w-head-day:480;               /* Fraunces headings on cream */

  /* type: tracking */
  --ls-display:-.015em;           /* serif >= 40px */
  --ls-head:-.008em;              /* serif 24-39px */
  --ls-none:0;                    /* body copy. always. */
  --ls-small:.01em;               /* Inter 14-15px on dark */
  --ls-caps:.12em;                /* every uppercase mono label, unified */

  /* type: measure */
  --measure-prose:62ch;
  --measure-lede:56ch;
  --measure-min:45ch;             /* floor for any paragraph of length */

  /* type: numerals */
  --num-tabular:tabular-nums lining-nums;
  --num-text:proportional-nums lining-nums;

  /* motion */
  --ease-out:cubic-bezier(.22,.9,.24,1);
  --ease-soft:cubic-bezier(.45,.02,.18,1);
  /* legibility over live footage */
  --tshadow:0 1px 2px rgba(5,5,10,.95),0 3px 12px rgba(5,5,10,.78),0 10px 44px rgba(5,5,10,.8);
  --maxw:1120px;
  --radius:20px;
}

:root{color-scheme:dark}

/* Metric-matched fallback for Inter, so display:swap costs no layout shift
   while the webfont arrives. Derived from the served Inter latin woff2:
   upm 2048, hhea ascent .9688em, descent -.2412em, line-gap 0, average
   lowercase advance .5363em, measured against Arial's .4895em. */
@font-face{
  font-family:"Inter Fallback";
  src:local("Arial"),local("Helvetica Neue"),local("Helvetica");
  size-adjust:109.57%;
  ascent-override:88.41%;
  descent-override:22.01%;
  line-gap-override:0%;
}

*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
html,body{overflow-x:hidden;overflow-x:clip}
body{
  font-family:var(--sans);
  font-size:var(--t-body);
  font-weight:var(--w-body);
  color:var(--text-primary);
  background:var(--canvas);
  line-height:var(--lh-body);
  letter-spacing:var(--ls-none);
  -webkit-font-smoothing:antialiased;
}
/* the storybook page reads lighter under it, so it wants slightly more
   weight for the same apparent colour (irradiation runs the other way
   on a light ground) */
.cream-band{font-weight:var(--w-body-day)}
/* form controls: 16px is the iOS Safari floor below which focus zooms
   the viewport. House rule; page-specific forms should not go under it. */
input,select,textarea{font-family:var(--sans);font-size:16px}
/* opt-in utility for any price or numeral column that needs to align on
   the decimal — Fraunces has no tabular-figure feature to reach for */
.num-tabular{font-variant-numeric:var(--num-tabular);font-feature-settings:"tnum" 1}
/* mono kickers and machine data sit outside the Inter weight scale, so they
   must not inherit body's 380 — Plex Mono only has real weight stops */
.kicker,.step-no,.foot h2,.foot h3,.foot h4,.sound-chip{font-weight:400}
img{max-width:100%;height:auto;display:block}
a{color:var(--accent);text-decoration:none}
::selection{background:var(--accent);color:var(--accent-ink)}
:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:4px}

/* ------------------------------------------------ the fixed environment
   One background layer behind everything: the night drifts, very slowly,
   so the page reads as a place. Stars are two tiny repeating radial dots. */
.sky{
  position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(1.2px 1.2px at 18% 22%,rgba(255,255,255,.5) 49%,transparent 51%),
    radial-gradient(1px 1px at 71% 64%,rgba(255,255,255,.35) 49%,transparent 51%),
    radial-gradient(130% 46% at 50% -8%,rgba(41,34,96,.6) 0%,rgba(41,34,96,0) 55%),
    linear-gradient(180deg,var(--canvas) 0%,var(--canvas2) 100%);
  background-size:520px 520px,340px 340px,100% 100%,100% 100%;
}
.sky::after{
  content:"";position:absolute;inset:-10%;
  background:radial-gradient(50% 34% at 50% 108%,rgba(255,201,102,.10) 0%,rgba(255,201,102,0) 70%);
  animation:skyBreath 64s var(--ease-soft) -20s infinite alternate;
}
@keyframes skyBreath{from{opacity:.55;transform:translateY(1.5%)}to{opacity:1;transform:translateY(0)}}

/* accessibility ------------------------------------------------------- */
.visually-hidden{position:absolute!important;width:1px;height:1px;margin:-1px;
  padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip-link{position:fixed;top:-48px;left:16px;z-index:200;background:var(--accent);
  color:var(--accent-ink);font-weight:600;padding:10px 18px;border-radius:999px;
  transition:top .2s var(--ease-out)}
.skip-link:focus{top:12px}

/* ------------------------------------------------ navigation */
.nav{
  position:fixed;top:0;left:0;right:0;z-index:100;
  display:flex;align-items:center;justify-content:space-between;gap:16px;
  padding:14px clamp(16px,4vw,40px);
  background:linear-gradient(180deg,rgba(7,10,30,.82) 0%,rgba(7,10,30,.55) 70%,rgba(7,10,30,0) 100%);
  backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  transition:background .4s var(--ease-soft);
}
.nav.scrolled{background:rgba(7,10,30,.9);border-bottom:1px solid var(--cloud)}
/* the gold wordmark with its mark beside it, as the founder had it before */
.wordmark{display:flex;align-items:center;gap:11px;flex-shrink:0}
.wordmark img{width:38px;height:38px;border-radius:10px;flex:none}
.wordmark span{font-family:var(--serif);font-weight:600;font-size:1.45rem;
  color:var(--accent);letter-spacing:.005em;line-height:1}
@media (max-width:420px){.wordmark img{width:32px;height:32px}
  .wordmark span{font-size:1.2rem}}
.nav ul{display:flex;gap:clamp(10px,2.5vw,26px);list-style:none;align-items:center}
.nav ul a{color:var(--text-secondary);font-size:15px;font-weight:500;
  transition:color .25s var(--ease-out)}
.nav ul a:hover{color:var(--text-primary)}
/* the nav CTA must win the link-colour cascade or gold-on-gold washes out */
.nav .btn-gold,.nav ul a.btn-gold:hover{color:var(--accent-ink)}
.nav .btn{padding:9px 18px;font-size:14px}
@media (max-width:760px){.nav ul .hide-m{display:none}}

/* THE MOBILE MENU. Below 760px the nav links were hidden with no replacement,
   so a phone visitor could reach nothing but the download button. */
.burger{display:none;position:relative;z-index:101;width:42px;height:42px;
  border:1px solid var(--cloud2);background:rgba(8,10,26,.6);border-radius:12px;
  cursor:pointer;padding:0;align-items:center;justify-content:center;
  flex-direction:column;gap:5px;backdrop-filter:blur(8px)}
.burger span{display:block;width:17px;height:1.8px;border-radius:2px;
  background:var(--text-primary);transition:transform .3s var(--ease-out),opacity .2s linear}
.burger.open span:nth-child(1){transform:translateY(6.8px) rotate(45deg)}
.burger.open span:nth-child(2){opacity:0}
.burger.open span:nth-child(3){transform:translateY(-6.8px) rotate(-45deg)}
.menu-panel{position:fixed;top:0;left:0;right:0;z-index:99;
  padding:84px clamp(20px,6vw,40px) 26px;
  background:rgba(7,10,26,.96);border-bottom:1px solid var(--cloud);
  backdrop-filter:blur(18px);-webkit-backdrop-filter:blur(18px);
  transform:translateY(-100%);opacity:0;
  transition:transform .34s var(--ease-out),opacity .24s linear;
  box-shadow:0 30px 60px -30px rgba(0,0,0,.9)}
.menu-panel.in{transform:translateY(0);opacity:1}
.menu-panel ul{list-style:none;display:flex;flex-direction:column;gap:2px}
.menu-panel li a{display:block;padding:14px 4px;font-size:19px;font-weight:500;
  color:var(--text-primary);border-bottom:1px solid rgba(180,185,220,.09)}
.menu-panel li a:hover,.menu-panel li a:focus-visible{color:var(--accent)}
.menu-panel .menu-cta{margin-top:20px;width:100%;text-align:center}
body.menu-open{overflow:hidden}
@media (max-width:760px){.burger{display:flex}}
@media (min-width:761px){.menu-panel{display:none}}

/* ------------------------------------------------ buttons */
.btn{display:inline-block;border:0;cursor:pointer;font-family:var(--sans);
  font-weight:600;font-size:16px;line-height:1;padding:15px 28px;border-radius:999px;
  transition:transform .25s var(--ease-out),box-shadow .25s var(--ease-out),
             background .25s var(--ease-out),color .25s var(--ease-out);
  text-shadow:none}
.btn-gold{background:var(--accent);color:var(--accent-ink);
  box-shadow:0 6px 26px -8px rgba(255,201,102,.55)}
.btn-gold:hover{background:var(--accent-hover);transform:translateY(-2px);
  box-shadow:0 12px 34px -8px rgba(255,201,102,.6)}
.btn-ghost{background:transparent;color:var(--text-primary);
  box-shadow:inset 0 0 0 1.5px var(--cloud2)}
.btn-ghost:hover{box-shadow:inset 0 0 0 1.5px var(--accent);color:var(--accent);
  transform:translateY(-2px)}
@media (pointer:coarse){.btn{min-height:44px;display:inline-flex;
  align-items:center;justify-content:center}}

/* .micro carries human trust copy (provenance lines, audience labels) —
   Inter, not mono. It is read for reassurance, not parsed like data,
   and the 14px floor keeps it above the purchase-relevant text minimum. */
.micro{font-family:var(--sans);font-size:var(--t-legal);letter-spacing:var(--ls-small);
  line-height:var(--lh-ui);color:var(--text-secondary)}
/* .kicker stays mono: short (2-4 word), uppercase, genuinely a label */
.kicker{font-family:var(--mono);font-size:var(--t-kicker);letter-spacing:var(--ls-caps);
  text-transform:uppercase;color:var(--accent)}

/* ------------------------------------------------ the scrub hero */
.hero{position:relative;height:420vh}
/* a phone scrolls in shorter flicks, so the journey gets more room per beat */
@media (max-width:720px){.hero{height:360svh}
  .band .inner{margin-top:12svh}
  .band h1,.band .line{font-size:clamp(27px,7.6vw,40px)}
  .band .sub{font-size:16px;max-width:34ch}
  .band .cta-row{margin-top:24px}}
.hero .stage{position:sticky;top:0;height:100vh;overflow:hidden}
.hero .poster,.hero video{position:absolute;inset:0;width:100%;height:100%;
  object-fit:cover;background-size:cover;background-position:center}
.hero video{opacity:0;transition:opacity .8s var(--ease-soft);
  will-change:transform;transform:translateZ(0)}
.stage.video-ready video{opacity:1}
.stage.video-failed video{display:none}

/* the live thread over the film */
#heroThread{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;opacity:0;
  transition:opacity .4s var(--ease-soft)}
#threadShimmer{animation:threadRun 3.2s linear infinite}
@keyframes threadRun{from{stroke-dashoffset:0}to{stroke-dashoffset:-1200}}
body.paused #threadShimmer{animation-play-state:paused}
@media (orientation:landscape) and (pointer:coarse) and (max-height:560px),
       (prefers-reduced-motion:reduce){
  #heroThread{opacity:1}
  #heroThread path{stroke-dashoffset:0!important}
  #threadShimmer{animation:none;opacity:0}
}

/* base scrim: no frame is ever raw behind the page */
/* The founder's fade: an even veil across the whole frame, so the picture
   reads as one calm night with the type sitting quietly on it, and the bottom
   edge settles into the page instead of cutting off. */
.scrim{position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(180deg,
    rgba(7,10,24,.62) 0%,
    rgba(7,10,24,.4) 30%,
    rgba(7,10,24,.32) 55%,
    rgba(7,10,24,.55) 100%)}
/* This flat veil sits ON TOP of .scrim, so the two multiply: at .3 over a .82
   scrim the top of the frame was about 87 percent black and the artwork was
   lost. It stays, because it is what stops a bright frame washing out the type,
   but it is now a light touch rather than a second blackout. */
.hero .stage::after{content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
  background:rgba(7,10,24,.12)}
.hero .band,.hero .static-hero,.hero .ring,.hero .cue{z-index:3}
#heroThread{z-index:2}
/* The PORTRAIT film carries its ribbon inside the artwork, so the drawn line
   would be a second strand crossing it. Wide film: line drawn by the page.
   Tall film: line already in the picture. */
@media (orientation:portrait) and (max-width:1024px){#heroThread{display:none}}

/* loading ring, honest progress */
.ring{position:absolute;right:26px;bottom:26px;width:34px;height:34px;
  color:var(--accent);opacity:.8;transform:rotate(-90deg)}
.ring circle{transition:stroke-dashoffset .2s linear}
.cue{position:absolute;left:50%;bottom:22px;transform:translateX(-50%);
  color:var(--text-secondary);opacity:.75;font-size:22px;
  animation:cueBob 2.6s var(--ease-soft) -1.2s infinite}
@keyframes cueBob{0%,100%{transform:translate(-50%,0)}50%{transform:translate(-50%,7px)}}

/* caption bands */
.band{position:absolute;inset:0;display:flex;flex-direction:column;
  align-items:center;justify-content:flex-start;text-align:center;
  padding:0 6vw;opacity:0;pointer-events:none;text-shadow:var(--tshadow)}
.band .inner{margin-top:16vh;max-width:900px}
.band.settle .inner{margin-top:12vh}
.band h1,.band .line{font-family:var(--serif);font-weight:var(--w-head);
  font-size:clamp(30px,5.2vw,64px);line-height:var(--lh-h1);letter-spacing:var(--ls-display);
  text-wrap:balance}
.band .sub{font-size:clamp(16px,1.9vw,21px);color:var(--text-secondary);
  max-width:58ch;margin:20px auto 0;line-height:1.55}
.band.settle .inner{padding-bottom:clamp(22px,2.8vw,34px)}
.band .cta-row{display:flex;gap:14px;justify-content:center;flex-wrap:wrap;margin-top:26px}
.band .cta-row .btn{pointer-events:auto}
.band .micro{margin-top:18px;display:block}
/* per-band scrim rides the band's opacity and deepens with --k */
/* No panel behind the headlines: the even fade above carries them, and a box
   around the big type fought the picture. Only the smallest line gets a
   reading chip, further down. */

/* entrances: transform+opacity only, driven by --k, seek-safe and reversible */
.band .w{display:inline-block;white-space:pre;
  --kc:clamp(0,(var(--k,0) - var(--th,0))*2.8,1);
  opacity:var(--kc);
  transform:translateY(calc((1 - var(--kc))*26px))}
.band .c{display:inline-block;white-space:pre;
  --kc:clamp(0,(var(--k,0) - var(--th,0))*2.6,1);
  opacity:var(--kc);
  transform:translate(calc((1 - var(--kc))*var(--jx,0px)),calc((1 - var(--kc))*var(--jy,0px)))
            rotate(calc((1 - var(--kc))*var(--jr,0deg)))}
/* blur-to-sharp pair (band 2): soft copy is static blur, opacity crossfade only */
.blurpair{position:relative;display:inline-block}
.blurpair .soft{position:absolute;inset:0;filter:blur(10px);
  opacity:calc(1 - var(--k,0));pointer-events:none}
.blurpair .sharp{opacity:var(--k,0)}
/* staged settle (band 4): sub then CTAs arrive after the headline */
.band.settle .sub{--ks:clamp(0,(var(--k,0) - .52)*3.4,1);
  opacity:var(--ks);transform:translateY(calc((1 - var(--ks))*18px))}
.band.settle .cta-row{--kb:clamp(0,(var(--k,0) - .68)*4,1);
  opacity:var(--kb);transform:translateY(calc((1 - var(--kb))*16px))}
.band.settle .micro{--km:clamp(0,(var(--k,0) - .8)*5,1);opacity:calc(var(--km)*.9)}

/* The static hero's ARTWORK, composed per shape rather than cropped. A
   landscape film squeezed into a portrait frame left a black void with a
   sliver of the golden line, which is what a phone visitor actually saw. */
.static-art{display:none;position:absolute;inset:0;background-size:cover;
  background-position:center;background-repeat:no-repeat;
  background-image:url('/assets/hero/two-cottages-tablet.v1.jpg')}
@media (max-width:720px){
  .static-art{background-image:url('/assets/hero/two-cottages-portrait.v1.jpg');
    background-position:center bottom}
}

/* the five static-hero gates: MUST match the JS strings exactly */
.static-hero{display:none}
@media (orientation:landscape) and (pointer:coarse) and (max-height:560px),
       (prefers-reduced-motion:reduce){
  .hero{height:auto}
  .hero .stage{position:relative;height:100svh;min-height:560px}
  .hero video,.hero .ring,.hero .cue,.hero .band,#heroThread{display:none}
  .hero .poster{display:none}
  .static-art{display:block}
  /* the words live in the artwork's OWN empty sky, not over its subject */
  .static-hero{display:flex;position:absolute;inset:0;flex-direction:column;
    align-items:center;justify-content:flex-start;text-align:center;
    padding:14svh 6vw 0;text-shadow:var(--tshadow)}
  .static-hero::before{content:"";position:absolute;inset:0;z-index:-1;
    background:linear-gradient(180deg,rgba(7,10,24,.86) 0%,rgba(7,10,24,.66) 34%,rgba(7,10,24,.2) 62%,rgba(7,10,24,.5) 100%)}
  .static-hero .hero-title{font-family:var(--serif);font-weight:var(--w-head);
    font-size:clamp(30px,8.5vw,52px);line-height:var(--lh-h1);letter-spacing:var(--ls-display);text-wrap:balance}
  .static-hero .sub{font-size:clamp(15px,4vw,19px);color:var(--text-secondary);
    max-width:34ch;margin:14px auto 0}
  .static-hero .cta-row{display:flex;gap:12px;justify-content:center;flex-wrap:wrap;margin-top:24px}
  /* The credential line sits at the VERY BOTTOM of the hero, in the dark band
     under the artwork. Two earlier placements failed: below the buttons it lay
     across the golden ribbon and needed a box that then hid the ribbon, and
     above the buttons it interrupted the run from promise to action. Down here
     it is legible on its own dark ground and interrupts nothing. */
  /* the same reading treatment the founder pointed at, on the smallest line */
  /* left:0;right:0 + auto margins, NOT left:50%: an absolutely positioned box
     anchored at 50% only gets the right half of the screen as available width,
     which squeezed this line into three cramped rows. */
  .static-hero .micro{position:absolute;left:0;right:0;
    bottom:max(8svh,64px);margin:0 auto;width:fit-content;
    max-width:min(460px,92vw);
    font-size:var(--t-legal);letter-spacing:var(--ls-small);text-wrap:balance;
    background:rgba(10,13,30,.62);border:1px solid rgba(150,158,205,.16);
    border-radius:14px;padding:9px 16px;
    backdrop-filter:blur(14px) saturate(105%);
    -webkit-backdrop-filter:blur(14px) saturate(105%);
    box-shadow:0 18px 40px -24px rgba(0,0,0,.8)}
  .static-hero .cta-row{margin-top:26px}
}
@media (max-height:560px){.cue,.ring{display:none}}

/* ------------------------------------------------ page fabric below the settle */
main{position:relative}
.section{position:relative;max-width:var(--maxw);margin:0 auto;
  padding:clamp(56px,8vh,96px) clamp(20px,4.5vw,40px)}
/* adjacent sections doubled their padding into a dead void, so the second of
   any pair drops its top padding; the cream bands keep theirs, since the
   colour change is what separates them. */
.section + .section{padding-top:0}
.cream-band + .section,.section + .cream-band{padding-top:clamp(56px,8vh,96px)}
.cream-band .section{padding-top:clamp(56px,8vh,96px)}
.section h2{font-family:var(--serif);font-weight:var(--w-head);
  font-size:var(--t-h2);line-height:var(--lh-h2);letter-spacing:var(--ls-head);text-wrap:balance}
.cream-band .section h2{font-weight:var(--w-head-day)}
.section .lede{color:var(--text-secondary);font-size:var(--t-lede);
  max-width:var(--measure-lede);margin-top:14px;line-height:var(--lh-lede)}

/* The wordmark inside the closing loop. The oval was drawing itself and then
   enclosing nothing, which read as a decorative shape rather than a knot being
   tied. The name fades up as the line completes, so the loop closing and the
   brand arriving are one gesture. Driven by --draw, the same variable the path
   is drawn by, so it can never appear before the circle is joined. */
.thread .loop-mark{
  font-family:var(--serif);font-style:italic;font-weight:600;font-size:30px;
  fill:var(--accent);letter-spacing:.01em;
  opacity:clamp(0,(var(--draw,0) - .72)*4,1);
  transition:opacity .25s var(--ease-out)}
@media (prefers-reduced-motion:reduce){.thread .loop-mark{opacity:1}}

/* the golden thread: the signature. An SVG path that draws itself on scroll. */
.thread{position:absolute;left:50%;transform:translateX(-50%);pointer-events:none;
  overflow:visible}
.thread path{fill:none;stroke:var(--accent);stroke-width:2;stroke-linecap:round;
  opacity:.65;filter:drop-shadow(0 0 6px rgba(255,201,102,.55));
  stroke-dasharray:var(--len,1000);
  stroke-dashoffset:calc(var(--len,1000)*(1 - var(--draw,0)))}
.thread .bead{fill:var(--accent);opacity:calc(var(--draw,0))}

/* fireflies, whisper level, paused off-screen via .live and body.paused */
.fireflies span{position:absolute;width:4px;height:4px;border-radius:50%;
  background:var(--accent);opacity:0;pointer-events:none;
  box-shadow:0 0 10px 2px rgba(255,201,102,.5)}
.live .fireflies span{animation:fly 9s var(--ease-soft) infinite}
.fireflies span:nth-child(2){animation-delay:-3.2s;animation-duration:11s}
.fireflies span:nth-child(3){animation-delay:-6.1s;animation-duration:8s}
.fireflies span:nth-child(4){animation-delay:-1.4s;animation-duration:12.5s}
.fireflies span:nth-child(5){animation-delay:-7.8s;animation-duration:10s}
.fireflies span:nth-child(6){animation-delay:-4.6s;animation-duration:13s}
@keyframes fly{0%{transform:translate(0,0);opacity:0}12%{opacity:.7}
  50%{transform:translate(26px,-48px);opacity:.35}88%{opacity:.6}
  100%{transform:translate(-12px,-96px);opacity:0}}
body.paused *,body.paused *::before,body.paused *::after{animation-play-state:paused!important}

/* entrance choreography for sections */
.reveal .part{opacity:0;transform:translateY(26px);
  transition:opacity .7s var(--ease-out),transform .7s var(--ease-out)}
.reveal.in .part{opacity:1;transform:none}
.reveal.in .part:nth-child(2){transition-delay:.09s}
.reveal.in .part:nth-child(3){transition-delay:.18s}
.reveal.in .part:nth-child(4){transition-delay:.27s}
.reveal.in .part:nth-child(5){transition-delay:.36s}
/* retire the stagger after entry so hovers never lag: matches specificity */
.reveal.done .part:nth-child(2),.reveal.done .part:nth-child(3),
.reveal.done .part:nth-child(4),.reveal.done .part:nth-child(5){transition-delay:0s}

/* HOW IT WORKS: three equal steps, each a real device shot in a device frame.
   A row, not a stack of full-bleed screenshots: the old .station layout let a
   1290px portrait screenshot run off the page edge and needed a decorative
   vertical rule to fill the dead column beside it. */
.steps{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(24px,3.4vw,44px);
  margin-top:clamp(40px,6vh,68px)}
.step{display:flex;flex-direction:column;gap:14px}
.step-head{display:flex;align-items:baseline;gap:12px}
.step-no{font-family:var(--mono);font-size:var(--t-kicker);letter-spacing:var(--ls-caps);color:var(--accent);
  border:1px solid var(--accent-muted);border-radius:999px;padding:4px 10px;flex:none}
.step h3{font-family:var(--serif);font-weight:var(--w-head);font-size:var(--t-h3);
  line-height:var(--lh-h3);text-wrap:balance}
.step > p{color:var(--text-secondary);font-size:15.5px;line-height:var(--lh-body)}
/* the device frame: the screenshot sits INSIDE a phone, never bleeding out */
.phone{position:relative;margin-top:auto;padding:9px;border-radius:34px;
  background:linear-gradient(160deg,rgba(255,255,255,.16),rgba(255,255,255,.03) 40%,rgba(0,0,0,.4));
  box-shadow:0 30px 70px -34px rgba(0,0,0,.9),inset 0 0 0 1px rgba(255,255,255,.07)}
.phone::after{content:"";position:absolute;top:17px;left:50%;transform:translateX(-50%);
  width:64px;height:5px;border-radius:99px;background:rgba(0,0,0,.55);z-index:2}
.phone img{width:100%;display:block;border-radius:26px;aspect-ratio:1290/2400;
  object-fit:cover;object-position:top center}
@media (max-width:860px){
  .steps{grid-template-columns:1fr;gap:clamp(34px,6vh,52px)}
  .step{display:grid;grid-template-columns:minmax(0,1fr) 190px;
    grid-template-areas:"head phone" "body phone";column-gap:26px;align-items:start}
  .step-head{grid-area:head}
  .step > p{grid-area:body}
  .phone{grid-area:phone;margin-top:0}
}
@media (max-width:560px){
  .step{grid-template-columns:1fr;grid-template-areas:"head" "body" "phone"}
  .phone{max-width:260px;margin:6px auto 0}
}

/* the interactive moment: press and hold, both pages turn */
.together{border:1px solid var(--cloud);border-radius:calc(var(--radius) + 6px);
  background:var(--panel);padding:clamp(24px,4vw,44px);margin-top:clamp(36px,6vh,60px)}
.together .panes{display:grid;grid-template-columns:1fr 1fr;gap:clamp(16px,3vw,32px)}
.together .pane{position:relative;border-radius:14px;overflow:hidden;
  background:var(--canvas2);border:1px solid var(--cloud);aspect-ratio:4/3}
.together .pane .label{position:absolute;top:10px;left:12px;z-index:3;
  font-family:var(--sans);font-size:var(--t-legal);letter-spacing:var(--ls-small);
  color:var(--text-secondary);background:rgba(8,8,15,.55);
  border:1px solid rgba(150,150,190,.3);border-radius:8px;padding:4px 8px;
  backdrop-filter:blur(8px)}
.together .page{position:absolute;inset:0;background-size:cover;background-position:center}
.together .page.next{transform-origin:left center}
.together .page.turning{transform:perspective(1200px) rotateY(calc(var(--hold,0)*-160deg));
  box-shadow:14px 0 34px -12px rgba(0,0,0,.6)}
.together .hint{display:flex;align-items:center;justify-content:center;gap:10px;
  margin-top:18px;color:var(--text-secondary);font-size:15px}
.together .hold-btn{touch-action:none;user-select:none;-webkit-user-select:none}
.together .done-line{text-align:center;font-family:var(--serif);font-weight:var(--w-head);font-size:clamp(18px,2.2vw,24px);
  margin-top:16px;opacity:calc(var(--lit,0));transform:translateY(calc((1 - var(--lit,0))*10px));
  transition:opacity .5s var(--ease-out),transform .5s var(--ease-out)}
@media (max-width:640px){.together .panes{grid-template-columns:1fr}}

/* the storybook page: cream daylight band */
.cream-band{background:linear-gradient(180deg,var(--cream) 0%,var(--cream2) 100%);
  color:var(--day-ink);border-top:1px solid rgba(255,255,255,.06);
  border-bottom:1px solid rgba(255,255,255,.06)}
.cream-band .section h2{color:var(--day-ink)}
.cream-band .section .lede,.cream-band p{color:var(--day-muted)}
/* The night-canvas gold is too light on cream: #A5721E measured 3.21:1 against
   #EFE0C4, a WCAG AA failure for small text. This darker gold of the same hue
   passes at 5.3:1 and still reads as the brand. */
.cream-band .kicker{color:#7A5210}
.cream-band a{color:#7a4c05}
.family-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));
  gap:18px;margin-top:36px}
.family-card{display:block;background:rgba(255,255,255,.55);border:1px solid var(--day-line);
  border-radius:var(--radius);padding:26px 24px;color:var(--day-ink);
  transition:transform .3s var(--ease-out),box-shadow .3s var(--ease-out)}
.family-card:hover{transform:translateY(-4px);box-shadow:0 18px 44px -18px rgba(36,31,61,.35)}
.family-card .micro{color:#7A5210}
.family-card h3{font-family:var(--serif);font-weight:var(--w-head-day);font-size:21px;margin:8px 0 6px}
.family-card p{font-size:15px;line-height:var(--lh-lede)}
.family-card .go{display:inline-block;margin-top:14px;font-weight:600;font-size:14.5px;color:#7a4c05}

/* book rail */
.book-rail{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(150px,190px);
  gap:18px;overflow-x:auto;padding:26px 4px 18px;scroll-snap-type:x mandatory;
  scrollbar-width:thin}
.book-rail img{border-radius:12px;scroll-snap-align:start;
  border:1px solid var(--cloud);aspect-ratio:1;object-fit:cover;
  transition:transform .35s var(--ease-out)}
.book-rail img:hover{transform:translateY(-5px) rotate(-1deg)}

/* keepsake feature */
.keepsake-feature{display:grid;grid-template-columns:minmax(0,6fr) minmax(0,5fr);
  gap:clamp(28px,5vw,64px);align-items:center}
.keepsake-feature .art{border-radius:var(--radius);overflow:hidden;
  border:1px solid var(--cloud);box-shadow:0 30px 80px -32px rgba(0,0,0,.85)}
@media (max-width:820px){.keepsake-feature{grid-template-columns:1fr}}

/* FAQ */
.faq{max-width:760px;margin:36px auto 0}
.faq details{border-bottom:1px solid var(--cloud);padding:4px 0}
.faq summary{cursor:pointer;list-style:none;display:flex;justify-content:space-between;
  align-items:baseline;gap:16px;padding:18px 4px;font-weight:600;font-size:17px}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";font-family:var(--mono);color:var(--accent);
  font-size:20px;transition:transform .3s var(--ease-out)}
.faq details[open] summary::after{transform:rotate(45deg)}
.faq .a{color:var(--text-secondary);padding:0 4px 20px;max-width:64ch}

/* THE FINALE: the family moment the whole page has been describing, shown
   rather than decorated. Replaced a floating half-drawn oval that meant
   nothing to anyone. */
.finale{position:relative;display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);
  gap:clamp(28px,4.5vw,60px);align-items:center}
.finale-art{border-radius:calc(var(--radius) + 6px);overflow:hidden;
  border:1px solid var(--cloud);box-shadow:0 40px 90px -38px rgba(0,0,0,.95)}
.finale-art img{width:100%;display:block}
.finale-words h2{font-family:var(--serif);font-weight:var(--w-head);
  font-size:clamp(27px,3.5vw,44px);line-height:var(--lh-h2);letter-spacing:var(--ls-head);
  text-wrap:balance;margin-top:10px}
.finale-words .lede{margin-top:14px}
.finale-words .btn{margin-top:26px}
@media (max-width:860px){
  .finale{grid-template-columns:1fr;gap:26px;text-align:center}
  .finale-words .lede{margin-left:auto;margin-right:auto}
}

/* footer */
footer{border-top:1px solid var(--cloud);padding:56px clamp(20px,4.5vw,40px) 44px;
  position:relative;overflow:hidden}
.foot{max-width:var(--maxw);margin:0 auto;display:grid;
  grid-template-columns:2fr 1fr 1fr 1fr;gap:32px}
.foot h2,.foot h3,.foot h4{font-family:var(--mono);font-size:var(--t-kicker);letter-spacing:var(--ls-caps);
  text-transform:uppercase;color:var(--text-secondary);margin-bottom:14px}
.foot ul{list-style:none}
.foot li{margin:9px 0}
.foot a{color:var(--text-secondary);font-size:15px}
.foot a:hover{color:var(--text-primary)}
/* .foot .legal carries the ABN line: purchase/legal-relevant, so it sits
   on the 14px floor rather than the old 13.5px */
.foot .legal{grid-column:1/-1;margin-top:26px;padding-top:22px;
  border-top:1px solid var(--cloud);display:flex;flex-wrap:wrap;gap:8px 22px;
  color:var(--text-secondary);font-size:var(--t-legal);align-items:baseline}
.constellation{position:absolute;inset:0;pointer-events:none;opacity:.5}
.constellation i{position:absolute;width:2px;height:2px;border-radius:50%;
  background:#fff;opacity:.5}
.live .constellation i.tw{animation:twinkle 5.5s var(--ease-soft) -2s infinite}
.live .constellation i.tw2{animation:twinkle 7s var(--ease-soft) -4.5s infinite}
@keyframes twinkle{0%,100%{opacity:.25}50%{opacity:.85}}
@media (max-width:760px){.foot{grid-template-columns:1fr 1fr}}

.sound-chip{position:fixed;left:18px;bottom:18px;z-index:90;display:flex;align-items:center;gap:8px;
  background:rgba(8,10,26,.75);border:1px solid var(--cloud2);color:var(--text-secondary);
  font-family:var(--mono);font-size:var(--t-kicker);letter-spacing:.05em;padding:9px 14px;border-radius:999px;
  cursor:pointer;backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);
  transition:color .25s var(--ease-out),border-color .25s var(--ease-out)}
.sound-chip::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--text-faint);
  transition:background .25s var(--ease-out),box-shadow .25s var(--ease-out)}
.sound-chip.on{color:var(--accent);border-color:var(--accent-muted)}
.sound-chip.on::before{background:var(--accent);box-shadow:0 0 8px rgba(255,201,102,.8)}
.sound-chip.remembered::before{background:var(--accent-hover)}
.listen-row .btn{font-size:14.5px;padding:11px 20px}
@media (max-width:720px){.sound-chip{bottom:14px;left:14px}}

/* ------------------------------------------------ reduced motion, complete */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none!important;transition:none!important;transition-delay:0s!important}
  html{scroll-behavior:auto}
  .reveal .part{opacity:1;transform:none}
  .thread path{stroke-dashoffset:0}
  .thread .bead{opacity:1}
  .together .done-line{opacity:1;transform:none}
  .band .w,.band .c{opacity:1;transform:none}
  .blurpair .soft{opacity:0}
}
