/* ============================================================================
   WENN DAS VIDEO ENDET — interactive storybook
   One stylesheet, no build step. Section banners below match the data-sid /
   data-title values in index.html and en.html, so a search for a section name
   finds its markup and its styles in the same two places.
   ============================================================================ */


/* ---------------------------------------------------------------------------
   FONTS
   Self-hosted variable fonts, reused from earlier projects so the page makes
   zero third-party requests. Newsreader carries the story (a serif reads as
   "book", not as "app"); Archivo carries the chrome — buttons, counters, labels.
   font-display:swap so the story text is readable before the font lands.
   --------------------------------------------------------------------------- */
@font-face {
  font-family: "Newsreader";
  src: url("assets/fonts/newsreader-latin.woff2") format("woff2");
  font-weight: 300 700;     /* the range the build keeps; see tools/build-assets.py */
  font-display: swap;
}
@font-face {
  font-family: "Archivo";
  src: url("assets/fonts/archivo-latin.woff2") format("woff2");
  font-weight: 400 800;
  font-display: swap;
}

/* Hebrew edition (he.html). Registered under the SAME font-family name as
   their Latin counterpart, split only by unicode-range: the browser matches
   per glyph, so `font-family: "Newsreader", …` already sets Hebrew text in
   Frank Ruhl Libre with no markup change anywhere the family is referenced.
   The narrow unicode-range is load-bearing, not cosmetic — de/en/es/pt never
   contain a Hebrew codepoint, so these two files are never requested on those
   four pages. See tools/build-assets.py for the license and the subset. */
@font-face {
  font-family: "Newsreader";
  src: url("assets/fonts/frankruhl-hebrew.woff2") format("woff2");
  font-weight: 300 700;
  font-display: swap;
  unicode-range: U+0590-05FF, U+200F, U+FB1D-FB4F;
}
@font-face {
  font-family: "Archivo";
  src: url("assets/fonts/heebo-hebrew.woff2") format("woff2");
  font-weight: 400 800;
  font-display: swap;
  unicode-range: U+0590-05FF, U+200F, U+FB1D-FB4F;
}


/* ---------------------------------------------------------------------------
   TOKENS
   The palette is pulled from the book's own artwork rather than invented:
   the cockatoo's crest (gold), the cage (steel), the cover's forest and sky,
   and a warm paper that matches the printed stock. Four colours plus ink is
   the whole budget — anything else would fight the illustrations.
   --------------------------------------------------------------------------- */
:root {
  --ink: #1b1714;
  --paper: #f4efe6;
  --gold: #e8a81c;
  --forest: #2e4034;
  --steel: #5a6b78;

  --stage: #0f0c0a;          /* the dark room the opening "video" plays in */
  --scrim: 15, 12, 10;       /* rgb parts, so scrims can vary only in alpha */

  --measure: 26ch;           /* story lines stay short enough to read aloud */
  --gutter: clamp(1.25rem, 0.6rem + 3vw, 4rem);
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}


/* ---------------------------------------------------------------------------
   BASE
   --------------------------------------------------------------------------- */
* { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  /* Snap settles the reader on one spread at a time without trapping them:
     "proximity" lets a deliberate scroll pass straight through. */
  scroll-snap-type: y proximity;
}

body {
  margin: 0;
  background: var(--stage);
  color: var(--paper);
  font-family: "Newsreader", Georgia, "Times New Roman", serif;
  font-optical-sizing: auto;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;         /* a stray wide child must never widen the page */
}

img { display: block; max-width: 100%; }

a { color: inherit; }

:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 3px;
  border-radius: 2px;
}

/* Visible only to screen readers — used for the skip link and live status. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* The story is 24 full-height sections. Without this, a keyboard or screen-reader
   user has to walk the whole opening before reaching page one. */
.skip-link {
  position: fixed;
  top: 0.5rem; inset-inline-start: 0.5rem;   /* reading-start corner in either direction */
  z-index: 100;
  padding: 0.6rem 1rem;
  background: var(--paper);
  color: var(--ink);
  font-family: "Archivo", system-ui, sans-serif;
  font-size: 0.9rem;
  border-radius: 4px;
  transform: translateY(-200%);
}
.skip-link:focus { transform: none; }


