/* QuranIsland main landing.
   Layout is written in a 971 px frame. --u turns one frame pixel into CSS px, limited by
   height so a scene's hierarchy survives on wide, short windows. Every section keeps its place
   in normal document flow. With scripts and motion the hero and the chapters after it hold in
   layers while the next slides over them (the end of this file), and the full-page section's own
   pane pins over a bounded track. */

@font-face {
  font-family: "KFGQPC Hafs";
  src: url("assets/kfgqpc_hafs_v30.ttf") format("truetype");
  font-display: block;
}

@font-face {
  font-family: "Literata";
  src: url("assets/fonts/literata/Literata%5Bopsz%2Cwght%5D.ttf") format("truetype");
  font-weight: 200 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Commissioner";
  src: url("assets/fonts/commissioner/Commissioner%5BFLAR%2CVOLM%2Cslnt%2Cwght%5D.ttf") format("truetype");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light;
  --paper: #fefefe;
  --ink: #000;
  --ink-2: #3b3b3d;
  --ink-3: #5a5b5e;
  --rule: #c9c9cb;
  --night: #050506;
  --black: #070708; /* the rim, the notch and every surface that grows from it */
  --serif: "Literata", Georgia, serif;
  --sans: "Commissioner", -apple-system, BlinkMacSystemFont, "Helvetica Neue", Helvetica, Arial, sans-serif;
  --ease-out: cubic-bezier(.16, 1, .3, 1);
}

*, *::before, *::after { box-sizing: border-box; }

html {
  background: var(--paper);
  color: var(--ink);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scrollbar-gutter: stable; /* the lock below never changes the page's width */
}

/* The opening is an event, not a chapter: while it shows, and while the entry it begins plays,
   the page beneath cannot be scrolled. Scripts remove the lock with the opening. */
.js[data-stage="intro"],
.js[data-stage="entering"] { overflow: hidden; overscroll-behavior: none; }
.js[data-stage="intro"] body,
.js[data-stage="entering"] body { overflow: hidden; overscroll-behavior: none; }

body {
  margin: 0;
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis: none;
  overflow-x: clip;
}

/* Stated once and last in importance: the `font` shorthand resets variation settings. Weight
   comes from font-weight and Literata's optical size stays automatic. */
body, body * { font-variation-settings: "slnt" 0, "FLAR" 0, "VOLM" 0 !important; }

