/* The home page and How it works: a product page told as you scroll, in the manner of Apple's. White by default, one idea per screen-height part,
   a short bold statement, one line under it, and a picture that stays put (the particle scene) while the words move. Everything here is readable
   at rest, with or without the script: no rule here makes a part's words see-through or hidden. Colours come from site.css. */

.story-page { --mast: 3.6rem; --stage-top: var(--mast); --stage-height: 40svh; }
.story-page .masthead { border-bottom-color: transparent; background: color-mix(in srgb, var(--page) 82%, transparent); }
.story-page main.wide { overflow-x: clip; }
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* ---------------------------------------------------------------- the pinned picture */

.story { position: relative; }
.story-stage { position: sticky; top: var(--stage-top); z-index: 2; height: var(--stage-height); background: var(--page); pointer-events: none; }
.story-stage::after { content: ""; position: absolute; left: 0; right: 0; top: 100%; height: 2.5rem; background: linear-gradient(var(--page), transparent); }
#story-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; opacity: 0; pointer-events: none; }
.story.scene-on #story-canvas { opacity: 1; }
.story.scene-on .story-fallback { visibility: hidden; }
.story-anchor, .story-fallback { position: absolute; top: 0.25rem; bottom: 0.25rem; left: -8%; right: -8%; width: auto; height: auto; pointer-events: none; }
.story-fallback { color: var(--ink-soft); }
@media (prefers-reduced-motion: no-preference) {
  #story-canvas { transition: opacity 900ms ease-out; }
}