/* ---------------------------------------------------------------------------
   CHROME — progress bar + toolbar
   Fixed, tiny, and always reachable. The toolbar is the only persistent UI;
   everything else is the book.
   --------------------------------------------------------------------------- */
/* A book has a visible thickness in your hand; a scrolling page has none. The
   hairline is the only thing telling a parent how much is left. */
#progress {
  position: fixed;
  inset: 0 0 auto 0;
  height: 3px;
  z-index: 40;
  background: rgba(244, 239, 230, 0.16);
}
#progress span {
  display: block;
  height: 100%;
  width: 0;
  background: var(--gold);
  /* Stays physical left on purpose, in RTL too: this reads as a scrubber/fuel
     gauge (quantity used up), not as text, and that convention fills the same
     physical direction regardless of script — the way a YouTube progress bar
     does in a Hebrew or Arabic UI. Flipping it would read as "less read". */
  transform-origin: left;
}

#toolbar {
  position: fixed;
  top: 0.75rem; inset-inline-end: 0.75rem;   /* opposite corner from .skip-link in both directions */
  z-index: 41;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-family: "Archivo", system-ui, sans-serif;
}

.tool {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 44px;                 /* thumb-sized: this is read on a phone */
  padding: 0 0.85rem;
  border: 1px solid rgba(244, 239, 230, 0.28);
  border-radius: 999px;
  background: rgba(15, 12, 10, 0.55);
  backdrop-filter: blur(8px);
  color: var(--paper);
  font: 600 0.82rem/1 "Archivo", system-ui, sans-serif;
  letter-spacing: 0.02em;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.25s var(--ease), border-color 0.25s var(--ease);
}
.tool:hover { background: rgba(15, 12, 10, 0.8); border-color: var(--gold); }
.tool[aria-pressed="true"] { background: var(--gold); color: var(--ink); border-color: var(--gold); }

.tool__dot {
  width: 8px; height: 8px;
  border-radius: 50%;
  background: currentColor;
}
.tool[aria-pressed="true"] .tool__dot { animation: pulse 1.4s infinite; }

@keyframes pulse { 50% { opacity: 0.25; } }

#counter {
  font-variant-numeric: tabular-nums;
  opacity: 0.75;
}


/* ---------------------------------------------------------------------------
   OPENING — "the video that ends"
   The one thing paper cannot do. A phone plays the same dancing-cockatoo clip
   the story opens with; it runs, the scrubber reaches the end, the screen goes
   dark — and the room behind it turns out to be a small cage. It is not a
   preloader: the story below is scrollable from the first frame, and the whole
   sequence is skipped outright under prefers-reduced-motion.
   --------------------------------------------------------------------------- */
#opening {
  position: relative;
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: 5rem var(--gutter) 3rem;
  scroll-snap-align: start;
  overflow: hidden;
}

/* The reality behind the screen — a dark suggestion of a room at first, fully
   revealed only as the video ends. It starts at 0.22 rather than 0 on purpose:
   invisible until second five would make this the largest paint of the page and
   push LCP past three seconds, and a faint room behind the phone reads better
   than a black void anyway. */
#opening .reveal {
  position: absolute;
  inset: 0;
  object-fit: cover;
  width: 100%; height: 100%;
  opacity: 0.22;
  transform: scale(1.08);
  filter: saturate(0.75) brightness(0.55);
  transition: opacity 1.6s var(--ease), transform 2.4s var(--ease);
}
#opening.ended .reveal { opacity: 1; transform: scale(1); }

#opening .stage {
  position: relative;
  z-index: 2;
  display: grid;
  justify-items: center;
  gap: clamp(1rem, 2.5svh, 2.5rem);
  text-align: center;
  max-width: 100%;
}

/* Once the cage is revealed the title sits on a bright illustration, so the
   stage carries its own pool of shadow. Without it the contrast depends on
   whatever happens to be behind the words. */