::selection { background: #000; color: #fff; }
.reader ::selection,
.fp__surface ::selection,
.opening ::selection { background: #fff; color: #000; }

img, svg { display: block; }
button { font: inherit; color: inherit; }
p, h1, h2, h3, ul { margin: 0; }
ul { padding: 0; list-style: none; }
a { color: inherit; text-underline-offset: .18em; text-decoration-thickness: 1px; }
kbd { font: inherit; }

:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 4px; }
main:focus, h1:focus, .reader:focus { outline: none; }

.sprite { position: absolute; }

.sr-only {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip {
  position: absolute;
  z-index: 40;
  top: 22px;
  left: 16px;
  padding: 10px 14px;
  border-radius: 999px;
  background: #fff;
  color: #000;
  font-size: 14px;
  text-decoration: none;
  transform: translateY(-200%);
}
.skip:focus { transform: none; }

/* ---------- Review switch: beside or centered nudge text ----------
   A requested review control, shown by app.js only with ?review; not product navigation. Small
   and quiet, above the chapter stack, with no shade. The hidden attribute keeps it gone, and it
   stays out of the way while the opening plays. */
.layout-review {
  position: fixed;
  z-index: 50;
  right: 16px;
  bottom: 16px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 8px 6px 12px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: rgb(254 254 254 / .92);
  color: var(--ink-2);
  font: 500 13px / 1 var(--sans);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}
.layout-review[hidden] { display: none; }
[data-stage="intro"] .layout-review,
[data-stage="opening"] .layout-review,
[data-stage="entering"] .layout-review,
:root:has(.opening.is-overlay) .layout-review { display: none; }

.layout-review__label { white-space: nowrap; }

.layout-review__options { display: inline-flex; gap: 2px; }

.layout-review button {
  min-height: 30px;
  padding: 0 12px;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--ink-2);
  cursor: pointer;
  transition: background-color 120ms ease, color 120ms ease;
}
.layout-review button:hover { background: rgb(0 0 0 / .06); color: var(--ink); }
.layout-review button[aria-pressed="true"] { background: var(--ink); color: #fff; }
.layout-review button:focus-visible { outline-offset: 1px; }

@media (max-width: 719px) { /* a media query: the aside sits outside main and the page container */
  .layout-review {
    right: 50%;
    bottom: 12px;
    max-width: calc(100% - 24px);
    transform: translateX(50%);
  }
  .layout-review button { min-height: 44px; }
}

/* ---------- Units ---------- */

.page { container: page / inline-size; }

/* Keep oversized mockups inside the chapter stack when it ends above the footer.
   Clip preserves the viewport as the scroll container for the sticky chapters. */
.page > main { overflow: clip; }

main, .foot {
  --u: min(calc(100cqw / 971), calc(100svh / 640), 1.62px);
  --hero-scale: .86;
  --frame: calc(971 * var(--u));
  --edge-gap: max(calc((100cqw - var(--frame)) / 2), 0px);
  --side: calc(var(--edge-gap) + 56 * var(--u));
}

@supports not (width: 1cqw) {
  main, .foot {
    --u: min(calc(100vw / 971), calc(100svh / 640), 1.62px);
    --edge-gap: max(calc((100vw - var(--frame)) / 2), 0px);
  }
}

/* ---------- Opening: the same display, straight on, asleep ----------
   A fixed layer over the page, never a section of it: it takes no document height, so nothing
   can scroll back to it, and app.js removes it once the entry has played or a direct link has
   retired it. Without scripts it is an ordinary first screen with a link onward. */

.opening {
  position: relative;
  height: 100svh;
  min-height: 440px;
  overflow: hidden;
  color: #fff;
}

/* With scripts it is a fixed layer over the page, never a section of it. */
.js .opening {
  position: fixed;
  inset: 0;
  z-index: 30;
  height: 100svh;
  min-height: 0;
}

/* Only while the entry plays, and only for the prompt: the hero's own display has taken over
   from the drawn edge. The element is removed as soon as the entry ends. */
.opening.is-overlay { pointer-events: none; }
.opening.is-overlay .opening__night,
.opening.is-overlay .edge { visibility: hidden; }

.opening__night {
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, #0d0d0f 0, var(--night) calc(330 * var(--u)));
}

.edge {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: calc(12 * var(--u) * var(--hero-scale));
  background: var(--black);
  box-shadow: inset 0 calc(1.1 * var(--u) * var(--hero-scale)) 0 #b9babe, inset 0 calc(2.4 * var(--u) * var(--hero-scale)) 0 #2b2b2f;
}

.edge__notch {
  position: absolute;
  top: calc(11.5 * var(--u) * var(--hero-scale));
  left: calc(50% - 142 * var(--u) * var(--hero-scale));
  width: calc(284 * var(--u) * var(--hero-scale));
  height: calc(60 * var(--u) * var(--hero-scale));
}

.opening__notch {
  position: absolute;
  z-index: 1;
  top: 0;
  left: 50%;
  width: calc(300 * var(--u));
  min-width: 160px;
  height: calc(74 * var(--u));
  min-height: 56px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  transform: translateX(-50%);
}

.opening__prompt {
  position: absolute;
  inset: calc(78 * var(--u)) 0 0;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 12px;
  padding: 0 20px 4svh;
}

.begin {
  display: grid;
  justify-items: center;
  padding: 10px 18px;
  border: 0;
  border-radius: 14px;
  background: none;
  color: #fff;
  cursor: pointer;
}
.opening .begin:focus-visible { outline-color: #fff; }

.begin__lead {
  font: 500 max(44px, calc(78 * var(--u))) / 1.05 var(--serif);
  letter-spacing: -.025em;
}

/* Generated PNG artwork, delivered as compressed copies. These windows map the canvases to measured
   visible bounds with 12 native pixels of safety margin; CSS draws no key face. */
.key-art {
  position: relative;
  display: block;
  flex: none;
  aspect-ratio: var(--crop-width) / var(--crop-height);
  overflow: hidden;
  pointer-events: none;
  user-select: none;
}

.key-art img {
  position: absolute;
  left: calc(-100% * var(--crop-x) / var(--crop-width));
  top: calc(-100% * var(--crop-y) / var(--crop-height));
  width: calc(100% * 2048 / var(--crop-width));
  height: calc(100% * 768 / var(--crop-height));
  max-width: none;
}

.begin__key {
  --key-height: max(58px, calc(64 * var(--u)));
  --crop-x: 43;
  --crop-y: 244;
  --crop-width: 1965;
  --crop-height: 294;
  width: min(calc(var(--key-height) * 1965 / 270), 78cqw);
  margin-top: calc(26 * var(--u));
  transition: transform 110ms var(--ease-out), filter 140ms ease;
}

.begin:hover .begin__key,
.opening__notch:hover ~ .opening__prompt .begin__key {
  filter: brightness(1.12);
}

.begin:active .begin__key,
.opening.is-pressed .begin__key {
  transform: translateY(3px);
}

.begin__or {
  margin-top: calc(24 * var(--u));
  color: rgb(255 255 255 / .8);
  font: 500 max(14px, calc(15.5 * var(--u))) / 1.3 var(--sans);
  text-decoration: underline;
  text-underline-offset: .28em;
}

.for-touch { display: none; }

@media (hover: none) and (pointer: coarse) {
  .for-keys, .begin__key { display: none; }
  .for-touch { display: inline; }
  .begin { padding: 14px 28px; }
}

.opening__continue { display: none; color: #fff; font-size: 16px; }
.no-js .opening__continue { display: block; }
.no-js .begin, .no-js .opening__notch { display: none; }

/* ---------- Hero ---------- */

/* The one mark in normal flow that app.js measures the chapters from. It holds nothing. */
.anchor { height: 0; }

/* The chapter's height is the frame's, plus whatever the open reader reserves: it never grows
   with the window, so a tall pane shows the next chapter below it rather than empty desktop.
   The straight-on display of the entry belongs to the fixed opening, not to this chapter. */
.hero {
  position: relative;
  min-height: max(calc(820 * var(--u)), var(--reserve, 0px));
  overflow: clip;
  background: var(--paper);
}

.hero__frame {
  position: relative;
  z-index: 3;
  width: var(--frame);
  margin: 0 auto;
  padding: calc(46 * var(--u)) 0 0 calc(56 * var(--u));
  pointer-events: none;
}
.hero__frame > * { pointer-events: auto; }

.hero h1 {
  width: max-content;
  font: 500 calc(72 * var(--u)) / calc(69 * var(--u)) var(--serif);
  letter-spacing: -.025em;
  font-kerning: normal;
}

.hero__lede {
  width: max-content;
  max-width: 100%;
  margin-top: calc(14 * var(--u));
  font: 400 max(16px, calc(22.5 * var(--u))) / 1.25 var(--sans);
}

.reopen {
  display: block;
  min-height: 40px;
  margin-top: calc(4 * var(--u));
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font: 500 max(15px, calc(15.5 * var(--u))) / 1 var(--sans);
  text-decoration: underline;
  text-underline-offset: .24em;
  cursor: pointer;
}
.reopen[hidden] { display: none; }
.no-js .reopen { display: none; }

.hero__note { display: none; margin-top: 12px; color: var(--ink-2); font-size: 15px; }
.no-js .hero__note { display: block; }

/* ---------- The Mac's display: one plane ----------
   The lid's edge, the thin black rim, the desktop, the notch and whatever grows from it are
   children of .screen, under one transform. Right is near and verticals stay vertical, as
   in the reference photograph: rotateY about the camera's axis, seen from below the rim.
   The numbers match PLANE in landing-core.mjs. */

.rig {
  --pu: calc(var(--u) * var(--hero-scale));
  --tilt: -18deg;
  --depth: calc(1439 * var(--pu));
  --horizon: calc(1085 * var(--pu));
  --half: calc(340 * var(--pu));
  --cam-local: calc(1400 * var(--pu));
  --cam-x: calc(50% - 8.5 * var(--u));
  --rim-y: calc(262 * var(--u));
  --back-h: max(calc(760 * var(--pu)), 41cqw); /* cover the deeper crop without stretching the display */
  position: absolute;
  inset: 0;
  z-index: 1;
}

/* During the turn the display passes in front of the headline. */
[data-stage="entering"] .rig { z-index: 4; }

/* Keep the chapter's flow height fixed through the reveal. Its clip opens over the following
   chapters, then retreats with the tilt; finishing the entry never moves those chapters. */
.js[data-stage="entering"] .hero { overflow: visible; z-index: 4; will-change: clip-path; }
[data-stage="entering"] #hero-wallpaper { will-change: transform; }
#hero-wallpaper { transform-origin: 50% 0; }

.screen {
  --bezel: calc(12 * var(--pu));
  --fillet: calc(16 * var(--pu));
  --radius: calc(34 * var(--pu));
  position: absolute;
  top: var(--rim-y);
  left: calc(var(--cam-x) - var(--cam-local));
  width: calc(2800 * var(--pu));
  /* A real 16:10 lid, sized from its width alone. The chapter crops it; a tall window never
     stretches it. */
  height: calc(1750 * var(--pu));
  border-radius: calc(30 * var(--pu)) calc(30 * var(--pu)) 0 0;
  background: var(--black);
  box-shadow: inset 0 0 0 calc(1.1 * var(--pu)) #b9babe, inset 0 0 0 calc(2.4 * var(--pu)) #2b2b2f;
  transform: perspective(var(--depth)) rotateY(var(--tilt));
  transform-origin: var(--cam-local) var(--horizon);
}

.screen__display {
  position: absolute;
  inset: var(--bezel) var(--bezel) 0;
  overflow: hidden;
  border-radius: calc(18 * var(--pu)) calc(18 * var(--pu)) 0 0;
  background: #8f9092;
}

.screen__backdrop {
  position: absolute;
  top: 0;
  left: calc(var(--cam-local) - var(--bezel) - 1.5 * var(--back-h));
  width: calc(3 * var(--back-h));
  max-width: none;
  height: var(--back-h);
  filter: blur(calc(1.6 * var(--pu)));
}

/* The display asleep, matching the opening, until the entry wakes it. */
.screen__off {
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, #0d0d0f 0, var(--night) calc(330 * var(--pu)));
  opacity: 0;
  pointer-events: none;
}

.screen__notch {
  position: absolute;
  z-index: 2;
  top: calc(11.5 * var(--pu));
  left: calc(var(--cam-local) - 142 * var(--pu));
  width: calc(284 * var(--pu));
  height: calc(60 * var(--pu));
  pointer-events: none;
}

/* ---------- Reader: one black surface with the rim and notch ----------
   Its top edge is the display's top edge, so nothing separates it from the camera. Its width
   includes a fillet each side for the shoulders app.js cuts; only that outline ever moves. */

.reader {
  position: absolute;
  z-index: 1;
  top: 0;
  left: calc(var(--cam-local) - var(--bezel) - var(--half) - var(--fillet));
  display: flex;
  width: calc(2 * (var(--half) + var(--fillet)));
  min-height: calc(300 * var(--pu));
  padding: 0 var(--fillet);
  border-radius: 0 0 var(--radius) var(--radius);
  background: var(--black);
  color: #fff;
}
.reader[hidden] { display: none; }

.reader__inner {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-width: 0;
  padding: calc(72 * var(--pu)) calc(26 * var(--pu)) 0;
}

.reader__text { display: grid; flex: 1; align-content: center; min-height: calc(64 * var(--pu)); }

.reader__ayah {
  font-family: "KFGQPC Hafs";
  font-size: calc(35 * var(--pu));
  line-height: 1.72;
  text-align: center;
  overflow-wrap: break-word;
}
.reader[data-long] .reader__ayah { font-size: calc(30 * var(--pu)); }

.reader__message {
  color: rgb(255 255 255 / .78);
  font: 400 max(14px, calc(15 * var(--pu))) / 1.4 var(--sans);
  text-align: center;
}

.reader__excerpt {
  margin-top: calc(10 * var(--pu));
  font: 400 max(15px, calc(21 * var(--pu))) / 1.25 var(--sans);
  text-align: center;
}
.reader__excerpt[hidden] { display: none; }
.reader__excerpt q { quotes: none; }

.reader__bar {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  align-items: center;
  min-height: calc(46 * var(--pu));
  margin-top: calc(14 * var(--pu));
  border-top: 1px solid rgb(255 255 255 / .14);
}

.reader__nav,
.reader__close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  min-height: 40px;
  padding: 0 6px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: rgb(255 255 255 / .8);
  font: 500 max(13px, calc(14.5 * var(--pu))) / 1 var(--sans);
  cursor: pointer;
  transition: background-color 140ms ease, color 140ms ease;
}

.reader__nav svg {
  flex: none;
  width: max(14px, calc(16 * var(--pu)));
  height: max(14px, calc(16 * var(--pu)));
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.reader__nav:hover,
.reader__close:hover { background: rgb(255 255 255 / .1); color: #fff; }
.reader__nav[aria-disabled="true"] { color: rgb(255 255 255 / .34); cursor: default; }
.reader__nav[aria-disabled="true"]:hover { background: none; color: rgb(255 255 255 / .34); }

.reader__close { gap: 8px; }
.reader__close kbd {
  padding: 2px 6px;
  border: 1px solid rgb(255 255 255 / .46);
  border-radius: 5px;
  font-size: .84em;
}

.reader :focus-visible { outline: 2px solid #fff; outline-offset: -2px; }

/* The same reader under the lower camera. Absolute on the display, so it never moves the page,
   and never taller than the display: a long ayah scrolls inside it rather than leaving the lid.
   Its notch is drawn smaller there, so its text begins closer to the top. */
.reader--local { --half: calc(400 * var(--pu)); max-height: 100%; }
.reader--local .reader__inner { padding-top: calc(40 * var(--pu)); }
.reader--local .reader__text { min-height: 0; overflow-y: auto; }
.reader--local .reader__ayah { font-size: max(20px, calc(35 * var(--pu))); }
.reader--local[data-long] .reader__ayah { font-size: max(19px, calc(30 * var(--pu))); }

/* ---------- Full page: original page inside photographic PNG hardware ----------
   The PNG supplies the complete laptop. Live text and original page artwork sit inside its
   transparent display opening; only that app surface expands and contracts. */

.fp {
  --chapter: var(--paper); /* white, like the nudge: one plane, no edge or shade between them */
  --photo-u: calc((100cqw - 100px) / 1082);
  --ref: calc(1082 * var(--photo-u) / 1440);
  --fp-height: calc(661 * var(--photo-u)); /* the transparent display opening */
  --fp-wide: calc(1180 * var(--photo-u)); /* layout width of the display and bezel */
  --fp-foot-h: max(calc(56 * var(--ref)), 48px);
  --fp-clear: calc(48 * var(--ref));
  --fp-compact: min(calc(1440 * var(--ref) - 24px), max(calc(760 * var(--ref)), 640px));
  /* The reading column: the fitted 345:550 page with a generous gutter each side. */
  --fp-column: calc((var(--fp-height) - var(--fp-clear) - var(--fp-foot-h) - 12 * var(--ref)) * 345 / 550 + 120 * var(--ref));
  position: relative; /* paints over the nudge's keyboard without scripts, as the next chapter */
  overflow: clip;
  padding: calc(64 * var(--u)) 20px calc(64 * var(--u));
  background: var(--chapter);
}

/* Head, caption, then the Mac, so the keyboard below the lid meets only the chapter's own edge. */
.fp__pin {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  overflow: visible; /* the full-width chapter clips the photograph, not this inset layout box */
}

/* The chapter's own words, set like the nudge's, centred over the Mac. */
.fp__head {
  max-width: calc(760 * var(--u));
  margin-inline: auto;
  text-align: center;
}

.fp h2 {
  font: 500 calc(64 * var(--u)) / 1.02 var(--serif);
  letter-spacing: -.025em;
  font-kerning: normal;
  text-wrap: balance;
}

.fp__body {
  max-width: 44ch;
  margin: calc(14 * var(--u)) auto 0;
  color: var(--ink-2);
  font: 400 max(16px, calc(20 * var(--u))) / 1.3 var(--sans);
}

/* The whole image can pass under the chapter edge; this box only reserves the lid's room. */
.fp__stage {
  --pu: var(--photo-u);
  --cam-local: 50%;
  --back-h: var(--fp-height);
  position: relative;
  width: var(--fp-wide);
  height: calc(750 * var(--photo-u)); /* the visible lid; the keyboard continues below it */
  overflow: visible;
  order: 1; /* last in the chapter: only the full-bleed edge cuts the keyboard */
  margin: calc(40 * var(--u)) auto 0;
  margin-inline: calc((100% - var(--fp-wide)) / 2);
}

/* The plane the script turns. Its origin is the Mac's own centre. */
.mac {
  position: relative;
  width: 100%;
  height: 100%;
}
.fp__stage > .mac {
  top: calc(-50 * var(--photo-u)); /* remove the PNG's empty top margin; keep the lower bezel in view */
  left: calc(-178 * var(--photo-u));
  width: calc(1536 * var(--photo-u));
  height: calc(1024 * var(--photo-u));
}

/* Hardware is a generated PNG, including the bezel, camera, keyboard and chassis. This
   invisible rectangle only positions live content in its transparent display opening. */
.screen--flat {
  --bezel: 0px;
  position: absolute;
  top: calc(87 * var(--photo-u));
  left: calc(227 * var(--photo-u));
  width: calc(1082 * var(--photo-u));
  height: calc(661 * var(--photo-u));
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  transform: none;
  transform-origin: 0 0;
}
.screen--flat .screen__display { inset: 0; border-radius: 0; }
.mac__hardware {
  position: absolute;
  z-index: 4;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  pointer-events: none;
  user-select: none;
}

/* The reader's surface. Its outline is the clip the script writes; its backing is the veil
   beneath everything else, solid while compact and thinned over the desktop once the page has
   the whole display. The ink and controls above it are never made translucent. */
.fp__surface {
  position: absolute;
  z-index: 1;
  inset: 0;
  color: #fff;
}
.fp__surface[hidden] { display: none; }

.fp__veil {
  position: absolute;
  inset: 0;
  background: var(--black);
}

.fp__compact {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  width: var(--fp-compact);
  max-height: calc(100% - 12px);
  margin-inline: auto;
  padding: var(--fp-clear) calc(28 * var(--ref)) calc(var(--fp-foot-h) + 10px);
}
.fp__compact[hidden] { display: none; }

.fp__compact-inner { display: grid; gap: calc(8 * var(--ref)); }

/* A long ayah wraps and scrolls here. Its glyphs are never scaled or clipped. */
.fp__text { max-height: calc(var(--fp-height) - var(--fp-foot-h) - var(--fp-clear) - 96px); overflow-y: auto; }
.fp__text .reader__ayah { font-size: max(23px, calc(34 * var(--ref))); line-height: 1.75; }

.fp__error {
  color: rgb(255 255 255 / .86);
  font: 400 max(14px, calc(15 * var(--ref))) / 1.4 var(--sans);
  text-align: center;
}
.fp__error[hidden] { display: none; }

/* Laid out at its final size before it is revealed, so nothing resizes under the outline. */
.fp__page {
  position: absolute;
  top: var(--fp-clear);
  bottom: calc(var(--fp-foot-h) + 12 * var(--ref));
  left: 0;
  right: 0;
  will-change: opacity;
}
.fp__page[hidden] { display: none; }

/* The reading column covers the wallpaper at 98.2% combined opacity over the .7 veil,
   giving the verses a nearly solid backing while the side gutters keep their translucency. */
.fp__page::before {
  content: "";
  position: absolute;
  top: calc(-1 * var(--fp-clear));
  bottom: calc(-1 * (var(--fp-foot-h) + 12 * var(--ref)));
  left: 50%;
  width: min(100%, var(--fp-column));
  background: rgb(7 7 8 / .94);
  transform: translateX(-50%);
}

.fp__sheet { position: absolute; inset: 0; }

/* The native reader's dark page: the publisher's ink, inverted as a whole, with one quiet
   backdrop behind the selected ayah. The whole 345:550 page is always in view. */
.fp__sheet svg {
  display: block;
  width: 100%;
  height: 100%;
  background: transparent;
  filter: grayscale(1) invert(1);
  pointer-events: none;
}

.fp__selected { fill: #000; fill-opacity: .18; }

.fp__waiting {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: rgb(255 255 255 / .78);
  font: 400 max(14px, calc(15 * var(--ref))) / 1.4 var(--sans);
}
.fp__waiting[hidden] { display: none; }

/* The app's footer. It rides the surface's lower edge, so its controls stay on the black and
   the toggle keeps its node and its focus through every mode. */
.fp__foot {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  align-items: center;
  gap: 2px;
  width: var(--fp-compact);
  min-height: var(--fp-foot-h);
  margin-inline: auto;
  padding: 0 12px;
  border-top: 1px solid rgb(255 255 255 / .14);
}

.fp__foot button { min-width: 44px; min-height: 44px; }

.fp__where {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  color: rgb(255 255 255 / .72);
  font: 400 max(12px, calc(14 * var(--ref))) / 1.25 var(--sans);
  font-variant-numeric: tabular-nums;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fp__number::before { content: " · "; }
.fp__number[hidden] { display: none; }

.fp__toggle {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 7px;
  padding: 0 8px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: #fff;
  font: 600 max(13px, calc(14.5 * var(--ref))) / 1 var(--sans);
  cursor: pointer;
  transition: background-color 140ms ease;
}
.fp__toggle:hover { background: rgb(255 255 255 / .1); }
.fp__mode-short { display: none; }
.fp__toggle[aria-disabled="true"] { color: rgb(255 255 255 / .34); cursor: default; }
.fp__toggle[aria-disabled="true"]:hover { background: none; }

.fp__toggle svg {
  flex: none;
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.fp__in, .fp__toggle[aria-expanded="true"] .fp__out { display: none; }
.fp__toggle[aria-expanded="true"] .fp__in { display: inline; }

.fp__surface :focus-visible { outline: 2px solid #fff; outline-offset: -2px; }

/* Sources stay with the chapter copy, clear of the keyboard that continues below the lid. */
.fp__under {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  min-height: 44px;
  margin-top: calc(28 * var(--u));
}

.fp__caption { color: var(--ink-3); font-size: max(13px, calc(15 * var(--u))); }

.fp__open { flex: none; margin-top: 0; }

.fp__static {
  position: absolute;
  inset: var(--fp-clear) 16px 8px;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  gap: 8px;
  justify-items: center;
  font-size: 14px;
  text-align: center;
}
.fp__static img { width: auto; height: 100%; min-height: 0; filter: grayscale(1) invert(1); }

.no-js .fp__compact, .no-js .fp__page, .no-js .fp__foot { display: none; }

/* ---------- Nudge: photographic display left, live invitation fitted into its screen ----------
   Preserve the full lid; the next chapter covers its keyboard. Phones use the front PNG. */

.nudge {
  --nudge-room: min(calc(100cqw - 48px), 1800px);
  --nudge-photo: calc((var(--nudge-room) - 24px) * .74);
  position: relative;
  display: grid;
  grid-template-columns: var(--nudge-photo) minmax(0, 1fr);
  grid-template-areas: "device copy";
  align-items: center;
  column-gap: 24px;
  min-height: calc(600 * var(--u));
  padding: calc(72 * var(--u)) max(24px, calc((100cqw - var(--nudge-room)) / 2)) 0;
  overflow: clip visible; /* the angled keyboard runs under the next chapter, never off the page's side */
  background: var(--paper);
}

/* The copy reads first in the DOM; on a desktop it stands at the right of the Mac. */
.nudge__copy {
  grid-area: copy;
  position: relative;
  z-index: 1; /* the photographed hardware passes beneath the words, never over them */
  width: max-content;
  max-width: 100%;
  justify-self: start;
}

.nudge h2 {
  font: 500 calc(52 * var(--u)) / calc(52 * var(--u)) var(--serif);
  letter-spacing: -.025em;
}

.nudge__sub {
  margin-top: calc(10 * var(--u));
  font: 500 calc(26 * var(--u)) / 1.15 var(--serif);
  letter-spacing: -.025em;
  text-wrap: balance; /* one line when it fits; otherwise "Only if you / want it.", never "it." alone */
}

.nudge__body {
  margin-top: calc(14 * var(--u));
  font: 400 max(15px, calc(18 * var(--u))) / 1.4 var(--sans);
  text-wrap: balance;
}

.nudge__preview {
  display: block;
  min-height: 40px;
  margin-top: calc(22 * var(--u));
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font: 500 max(15px, calc(17 * var(--u))) / 1 var(--sans);
  text-decoration: underline;
  text-underline-offset: .26em;
  cursor: pointer;
}
.nudge__preview:disabled { color: var(--ink-3); text-decoration: none; cursor: default; }
.no-js .nudge__preview { display: none; }

/* Scale from the lid, letting the much wider keyboard continue under the next chapter. */
.nudge__device {
  --photo-u: min(calc(var(--nudge-photo) / 946), calc((100svh - 144 * var(--u)) / 750));
  --pu: var(--photo-u);
  --half: calc(240 * var(--pu));
  --cam-local: calc(535 * var(--photo-u));
  --back-h: calc(661 * var(--photo-u));
  grid-area: device;
  position: relative;
  width: calc(946 * var(--photo-u));
  max-width: none;
  height: calc(750 * var(--photo-u)); /* the lid; the keyboard flows on below, cut only by the next chapter */
  overflow: visible;
  margin-left: 0;
  justify-self: start;
}
.nudge__device > .mac {
  left: calc(-61 * var(--photo-u));
  width: calc(1536 * var(--photo-u));
  height: calc(1024 * var(--photo-u));
  transform: none;
}
/* The angled PNG already contains the perspective. app.js maps the live display to its
   photographed four corners; the physical computer is never drawn by CSS. */
.nudge__device .screen--flat {
  top: 0;
  left: 0;
  width: calc(1080 * var(--photo-u));
  height: calc(658 * var(--photo-u));
}
/* The photo's transparent opening extends a few pixels beyond its four measured corners.
   An underlap inside the photographed bezel prevents the white page showing through there. */
.nudge__device .screen--flat::before {
  content: "";
  position: absolute;
  inset: calc(-12 * var(--photo-u));
  background: var(--black);
}
.no-js .nudge__device .screen--flat { display: none; }

/* ---------- Centered text layout (review switch) ----------
   The heading and its lines centred above a fitted Mac, which keeps its turn and stands a
   little left of centre, so its direction still contrasts with the hero. The chapter's
   min-height is shared with the beside layout. */

[data-copy-layout="centered"] .nudge {
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "copy" "device";
  align-content: center;
  justify-items: center;
  row-gap: calc(52 * var(--u));
  padding-block: calc(48 * var(--u));
}

[data-copy-layout="centered"] .nudge__copy {
  justify-self: center;
  text-align: center;
}

[data-copy-layout="centered"] .nudge__body { max-width: 46ch; margin-inline: auto; }
[data-copy-layout="centered"] .nudge__preview { margin-inline: auto; }
[data-copy-layout="centered"] .nudge h2 br { display: none; }

[data-copy-layout="centered"] .nudge__device {
  --photo-u: calc(min(var(--nudge-room), 1200px) / 946);
  justify-self: center;
  margin-left: 0;
}

/* The photographed camera stays above the live invitation and reader. */

.cue {
  position: absolute;
  z-index: 1;
  top: 0;
  left: calc(var(--cam-local) - var(--bezel) - var(--half) - var(--fillet));
  display: block;
  width: calc(2 * (var(--half) + var(--fillet)));
  min-height: calc(140 * var(--pu)); /* a quiet invitation, not a sheet; --half stays, app.js measures it */
  border-radius: 0 0 var(--radius) var(--radius);
  background: var(--black);
  color: #fff;
  text-decoration: none;
}
.cue:focus-visible { outline: 2px solid #fff; outline-offset: -5px; border-radius: 0 0 var(--radius) var(--radius); }

.cue__inner {
  display: grid;
  justify-items: center;
  gap: calc(12 * var(--pu));
  padding: calc(42 * var(--pu)) var(--fillet) calc(18 * var(--pu));
}

.cue__title { font: 500 max(18px, calc(36 * var(--pu))) / 1.2 var(--sans); }

.cue__action {
  padding: calc(8 * var(--pu)) calc(20 * var(--pu));
  border: 1px solid rgb(255 255 255 / .3);
  border-radius: calc(9 * var(--pu));
  background: rgb(255 255 255 / .1);
  color: rgb(255 255 255 / .86);
  font: 500 max(15px, calc(26 * var(--pu))) / 1.3 var(--sans);
  transition: background-color 140ms ease;
}
.cue:hover .cue__action { background: rgb(255 255 255 / .18); }

/* ---------- Close ---------- */

.cta {
  display: grid;
  justify-items: center;
  padding: calc(84 * var(--u)) 24px calc(66 * var(--u));
  background: var(--paper);
  text-align: center;
}

.cta h2 {
  font: 500 calc(70 * var(--u)) / 1 var(--serif);
  letter-spacing: -.025em;
  text-wrap: balance;
}

.cta__line {
  margin-top: calc(16 * var(--u));
  font: 400 max(17px, calc(25 * var(--u))) / 1.25 var(--sans);
}

/* The companion PNG carries its Apple logo and label. The live button owns focus,
   the release gate and the unavailable text, independently of the artwork. */
.cta__action {
  --key-height: max(58px, calc(64 * var(--u)));
  position: relative;
  display: block;
  width: min(calc(var(--key-height) * 1437 / 267), 100%);
  min-height: 44px;
  margin-top: calc(30 * var(--u));
  padding: 0;
  border: 0;
  border-radius: max(10px, calc(12 * var(--u)));
  background: none;
  color: var(--ink);
  font: 400 max(16px, calc(18 * var(--u))) / 1.3 var(--sans);
  cursor: pointer;
  transition: transform 110ms var(--ease-out), filter 140ms ease;
}

.cta__art {
  --crop-x: 306;
  --crop-y: 239;
  --crop-width: 1437;
  --crop-height: 291;
  width: 100%;
}

.cta__action:not([aria-disabled="true"]):hover { filter: brightness(1.12); }

.cta__action:not([aria-disabled="true"]):active {
  transform: translateY(3px);
}

.cta__action:focus-visible { outline-offset: 4px; }
.cta__action[aria-disabled="true"] { opacity: .58; cursor: default; }
.cta__action[data-unavailable="true"] {
  width: auto;
  max-width: 100%;
  min-height: 58px;
  padding: 14px 20px;
  border: 1px solid var(--rule);
  opacity: 1;
}
.no-js .cta__action, .no-js .cta__meta { display: none; }

.cta__meta {
  margin-top: calc(18 * var(--u));
  color: var(--ink-3);
  font-size: max(13px, calc(15 * var(--u)));
  font-variant-numeric: tabular-nums;
}
.cta__meta[hidden] { display: none; }
.cta__meta + .cta__meta { margin-top: 2px; }

.cta__fallback { margin-top: 20px; color: var(--ink-2); font-size: 15px; }

.cta__panel {
  display: grid;
  justify-items: center;
  gap: 6px;
  max-width: 62ch;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--rule);
  color: var(--ink-2);
  font-size: max(14px, calc(14.5 * var(--u)));
  line-height: 1.5;
}
.cta__panel[hidden] { display: none; }

.cta__actions { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px 16px; margin-top: 8px; }

.text-button {
  min-height: 40px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  text-decoration: underline;
  text-underline-offset: .22em;
  cursor: pointer;
}

.cta__file {
  display: inline-flex;
  align-items: center;
  min-height: 42px;
  padding: 0 18px;
  border-radius: 9px;
  background: linear-gradient(to bottom, #2c2d31, #0d0d0f);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / .17), 0 3px 0 #3a3b3f;
  color: #fff;
  font: 600 14px / 1 var(--sans);
  text-decoration: none;
  transition: transform 110ms var(--ease-out), box-shadow 110ms var(--ease-out);
}
.cta__file:hover { background: linear-gradient(to bottom, #393a3f, #18191c); }
.cta__file:active { box-shadow: inset 0 1px 0 rgb(255 255 255 / .1), 0 1px 0 #3a3b3f; transform: translateY(2px); }
.cta__file:focus-visible { border-radius: 9px; }

/* ---------- Footer ---------- */

.foot {
  position: relative;
  margin: 0 var(--side);
  padding: calc(14 * var(--u)) 0 calc(20 * var(--u));
  border-top: 1px solid #b5b5b7;
  color: var(--ink-2);
  font: 400 max(13px, calc(13.5 * var(--u))) / 1.5 var(--sans);
}

.foot__mark {
  position: absolute;
  top: calc(14 * var(--u));
  left: 0;
  display: flex;
  align-items: center;
  min-height: 40px;
  color: var(--ink);
  font: 600 max(19px, calc(22 * var(--u))) / 1 var(--serif);
  font-variation-settings: "opsz" 48 !important;
  letter-spacing: -.035em;
}

.foot__feedback {
  display: flex;
  align-items: center;
  gap: 7px;
  width: max-content;
  min-height: 40px;
  margin-left: auto;
  color: var(--ink-2);
  text-decoration: none;
}
.foot__feedback:hover { color: var(--ink); text-decoration: underline; }

.sources summary {
  display: flex;
  align-items: center;
  gap: 8px;
  width: max-content;
  min-height: 40px;
  margin-left: auto;
  color: var(--ink-2);
  cursor: pointer;
  list-style: none;
}
.sources summary::-webkit-details-marker { display: none; }
.sources summary:hover { color: var(--ink); }
.sources__mark { transition: transform 160ms var(--ease-out); }
.sources[open] .sources__mark { transform: rotate(90deg); }

.sources__body {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: calc(32 * var(--u));
  padding-top: calc(14 * var(--u));
}

.sources h2 {
  margin-bottom: 6px;
  color: var(--ink);
  font: 600 max(13px, calc(13.5 * var(--u))) / 1.3 var(--sans);
}

.sources p + p { margin-top: 6px; }
.sources__ayahs { margin-top: 6px; }
.sources__ayahs li + li { margin-top: 2px; }
.sources__verified { color: var(--ink-3); }

/* ---------- Phones and narrow windows: the same order, composed for a column ---------- */

@container page (max-width: 719px) {
  main, .foot {
    --u: calc(100cqw / 640);
    --hero-scale: 1;
    --m: clamp(.84px, calc(100cqw / 390), 1.3px);
    --frame: 100cqw;
    --edge-gap: 0px;
    --side: 20px;
  }

  .hero { display: flex; flex-direction: column; min-height: max(calc(700 * var(--u)), var(--reserve, 0px)); }
  .hero__frame { flex: none; padding: 44px 20px 0; }
  .hero h1 { font-size: calc(50 * var(--m)); line-height: calc(49 * var(--m)); }
  .hero__lede { width: auto; margin-top: 12px; font-size: 17px; }
  .reopen { margin-top: 8px; }

  /* Everything on the display eases together, so the Arabic stays comfortable. */
  .rig {
    --tilt: -8deg;
    --depth: calc(2530 * var(--pu));
    --horizon: calc(1800 * var(--pu));
    --half: calc(300 * var(--pu));
    --cam-x: 50%;
    --rim-y: 34px;
    --back-h: max(calc(640 * var(--pu)), 41cqw);
    position: relative;
    inset: auto;
    flex: 1;
    min-height: 430px;
  }

  .reader { min-height: 0; }
  .reader__inner { padding: calc(70 * var(--pu)) 10px 0; }
  .reader__text { min-height: 84px; }
  .reader__ayah, .reader[data-long] .reader__ayah { font-size: 23px; line-height: 1.75; }
  .reader__excerpt { font-size: 16px; }
  .reader__bar { min-height: 48px; margin-top: 12px; }
  .reader__nav, .reader__close { font-size: 14px; }

  /* Keep the display prominent on phones too, cropping the keyboard without stretching it. */
  .fp {
    --photo-u: calc((100cqw - 40px) / 1180);
    --ref: calc(1082 * var(--photo-u) / 1440);
    --fp-foot-h: 44px;
    --fp-clear: max(8px, calc(36 * var(--ref)));
    --fp-wide: calc(1180 * var(--photo-u));
    --fp-compact: calc(1082 * var(--photo-u) - 8px);
    --fp-height: calc(661 * var(--photo-u));
    --fp-column: calc((var(--fp-height) - var(--fp-clear) - var(--fp-foot-h) - 4px) * 345 / 550 + 16px);
    padding: 48px 20px 56px;
  }

  .fp h2 { font-size: clamp(38px, calc(42 * var(--m)), 50px); line-height: 1.05; }
  .fp__body { max-width: none; margin-top: 12px; font-size: 16px; line-height: 1.5; }

  .fp__stage { margin-top: 28px; }

  .fp__compact { padding: var(--fp-clear) 4px calc(var(--fp-foot-h) + 4px); }
  .fp__text { max-height: max(24px, calc(var(--fp-height) - var(--fp-foot-h) - var(--fp-clear) - 40px)); }
  .fp__text .reader__ayah { font-size: 15px; line-height: 1.4; }
  .fp__compact .reader__excerpt { margin-top: 2px; font-size: 11px; }
  .fp__page {
    left: 8px;
    right: 8px;
    bottom: calc(var(--fp-foot-h) + 4px);
  }
  .fp__page::before { bottom: calc(-1 * (var(--fp-foot-h) + 4px)); }

  .fp__foot {
    display: grid;
    grid-template-columns: repeat(4, minmax(44px, 1fr));
    grid-template-areas: "next previous toggle close";
    padding: 0;
  }
  #page-next { grid-area: next; }
  #page-previous { grid-area: previous; }
  #page-close { grid-area: close; }
  .fp__where { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .fp__foot .reader__nav span, .fp__toggle span { display: none !important; }
  .fp__foot .reader__close { font-size: 0; }
  .fp__foot .reader__close::before { content: "×"; font: 400 24px / 1 var(--sans); }
  .fp__foot button { padding-inline: 0; }
  .fp__toggle { grid-area: toggle; }
  .fp__number { display: block; }
  .fp__number::before { content: none; }

  .fp__under { align-items: flex-start; margin-top: 20px; }

  /* Copy above the enlarged display, keeping the PNG's proportions. Long reader content
     scrolls inside its photographed display rather than stretching the hardware. */
  .nudge,
  [data-copy-layout="centered"] .nudge { display: block; min-height: 0; padding: 44px 20px 44px; }
  .nudge__copy,
  [data-copy-layout="centered"] .nudge__copy { width: auto; padding: 0 0 24px; }
  .nudge h2 { font-size: calc(46 * var(--m)); line-height: calc(46 * var(--m)); }
  .nudge__sub { margin-top: 8px; font-size: calc(26 * var(--m)); }
  .nudge__body { margin-top: 10px; font-size: 17px; }
  .nudge__preview { margin-top: 12px; font-size: 16px; }

  /* The front PNG keeps controls usable at a phone's width. */
  .nudge__device,
  [data-copy-layout="centered"] .nudge__device {
    --photo-u: calc((100cqw - 40px) / 1180);
    --half: calc(300 * var(--pu));
    --cam-local: 50%;
    width: calc(1180 * var(--photo-u));
    height: calc(820 * var(--photo-u));
    max-width: 100%;
    overflow: visible; /* only the full-width chapter, never the inset device box, can cover the keyboard */
    margin: 0 auto;
  }
  .nudge__device > .mac { left: calc(-178 * var(--photo-u)); }
  .nudge__device .screen--flat {
    top: calc(87 * var(--photo-u));
    left: calc(227 * var(--photo-u));
    width: calc(1082 * var(--photo-u));
    height: calc(661 * var(--photo-u));
  }
  .cue__inner { padding-inline: max(8px, var(--fillet)); }
  .cue__title { max-width: 11ch; font-size: 13px; text-align: center; text-wrap: balance; }
  .cue__action { font-size: 12px; }
  .reader--local { --half: calc(480 * var(--pu)); }
  .reader--local .reader__excerpt { font-size: 13px; }
  .reader--local .reader__bar { margin-top: 4px; }
  .reader--local .reader__ayah, .reader--local[data-long] .reader__ayah { font-size: 21px; }
  .reader--local .reader__nav,
  .reader--local .reader__close { min-height: 46px; padding-inline: 3px; }
  .reader--local .reader__close { gap: 4px; }
  .reader--local .reader__nav span, .reader--local .reader__close kbd { display: none; }
  .reader--local .reader__nav svg { width: 18px; height: 18px; }
  .reader--local .reader__close { font-size: 0; }
  .reader--local .reader__close::before { content: "×"; font: 400 24px / 1 var(--sans); }

  .cta { padding: 54px 20px 44px; }
  .cta h2 { font-size: calc(38 * var(--m)); }
  .cta__line { margin-top: 12px; }
  .cta__action { margin-top: 24px; }
  .cta__meta { margin-top: 16px; }

  .foot { margin: 0 20px; padding: 10px 0 18px; font-size: 14px; }
  .foot__mark { top: 10px; }
  .sources__body { grid-template-columns: 1fr; gap: 16px; }
}

/* The header stacks before its two columns can collide. */
@container page (max-width: 359.98px) {
  .fp__mode-long { display: none; }
  .fp__mode-short { display: inline; white-space: nowrap; }


}

@media (max-height: 520px) {
  .begin { padding: 4px 16px; }
  .begin__key { margin-top: 10px; }
  .begin__or { margin-top: 16px; }
  .opening__prompt { padding-bottom: 0; }
}

/* ---------- Full page, as a scroll scene ----------
   Only with scripts and motion. The chapter scrolls in from the nudge's straight edge like any
   section; then one pane, exactly the window's height, holds still over a bounded track, so the
   Mac settles, the page grows inside its display, holds, and gives the ayah back before the
   download slides over it. Nothing here depends on the reader's mode, so the page
   below never moves. The head, gap and caption are reserved and the display takes the room
   left, with its whole bezel visible and its keyboard cropped below. A shorter window draws
   the display smaller. The heading
   stays; the support line beneath it is the one that follows the poses, in one cell, and
   full-page-view.mjs writes its fades. */

.fp__say { display: none; }

@media (prefers-reduced-motion: no-preference) {
  .js .fp {
    --fp-track: 200svh;
    --fp-pad: calc(16 * var(--u));
    --fp-head-h: calc(120 * var(--u)); /* heading, support line and the gap to the Mac */
    --fp-gap: calc(20 * var(--u));
    --fp-under-h: 44px;
    --fp-room: calc(100svh - 2 * var(--fp-pad) - var(--fp-head-h) - var(--fp-gap) - var(--fp-under-h));
    --photo-u: min(calc((100cqw - 100px) / 1082), calc(var(--fp-room) / 750)); /* fit the lid, not the whole PNG */
    height: calc(100svh + var(--fp-track));
    padding-block: 0;
  }

  .js .fp__pin {
    position: sticky;
    top: 0;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-content: center;
    height: 100svh;
    padding-block: var(--fp-pad);
  }

  .js .fp__head {
    display: grid;
    align-content: end;
    height: var(--fp-head-h);
    padding-bottom: calc(16 * var(--u));
  }

  /* The section's stable description, for screen readers. The lines beside it are aria-hidden. */
  .js .fp__body {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
  }

  .js .fp__say {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    margin-top: calc(10 * var(--u));
    color: var(--ink-2);
    font: 400 max(16px, calc(20 * var(--u))) / 1.3 var(--sans);
    text-align: center;
  }

  .js .fp__say span { grid-area: 1 / 1; opacity: 0; will-change: opacity, transform; }

  .js .fp__stage { margin-top: var(--fp-gap); }
  .js .fp__under { margin-top: 0; } /* the caption sits under the support line, above the Mac */
}

@container page (max-width: 719px) {
  @media (prefers-reduced-motion: no-preference) {
    .js .fp {
      --fp-pad: 12px;
      --fp-head-h: 140px;
      --fp-gap: 16px;
      --fp-under-h: 44px;
      --photo-u: min(calc((100cqw - 40px) / 1180), calc(var(--fp-room) / 750));
      --fp-height: calc(661 * var(--photo-u));
    }

    /* A smaller heading in the pinned scene, so the page keeps its room on a phone. */
    .js .fp h2 { font-size: clamp(30px, calc(34 * var(--m)), 40px); line-height: 1.05; }
    .js .fp__head { padding-bottom: 12px; }
    .js .fp__say { margin-top: 8px; font-size: 16px; line-height: 1.4; }
  }
}

/* ---------- Chapters in layers ----------
   With scripts and motion, the hero and every chapter after it hand over in layers: a chapter
   that has been read holds where it is and the next slides up over it, on the page's own scroll,
   and back again the same way. Each holds against the top of the window, one layer above the
   chapter before it, and main is their containing block, so nothing holds past the footer. A
   chapter taller than the window (the hero with a long reader, the nudge on a short phone) holds
   with its lower edge on the window's instead: app.js sets --hold, so all of it can still be
   reached before it is covered. The full page holds at the end of its track, so its last pane
   stays put, at its last pose, while the download passes over it. The download fills the window,
   so nothing beneath can show once the footer arrives. Every chapter is an opaque, full-bleed
   plane, so the edge that passes over needs no shade, line or rounding: one page simply covers
   the last. The hero's own layers stay inside it. */

@media (prefers-reduced-motion: no-preference) {
  .js .hero {
    position: sticky;
    top: var(--hold, 0px);
    z-index: 0;
  }

  .js .nudge {
    position: sticky;
    top: var(--hold, 0px);
    z-index: 1;
  }

  .js .fp {
    position: sticky;
    top: calc(-1 * var(--fp-track)); /* its lower edge on the window's: the last pane */
    z-index: 2;
  }

  .js .cta {
    position: relative;
    z-index: 3;
    align-content: center;
    min-height: 100svh;
  }
}

/* ---------- Reduced motion: everything settled ---------- */

@media (prefers-reduced-motion: reduce) {
  .begin__key,
  .reader__nav,
  .reader__close,
  .cue__action,
  .fp__toggle,
  .cta__action,
  .cta__file,
  .sources__mark { transition: none; }
}