/* The still picture of seven homes, shown until the scene runs (and always without WebGL). */
.hero-fallback { position: absolute; inset: 0; width: 100%; height: 100%; }
.fallback-line { fill: none; stroke: var(--accent); stroke-width: 1.4; stroke-linecap: round; opacity: 0.55; }
.fallback-glow { fill: var(--accent); opacity: 0.16; }
.fallback-glow-gold { fill: var(--lamp); opacity: 0.2; }
.fallback-house { fill: none; stroke: var(--ink); stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.fallback-window { fill: var(--lamp); }
@media (prefers-reduced-motion: no-preference) {
  .fallback-window { animation: light-up 900ms ease-out both; }
  .fallback-window:nth-of-type(2n) { animation-delay: 400ms; }
  .fallback-window:nth-of-type(3n) { animation-delay: 800ms; }
}
@keyframes light-up {
  from { fill: var(--surface); }
  to { fill: var(--lamp); }
}

/* ---------------------------------------------------------------- the parts */

.chapter { position: relative; z-index: 1; display: flex; align-items: center; min-height: calc(100svh - var(--mast) - var(--stage-height)); padding-block: 1.5rem; }
.chapter-inner { display: grid; gap: 1.5rem; }
.chapter h1,
.chapter h2 { margin: 0 0 1rem; font-size: clamp(2.35rem, 10vw, 3rem); font-weight: 700; line-height: 1.03; letter-spacing: -0.035em; text-wrap: balance; }
.chapter-line { margin: 0; max-width: 26rem; color: var(--ink-soft); font-size: clamp(1.1rem, 4.4vw, 1.25rem); line-height: 1.4; letter-spacing: -0.012em; text-wrap: balance; }
.chapter-note { margin: 1rem 0 0; max-width: 26rem; color: var(--ink); font-size: clamp(1rem, 4vw, 1.1rem); font-weight: 600; line-height: 1.45; text-wrap: pretty; }
.chapter-hero h1 { font-size: clamp(2.6rem, 11vw, 3.4rem); }
.scroll-cue { display: none; }
.scroll-cue svg { width: 1.6rem; height: 1.6rem; fill: none; stroke: var(--ink-soft); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

/* The home page opens with a whole sentence, not a few words, so its headline is smaller and its second line quieter. */
.chapter-hero-long h1 { font-size: clamp(2.05rem, 8.6vw, 2.7rem); line-height: 1.06; }
.chapter-hero-long .chapter-line { font-size: clamp(1rem, 4vw, 1.1rem); line-height: 1.45; }
.chapter-actions { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 1.25rem; }
.chapter-actions .button, .cta .button { min-height: 3rem; padding-inline: 1.05rem; border-radius: 999px; font-size: 0.95rem; }
/* Commands in a part: the same code block as the guide, a little smaller. */
.chapter .code { max-width: 34rem; margin: 1.1rem 0 0; padding: 0.8rem 0.9rem; font-size: clamp(0.7rem, 2.9vw, 0.8rem); line-height: 1.55; }
.chapter-link { margin: 1rem 0 0; max-width: 34rem; font-size: 1rem; }

/* Where scripts are off there is no scene and the pinned picture cannot change, so it goes and each part carries its own still picture instead.
   Everywhere else the page has its final layout from the first paint, so nothing moves when the script arrives. */
.chapter-still { display: none; margin: 0; }
.chapter-still svg { display: block; width: 100%; max-width: 26rem; height: auto; }
@media (scripting: none) {
  .story-stage { display: none; }
  .chapter-still { display: block; }
  .chapter { min-height: 0; }
}
/* Phones: the picture is pinned above the words, so each part comes to rest just below it instead of scrolling underneath. */
@media (max-width: 55.99rem) {
  html.js-story { scroll-snap-type: y mandatory; }
  .js-story .finale > *, .js-story .colophon { scroll-snap-align: start; }
  .js-story .chapter { scroll-snap-align: start; scroll-margin-top: var(--stage-height); }
  /* The words start at the same place under the picture in every part, rather than floating in the middle of what is left. */
  .chapter { align-items: flex-start; padding-top: 1.75rem; }
  /* Words that have scrolled past go behind a solid bar, so no part of the last heading shows through above the picture. */
  .story-page .masthead { background: var(--page); }
}
.still-house, .s-line, .s-strong, .s-ring, .s-dash, .s-pulse, .s-check, .s-card, .s-rock, .s-blocked-line { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.still-house { stroke: var(--ink); stroke-width: 2.4; }
.still-window { fill: var(--lamp); }
.s-line { stroke: var(--accent); stroke-width: 1.6; opacity: 0.55; }
.s-strong { stroke: var(--accent); stroke-width: 6; }
.s-strong.s-gold { stroke: var(--lamp); }
.s-ring { stroke: var(--accent); stroke-width: 1.6; stroke-dasharray: 2 7; opacity: 0.8; }
.s-dash { stroke: var(--lamp); stroke-width: 2.4; stroke-dasharray: 3 9; }
.s-pulse { stroke: var(--lamp); stroke-width: 3; opacity: 0.8; }
.s-check { stroke: var(--lamp); stroke-width: 6; }
.s-card { stroke: var(--accent); stroke-width: 2.4; stroke-dasharray: 5 6; }
.s-rock { fill: var(--accent-soft); stroke: var(--accent); stroke-width: 2; }
.s-blocked { fill: var(--blocked); opacity: 0.85; }
.s-blocked-line { stroke: var(--blocked); stroke-width: 1.4; opacity: 0.4; }
.s-gold-dot { fill: var(--lamp); }

/* Short phones (an iPhone SE, older Android): a smaller picture and smaller words, so every part still fits under the picture. */
@media (max-width: 55.99rem) and (max-height: 45rem) {
  .story-page { --stage-height: 34svh; }
  .chapter h1, .chapter h2 { margin-bottom: 0.6rem; font-size: clamp(1.8rem, 8.4vw, 2.2rem); }
  .chapter-hero-long h1 { font-size: clamp(1.75rem, 8vw, 2.1rem); }
  .chapter-line, .chapter-hero-long .chapter-line { font-size: 1rem; line-height: 1.35; }
  .chapter-note { margin-top: 0.7rem; font-size: 0.95rem; }
  .chapter-actions { margin-top: 0.9rem; }
  .chapter .code { margin-top: 0.8rem; font-size: 0.68rem; }
  .chapter-link { margin-top: 0.7rem; font-size: 0.95rem; }
}

/* Wide screens: the words on the left, the picture pinned on the right, a screen of height per part. */
@media (min-width: 56rem) {
  /* The picture and the parts share one grid cell, so the picture stays pinned exactly as long as the parts last and lets go before the screens. */
  .story { display: grid; }
  .story-stage { grid-area: 1 / 1; align-self: start; height: calc(100svh - var(--stage-top)); z-index: 0; }
  .story-chapters { grid-area: 1 / 1; min-width: 0; }
  .story-stage::after { display: none; }
  .story-anchor, .story-fallback { top: 6%; bottom: 6%; left: 42%; right: 2%; }
  .story-home .story-anchor, .story-home .story-fallback { left: 40%; }
  .chapter { align-items: center; min-height: calc(100svh - var(--mast)); padding-block: 4rem; }
  .chapter-inner { grid-template-columns: minmax(0, 30rem) minmax(0, 1fr); gap: 3rem; align-items: center; }
  .chapter-hero-long .chapter-inner { grid-template-columns: minmax(0, min(36rem, 42vw)) minmax(0, 1fr); }
  .chapter h1, .chapter h2 { font-size: clamp(2.7rem, 4.6vw, 4.2rem); }
  .chapter-hero h1 { font-size: clamp(3.2rem, 6.2vw, 5.4rem); }
  .chapter-hero-long h1 { font-size: clamp(2.6rem, 4.5vw, 4.1rem); }
  .chapter-line { font-size: clamp(1.2rem, 1.7vw, 1.5rem); }
  .chapter-hero-long .chapter-line { max-width: 30rem; font-size: clamp(1.05rem, 1.35vw, 1.25rem); }
  .chapter-still svg { margin-inline: auto; }
  .scroll-cue { display: block; margin-top: 3rem; }
}

/* Arriving: the opening part fades and rises in by itself, with no script, on a timer that always ends with it in place. The other parts
   only rise a little as they come into view, and they are never see-through: their words show at full strength whether or not the script,
   its observer or the scene ever runs. (They used to start invisible and wait for the observer to fade them in. Where that never happened,
   as on an iPhone in Safari, everything below the opening stayed blank.) */
@media (prefers-reduced-motion: no-preference) {
  .chapter-hero .chapter-copy { animation: arrive 900ms cubic-bezier(0.2, 0.7, 0.2, 1) both; }
  .js-story [data-reveal] { transition: transform 900ms cubic-bezier(0.2, 0.7, 0.2, 1); }
  .js-story [data-reveal]:not(.is-in) { transform: translateY(1.75rem); }
  .scroll-cue svg { animation: cue 2.4s ease-in-out infinite; }
}
@keyframes arrive {
  from { opacity: 0; transform: translateY(1.75rem); }
  to { opacity: 1; transform: none; }
}
@keyframes cue {
  0%, 100% { transform: translateY(0); opacity: 0.4; }
  50% { transform: translateY(0.45rem); opacity: 1; }
}

/* ---------------------------------------------------------------- the end: screens, the call to action and the footer */

/* The page ends by fading from its own colour to a deeper one: white to pale blue, and in dark mode black to #001141. The footer carries it to the edges. */
.finale { background: linear-gradient(var(--page), var(--page-end)); }
.story-page .colophon { background: var(--page-end); box-shadow: 0 0 0 100vmax var(--page-end); clip-path: inset(0 -100vmax); }

.showcase { padding-block: clamp(3.5rem, 10vw, 6rem) clamp(2rem, 6vw, 4rem); text-align: center; }
.showcase-head h2, .cta h2 { margin: 0 0 1rem; font-size: clamp(2.35rem, 8vw, 4.5rem); font-weight: 700; line-height: 1.03; letter-spacing: -0.035em; text-wrap: balance; }
.showcase .chapter-line, .cta .chapter-line { max-width: 32rem; margin-inline: auto; }
.gallery { display: flex; gap: clamp(1.25rem, 3vw, 2.25rem); margin: clamp(2.5rem, 6vw, 4rem) 0 0; padding: 1rem max(var(--gutter), calc((100% - var(--wide)) / 2 + var(--gutter))) 2rem; list-style: none; overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: max(var(--gutter), calc((100% - var(--wide)) / 2 + var(--gutter))); -webkit-overflow-scrolling: touch; text-align: left; }
.shot { flex: 0 0 auto; width: clamp(13rem, 64vw, 17rem); scroll-snap-align: center; }
.shot:nth-child(even) { margin-top: 2.25rem; }
.shot figure { margin: 0; }
.phone { padding: 0.55rem; border-radius: 2.5rem; background: #001141; box-shadow: 0 2.2rem 3.5rem -1.5rem rgba(0, 17, 65, 0.5), inset 0 0 0 2px rgba(255, 255, 255, 0.08); }
.phone img { display: block; width: 100%; height: auto; aspect-ratio: 540 / 960; border-radius: 1.95rem; background: #000000; }
.shot figcaption { margin-top: 1rem; text-align: center; color: var(--ink); font-size: 1rem; font-weight: 600; letter-spacing: -0.012em; }
@media (min-width: 56rem) {
  .gallery { scroll-snap-type: x proximity; margin-top: clamp(1.5rem, 4svh, 3rem); }
  /* The phones are sized by the screen's height, so the heading and the phones fit on one screen. */
  .shot { width: clamp(11rem, 26svh, 17rem); }
}
@media (prefers-reduced-motion: no-preference) {
  .js-story .shot:nth-child(3n + 2) { transition-delay: 90ms; }
  .js-story .shot:nth-child(3n + 3) { transition-delay: 180ms; }
}

.cta { padding-block: clamp(3.5rem, 9vw, 5.5rem) clamp(3.5rem, 9vw, 5.5rem); text-align: center; }
.cta-inner { display: flex; flex-direction: column; align-items: center; }
.ask-block { display: flex; flex-direction: column; align-items: center; width: 100%; max-width: 40rem; margin-top: 1.75rem; }
.cta .ask-actions { justify-content: center; }
.cta .copy-status { min-height: 1.4rem; margin: 0.5rem 0 0; }
.cta .prompt-text { margin-top: 0.5rem; width: 100%; text-align: left; font-size: 0.95rem; border-left-width: 3px; }
.cta .ask-fine { margin: 0.75rem 0 0; color: var(--ink-soft); font-size: 0.9rem; text-wrap: balance; }
.cta .downloads { justify-content: center; margin-top: 2.25rem; }
.cta .download-note { margin: 1rem 0 0; }
.cta .ask-block + .download-note { margin-top: 2.25rem; }
.cta .server-note { max-width: 28rem; margin: 0.5rem 0 0; color: var(--ink-soft); font-size: 0.95rem; text-wrap: balance; }