#opening::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(ellipse 90% 62% at 50% 62%, rgba(var(--scrim), 0.78), rgba(var(--scrim), 0) 72%);
  opacity: 0;
  transition: opacity 1.6s var(--ease);
}
#opening.ended::before { opacity: 1; }

/* --- the phone ------------------------------------------------------------ */
/* Sized by HEIGHT, not width: the phone shares the fold with a title, a
   paragraph and a button, and on a 900px-tall laptop a width-driven phone
   pushes the button off the screen. */
.phone {
  position: relative;
  height: clamp(240px, 34svh, 420px);
  width: auto;
  aspect-ratio: 9 / 18.5;
  padding: 8px;
  border-radius: 30px;
  background: linear-gradient(160deg, #3b3b40, #17171a 55%, #2c2c31);
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.08) inset;
}
.phone__screen {
  position: relative;
  height: 100%;
  border-radius: 22px;
  overflow: hidden;
  background: linear-gradient(180deg, #f6821f, #e2560f);
}
.phone__screen img {
  width: 100%; height: 100%;
  object-fit: cover;
  mix-blend-mode: multiply;      /* drops the crop's cream card onto the orange */
  transform-origin: 50% 62%;
}
#opening.playing .phone__screen img { animation: dance 1.15s var(--ease) infinite; }

@keyframes dance {
  0%, 100% { transform: translateY(0) rotate(-3deg) scale(1.02); }
  50%      { transform: translateY(-3%) rotate(3deg) scale(1.05); }
}

/* The black-out that gives the book its title. The diagonal sheen keeps it
   reading as a switched-off screen rather than a hole cut in the page. */
.phone__off {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(118deg, rgba(255, 255, 255, 0.09) 0%, rgba(255, 255, 255, 0) 38%),
    #08070a;
  opacity: 0;
  transition: opacity 0.55s var(--ease);
}
#opening.ended .phone__off { opacity: 1; }

.phone__scrub {
  position: absolute;
  /* Equal on both sides, so this is direction-neutral either way — logical
     shorthand purely because it is shorter, not because RTL changes it. */
  inset-inline: 10px; bottom: 12px;
  height: 3px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.35);
  overflow: hidden;
}
.phone__scrub b {
  display: block;
  height: 100%;
  width: 0;
  background: #fff;
}
#opening.playing .phone__scrub b { animation: scrub 5.2s linear forwards; }
#opening.ended .phone__scrub { opacity: 0; transition: opacity 0.4s; }

@keyframes scrub { to { width: 100%; } }

/* --- the title ------------------------------------------------------------ */
.opening__caption {
  font-family: "Archivo", system-ui, sans-serif;
  font-size: 0.8rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(244, 239, 230, 0.65);
  margin: 0;
  transition: opacity 0.4s var(--ease);
}
#opening.ended .opening__caption { opacity: 0; }

.opening__title {
  margin: 0;
  max-width: 16ch;
  font-size: clamp(2.4rem, 1.2rem + 6.4vw, 5.5rem);
  font-weight: 300;
  line-height: 0.98;
  letter-spacing: -0.02em;
  text-shadow: 0 2px 30px rgba(0, 0, 0, 0.65);
  opacity: 0;
  transform: translateY(0.4em);
  transition: opacity 1s var(--ease) 0.35s, transform 1s var(--ease) 0.35s;
}
.opening__title em {
  display: block;
  font-style: normal;
  color: var(--gold);
}
#opening.ended .opening__title { opacity: 1; transform: none; }

.opening__sub,
.opening__cta {
  opacity: 0;
  transform: translateY(0.6em);
  transition: opacity 0.9s var(--ease) 0.7s, transform 0.9s var(--ease) 0.7s;
}
#opening.ended .opening__sub,
#opening.ended .opening__cta { opacity: 1; transform: none; }

.opening__sub {
  margin: 0;
  max-width: 34ch;
  font-size: clamp(1rem, 0.9rem + 0.6vw, 1.3rem);
  line-height: 1.5;
  color: rgba(244, 239, 230, 0.88);
  text-shadow: 0 1px 20px rgba(0, 0, 0, 0.7);
}

.opening__cta {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 52px;
  padding: 0 1.6rem;
  border: 0;
  border-radius: 999px;
  background: var(--gold);
  color: var(--ink);
  font: 700 0.95rem/1 "Archivo", system-ui, sans-serif;
  text-decoration: none;
  cursor: pointer;
}
.opening__cta:hover { background: #f5bb3c; }

.opening__meta {
  position: absolute;
  inset-inline-start: var(--gutter); bottom: 1.5rem;
  z-index: 2;
  margin: 0;
  font: 500 0.78rem/1.5 "Archivo", system-ui, sans-serif;
  letter-spacing: 0.04em;
  color: rgba(244, 239, 230, 0.55);
}


/* ---------------------------------------------------------------------------
   SPREADS — the 24 pages of the story
   Every spread is one full-bleed illustration with its text set ON the picture,
   never beside it. data-text="top|bottom" picks the edge that does not cover
   the subject of that particular painting; it is chosen per image, by eye.
   --------------------------------------------------------------------------- */
.spread {
  position: relative;
  min-height: 100svh;
  display: grid;
  scroll-snap-align: start;
  background: var(--stage);
  overflow: hidden;
}

.spread__art {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center 28%;   /* the subject sits high in most of the art */
}

/* The scrim is a gradient on the picture, not a card behind the words: it keeps
   the illustration whole while still guaranteeing text contrast. */
.spread::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    to top,
    rgba(var(--scrim), 0.92) 0%,
    rgba(var(--scrim), 0.72) 26%,
    rgba(var(--scrim), 0.12) 58%,
    rgba(var(--scrim), 0) 78%
  );
}
.spread[data-text="top"]::after {
  background: linear-gradient(
    to bottom,
    rgba(var(--scrim), 0.92) 0%,
    rgba(var(--scrim), 0.72) 26%,
    rgba(var(--scrim), 0.12) 58%,
    rgba(var(--scrim), 0) 78%
  );
}

.spread__text {
  position: relative;
  z-index: 2;
  align-self: end;
  max-width: var(--measure);
  padding: 0 var(--gutter) clamp(3.5rem, 8vh, 6rem);
  font-size: clamp(1.3rem, 1.02rem + 1.5vw, 2.1rem);
  line-height: 1.36;
  font-weight: 400;
  text-wrap: balance;   /* no orphaned last word hanging under a sentence */
  text-shadow: 0 1px 24px rgba(0, 0, 0, 0.55);
}
.spread[data-text="top"] .spread__text {
  align-self: start;
  padding: clamp(5rem, 12vh, 8rem) var(--gutter) 0;
}

.spread__text p { margin: 0 0 0.85em; }
.spread__text p:last-child { margin-bottom: 0; }

/* Each paragraph is one unit of read-aloud. While "read to me" is running the
   active line lifts out of the scrim so a child can follow along. */
.spread__text p {
  transition: color 0.3s var(--ease), opacity 0.3s var(--ease);
}
body.reading .spread__text p { opacity: 0.45; }
body.reading .spread__text p.is-speaking {
  opacity: 1;
  color: var(--gold);
}

/* The printed page number, kept. It is what a parent says out loud when a child
   asks where they are, and it makes a link to #s12 mean something. */
.spread__num {
  position: absolute;
  z-index: 2;
  /* Deliberately NOT inset-inline-end. The folio sits in a fixed physical
     corner of the illustration, like a printed book's page number, not at a
     text-flow edge — the scrim and every full-bleed image were art-directed
     with that corner in mind (see data-text="top|bottom", "chosen per image,
     by eye" above), and no page has been re-checked for a bottom-LEFT corner.
     Mirroring it for Hebrew would be guessing at a composition decision that
     was never made for that corner. Stays physical right in every language. */
  right: var(--gutter);
  bottom: 1.5rem;
  margin: 0;
  font: 500 0.8rem/1 "Archivo", system-ui, sans-serif;
  font-variant-numeric: tabular-nums;
  color: rgba(244, 239, 230, 0.5);
}

/* Entrance: the picture settles and the words rise. Small on purpose — the
   next sentence must never wait on an animation. */
.spread__art {
  transform: scale(1.06);
  transition: transform 1.4s var(--ease);
}
.spread.is-visible .spread__art { transform: scale(1); }

.spread__text {
  opacity: 0;
  transform: translateY(1.2rem);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}
.spread.is-visible .spread__text { opacity: 1; transform: none; }


/* ---------------------------------------------------------------------------
   CLOSING — facts, the note for parents, and the offer
   Everything commercial lives here and nowhere earlier. Set on paper, not on
   a photograph: the story is over and this part is meant to be read, not felt.
   --------------------------------------------------------------------------- */
.paper {
  background: var(--paper);
  color: var(--ink);
  padding: clamp(3.5rem, 10vh, 7rem) var(--gutter);
}

/* The afterword is long-form reading, so it gets a reading measure rather than
   the short, spoken-aloud measure the story pages use. */
.wrap { max-width: 62ch; margin: 0 auto; }

.paper h2 {
  margin: 0 0 1.2rem;
  font-size: clamp(1.8rem, 1.2rem + 2.6vw, 3rem);
  font-weight: 300;
  line-height: 1.05;
  letter-spacing: -0.01em;
}

.paper h3 {
  margin: 2rem 0 0.5rem;
  font: 700 0.82rem/1.3 "Archivo", system-ui, sans-serif;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--forest);
}

.paper p, .paper li {
  font-size: 1.06rem;
  line-height: 1.65;
}

.paper a { color: var(--forest); text-underline-offset: 3px; }

.eyebrow {
  margin: 0 0 0.75rem;
  font: 700 0.78rem/1 "Archivo", system-ui, sans-serif;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--steel);
}

/* The five facts, as a plain list with a gold rule — no card grid. */
.facts { list-style: none; margin: 0; padding: 0; }
.facts li {
  padding-block: 0.9rem;
  padding-inline: 1.6rem 0;   /* room for the mark at the reading-start edge */
  border-top: 1px solid rgba(27, 23, 20, 0.14);
  position: relative;
}
/* A gold rule instead of a bullet: five short facts read as a list either way,
   and a bullet character would be the sixth typeface on the page. */
.facts li::before {
  content: "";
  position: absolute;
  inset-inline-start: 0; top: 1.5rem;
  width: 0.6rem; height: 2px;
  background: var(--gold);
}
.facts li:last-child { border-bottom: 1px solid rgba(27, 23, 20, 0.14); }

.note { border-top: 1px solid rgba(27, 23, 20, 0.14); margin-top: 3rem; padding-top: 2rem; }
.note p { font-size: 0.98rem; }
.note ul { padding-inline-start: 1.1rem; }
.note li { font-size: 0.98rem; margin-bottom: 0.35rem; }

/* The one paragraph in the note that is a legal warning, marked as one. Colour
   alone would fail contrast for some readers, so it carries a rule as well. */
.warn {
  border-inline-start: 3px solid #b4441f;
  padding-inline-start: 1rem;
  margin: 1.5rem 0;
}

/* --- the offer, on forest ------------------------------------------------- */
.offer {
  background: var(--forest);
  color: var(--paper);
  padding: clamp(3.5rem, 10vh, 7rem) var(--gutter);
  text-align: center;
}
.offer h2 { margin: 0 0 1rem; font-size: clamp(1.9rem, 1.2rem + 3vw, 3.2rem); font-weight: 300; }
.offer p { max-width: 46ch; margin: 0 auto 2rem; line-height: 1.6; opacity: 0.88; }
.offer .opening__cta { opacity: 1; transform: none; }

/* The other four books as plain pills, not cards with covers: the reader has
   just finished a story, and five product tiles would undo the ending. */
.offer__series {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.6rem;
  margin: 2.5rem 0 0;
  padding: 0;
  list-style: none;
  font: 500 0.82rem/1 "Archivo", system-ui, sans-serif;
  opacity: 0.75;
}
.offer__series li { padding: 0.5rem 0.9rem; border: 1px solid rgba(244, 239, 230, 0.25); border-radius: 999px; }

footer {
  background: var(--stage);
  padding: 2.5rem var(--gutter);
  text-align: center;
  font: 400 0.82rem/1.7 "Archivo", system-ui, sans-serif;
  color: rgba(244, 239, 230, 0.55);
}


/* ---------------------------------------------------------------------------
   REDUCED MOTION
   Nothing moves, the opening starts already ended, and the story is still
   completely readable. This is the state most "immersive" storybooks forget.
   --------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; scroll-snap-type: none; }

  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

  .spread__art { transform: none; }
  .spread__text { opacity: 1; transform: none; }
  #opening .reveal { opacity: 1; transform: none; }
}


/* ---------------------------------------------------------------------------
   WIDE SCREENS — the open-book spread
   The artwork is A5 portrait; a laptop is landscape. Filling that screen with a
   portrait picture means cropping roughly a third of it away, which is fine on a
   phone (nearly the same shape) and a real loss on a desktop.
   So above 56rem AND only when the viewport is wider than it is tall, the page
   becomes a spread: the WHOLE picture stands on the right like a printed page,
   the text sits on the left, and the space around them is the picture itself,
   blurred right down — the room the page is lying in, in its own colours.
   Each section carries its art URL as --art (set inline next to its <img>), so
   the backdrop reuses the file the browser already downloaded.
   --------------------------------------------------------------------------- */
@media (min-width: 56rem) and (min-aspect-ratio: 1/1) {
  /* The backdrop. Blurred this hard it is colour and light, not an image. */
  .spread::before {
    content: "";
    position: absolute;
    inset: -8%;                       /* overscan, so the blur has no soft edge */
    background: var(--art) center / cover no-repeat;
    filter: blur(48px) saturate(0.8) brightness(0.38);
    transform: scale(1.04);
  }

  /* The picture itself: nothing cropped, standing like a page on a table.
     inset-inline (not left/right) so a Hebrew edition opens the book from the
     other side: the picture stands on the reading-END edge in both
     directions — right in LTR, left in RTL — with the text held toward
     reading-START, same as a physical book turns from either spine. */
  .spread__art {
    inset-block: 5vh;
    inset-inline: auto max(3vw, 1.5rem);
    height: 90svh;
    width: auto;
    aspect-ratio: 1747 / 2211;        /* matches the trimmed source exactly */
    object-position: center;          /* element == picture, so nothing is cut */
    border-radius: 3px;
    box-shadow: 0 40px 90px rgba(0, 0, 0, 0.55);
  }

  /* A gentle pool of shadow on the text side. `to right`/`to left` are
     physical — CSS gradients have no logical direction keyword — so the RTL
     mirror for this one lives in the scoped block at the end of this file,
     next to the reasoning. The backdrop is already dark, so this only has to
     guarantee the worst case, not carry the contrast alone. */
  .spread::after,
  .spread[data-text="top"]::after {
    background: linear-gradient(to right,
      rgba(var(--scrim), 0.65) 0%,
      rgba(var(--scrim), 0.35) 34%,
      rgba(var(--scrim), 0) 60%);
  }

  .spread__text,
  .spread[data-text="top"] .spread__text {
    align-self: center;
    max-width: 32ch;
    margin-inline-start: clamp(2.5rem, 7vw, 8rem);
    padding-block: 0;
  }

  .spread__num { color: rgba(244, 239, 230, 0.4); }
}

/* Very wide screens have room for the text to breathe further from the page. */
@media (min-width: 90rem) {
  .spread__art { inset-block: 8vh; inset-inline: auto 6vw; height: 84svh; }
  .spread__text { max-width: 34ch; margin-inline-start: clamp(4rem, 10vw, 12rem); }
}

/* Someone will print this for a classroom. Drop the interface, let each spread
   be a page, and remove the scrim so the illustrations come out clean. */
@media print {
  #toolbar, #progress, .phone { display: none; }
  .spread { min-height: auto; page-break-after: always; }
  .spread::after { display: none; }
}


/* ---------------------------------------------------------------------------
   THE SECOND ASK
   Under the main button: reserving the printed edition costs nothing and is the
   only number that can justify a print run, so it belongs on the page — but
   quietly, as a text link, not as a second button competing with the first.
   --------------------------------------------------------------------------- */
.offer__second {
  margin: 1.25rem 0 0;
  font: 500 0.9rem/1.5 "Archivo", system-ui, sans-serif;
}
/* Quiet, but still a thumb-sized target: as a bare inline link it failed the
   touch-target check and cost the page its perfect accessibility score. */
.offer__second a {
  display: inline-block;
  min-height: 44px;
  padding: 0.75rem 0.5rem;
  color: rgba(244, 239, 230, 0.8);
  text-underline-offset: 4px;
}
.offer__second a:hover { color: var(--gold); }


/* ---------------------------------------------------------------------------
   LANGUAGE MENU
   A two-way toggle stopped working the moment there was a third edition, so the
   languages are a list and the one you are reading is marked rather than
   linked. On a phone the list wraps under the toolbar instead of pushing the
   page counter off the screen.
   --------------------------------------------------------------------------- */
.langs {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  justify-content: flex-end;
}

.tool--on {
  background: rgba(244, 239, 230, 0.14);
  border-color: rgba(244, 239, 230, 0.4);
  cursor: default;
}

#toolbar { flex-wrap: wrap; max-width: calc(100vw - 1.5rem); justify-content: flex-end; }

/* Under about 30rem the four pills plus the button and the counter cannot share
   one row at a readable size; the counter is the least important of the three. */
@media (max-width: 30rem) {
  #counter { display: none; }
  .tool { padding: 0 0.7rem; font-size: 0.78rem; }
}


/* ---------------------------------------------------------------------------
   LANGUAGE CHOOSER
   A native <details>: the toolbar stays one row tall however many editions
   exist, and it works with the keyboard and a screen reader without any script.
   --------------------------------------------------------------------------- */
.langs { position: relative; }
.langs > summary { list-style: none; user-select: none; }
.langs > summary::-webkit-details-marker { display: none; }
.langs > summary::after {
  content: "";
  width: 0; height: 0;
  margin-inline-start: 0.15rem;
  border: 0.28rem solid transparent;
  border-top-color: currentColor;
  transform: translateY(0.14rem);
}
.langs[open] > summary { background: var(--gold); color: var(--ink); border-color: var(--gold); }

.langs__panel {
  position: absolute;
  top: calc(100% + 0.35rem);
  inset-inline-end: 0;   /* hangs from the same corner the summary toggle sits in */
  display: grid;
  min-width: 9.5rem;
  padding: 0.35rem;
  border: 1px solid rgba(244, 239, 230, 0.28);
  border-radius: 12px;
  background: rgba(15, 12, 10, 0.92);
  backdrop-filter: blur(10px);
  font: 500 0.85rem/1 "Archivo", system-ui, sans-serif;
}
.langs__panel a,
.langs__on {
  display: flex;
  align-items: center;
  min-height: 40px;
  padding: 0 0.7rem;
  border-radius: 8px;
  text-decoration: none;
  color: var(--paper);
}
.langs__panel a:hover { background: rgba(244, 239, 230, 0.12); }
.langs__on { color: var(--gold); cursor: default; }


/* ==========================================================================
   Band 2 per E-Mail — das Anmeldefeld am Ende von Band 1
   Steht bewusst VOR dem Angebot: wer gerade fertig gelesen hat, will die
   naechste Geschichte, nicht den Shop. Band 1 selbst bleibt ohne jede Huerde.
   ========================================================================== */
.weiter{max-width:34rem;margin:0 auto;padding:3rem 1.25rem 1rem;text-align:center}
.weiter h2{margin:0 0 .6rem}
.weiter>p{margin:0 auto 1.4rem;max-width:30rem;line-height:1.65}
.weiter__form{text-align:start;background:rgba(255,255,255,.55);border:1px solid rgba(29,26,20,.14);
  border-radius:16px;padding:1.15rem 1.2rem}
.weiter__form label{display:block;font-size:.86rem;margin:.7rem 0 .25rem}
.weiter__form input[type=text],.weiter__form input[type=email]{width:100%;padding:.62rem .75rem;
  border:1px solid rgba(29,26,20,.25);border-radius:9px;background:#fff;font:inherit;color:inherit}
.weiter__form input[type=text]:focus-visible,.weiter__form input[type=email]:focus-visible,
.weiter__form button:focus-visible,.weiter__consent input:focus-visible{outline:3px solid #8a6d2f;outline-offset:2px}
.weiter__consent{display:flex;gap:.55rem;align-items:flex-start;font-size:.82rem;line-height:1.5;margin:.95rem 0 .2rem}
.weiter__consent input{margin-top:.25rem;flex:none;width:1.05rem;height:1.05rem}
.weiter__form button{margin-top:1rem;width:100%;background:#1d1a14;color:#f5efe2;border:0;
  padding:.8rem 1rem;border-radius:999px;font:inherit;font-weight:700;cursor:pointer}
.weiter__form button:hover{background:#3a3121}
.weiter__note{font-size:.8rem;opacity:.75;line-height:1.55;margin:.9rem auto 0;max-width:30rem}
.weiter__msg{margin:0 0 1rem;padding:.75rem .9rem;border-radius:10px;font-size:.9rem;line-height:1.5}
.weiter__msg.is-ok{background:rgba(58,102,72,.14);border:1px solid rgba(58,102,72,.4)}
.weiter__msg.is-err{background:rgba(150,54,42,.12);border:1px solid rgba(150,54,42,.4)}
/* Honigtopf: nie sichtbar, nie im Tabstopp, aber fuer Bots ausfuellbar. */
.weiter__hp{position:absolute;inset-inline-start:-9999px;top:-9999px}
@media (prefers-reduced-motion:no-preference){.weiter__form button{transition:background .2s ease}}


/* ---------------------------------------------------------------------------
   RTL — HEBREW EDITION (he.html)
   Nearly everything above needed no override at all: every left/right in this
   file was converted in place to an inline-start/inline-end logical property,
   which resolves per `<html dir>` on its own — that is fewer lines than a
   mirrored block and, unlike a second block living far from the first, it
   cannot silently drift out of sync with it. Two things could not be handled
   that way and live here instead, plus the two decisions to NOT flip
   something are written where that rule itself is (`.spread__num`, the
   comment on `#progress span`), not repeated here.

   Do not add a `@media (min-width: 90rem)` block here to answer the one
   above — see docs/HANDOFF.md. build-v2-web.py injects a per-edition <style>
   AFTER this file at plain class specificity, and it already wins the
   desktop layout for every live edition; a second physical-direction block
   in THIS file duplicating that width has bitten this project before by
   landing later in source order than the block it was meant to answer.
   `[dir="rtl"]` selectors below outrank that plain-class override on
   specificity alone, so they are safe regardless of injection order — this
   note is only about not adding another bare `@media` block.
   --------------------------------------------------------------------------- */

/* CSS gradients have no logical `to inline-end` keyword — `to right` and
   `to left` are always physical — so the one shadow gradient that must point
   the other way for Hebrew is mirrored explicitly here. Same three colour
   stops as the LTR rule above; only the direction changes. */
@media (min-width: 56rem) and (min-aspect-ratio: 1/1) {
  [dir="rtl"] .spread::after,
  [dir="rtl"] .spread[data-text="top"]::after {
    background: linear-gradient(to left,
      rgba(var(--scrim), 0.65) 0%,
      rgba(var(--scrim), 0.35) 34%,
      rgba(var(--scrim), 0) 60%);
  }
}
