/* Preambient site styles. Layout measured 1:1 from biograph.com at 1440 wide. */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: calc(var(--nav-h) + 16px); scroll-padding-bottom: 24px; }
/* Owner, 2026-11-06: "they shouldnt be able to scroll above the page". No rubber-band bounce past the top (or the foot) of the
   page, so nothing shows above the header. Scrolling inside the page is unchanged. */
html, body { overscroll-behavior-y: none; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body { margin: 0; background: #fff; color: var(--ink); font-family: var(--font-body); font-size: 16px; line-height: 24px; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
body.no-scroll { overflow: hidden; }
img, video, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
h1, h2, h3, h4, p { margin: 0; font-weight: 400; }
.container { width: min(var(--container), 100% - 2 * var(--gutter)); margin-inline: auto; }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
/* The page's icon sprite (partials/symbols.html): a 0x0 svg of <symbol>s, out of the flow. */
.symbols { position: absolute; }

/* Type */
.h1 { font-family: var(--font-display); font-size: 68px; line-height: 0.95; letter-spacing: -0.02em; }
.h2 { font-family: var(--font-display); font-size: 52px; line-height: 52px; letter-spacing: -0.01em; text-align: center; text-wrap: balance; }
.lead { font-size: 16px; line-height: 24px; color: var(--muted); text-align: center; text-wrap: pretty; }
.section-head { display: flex; flex-direction: column; align-items: center; }
.section-head .h2 { margin-top: 0; }
.section-head .lead { margin-top: 20px; }
.section-head .btn { margin-top: 20px; }

/* Buttons */
.btn { display: inline-flex; align-items: center; justify-content: center; height: 41px; padding: 0 20px; border-radius: var(--radius-sm); font-size: 14px; line-height: 21px; white-space: nowrap; transition: opacity .2s ease, transform .2s ease; }
.btn:hover { opacity: .85; }
.btn--dark { background: var(--btn-dark); color: #fff; }
.btn--light { background: var(--white-90); color: var(--ink); }
.btn--nav { height: 35px; padding: 0 14px; background: #fff; color: var(--ink); }
.nav[data-theme="light"] .btn--nav { background: var(--btn-dark); color: #fff; }

/* Appear */
[data-appear] { opacity: 0; transform: translateY(24px); transition: opacity .8s cubic-bezier(.2,.65,.3,1), transform .8s cubic-bezier(.2,.65,.3,1); }
[data-appear].is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { [data-appear] { opacity: 1; transform: none; transition: none; } }

/* Nav */
.nav { position: fixed; inset: 0 0 auto 0; height: var(--nav-h); z-index: 50; color: #fff; transition: color .3s ease, background .3s ease; }
.nav[data-theme="light"] { color: var(--ink); }
.nav__inner { position: relative; display: flex; align-items: center; height: var(--nav-h); padding: 0 var(--gutter); }
.nav__logo { display: flex; align-items: center; gap: 8px; height: 24px; }
.nav__mark { width: 16px; height: 16px; color: currentColor; }
.nav__wordmark { font-family: var(--font-wordmark); font-size: 21px; line-height: 1; letter-spacing: -0.01em; transform: translateY(-1px); }
.nav__right { margin-left: auto; display: flex; align-items: center; gap: 10px; }
.nav[data-theme="light"].nav--scrolled { background: rgba(255,255,255,.92); backdrop-filter: blur(12px); }
.nav[data-theme="dark"].nav--scrolled { background: rgba(0,0,0,.35); backdrop-filter: blur(12px); }

/* Hero */
.hero { position: relative; height: 100vh; min-height: 640px; max-height: 1100px; background: #000; color: #fff; overflow: hidden; }
.hero__media { position: absolute; inset: 0; }
.hero__media img, .hero__media video { width: 100%; height: 100%; object-fit: cover; }
.hero__media::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 180px; background: linear-gradient(#000 0%, rgba(0,0,0,0) 100%); }
.hero__media::after { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 60%; background: linear-gradient(90deg, #000 0%, rgba(0,0,0,0) 100%); }
.hero__content { position: absolute; left: var(--gutter); right: var(--gutter); bottom: 50px; display: flex; align-items: flex-end; justify-content: space-between; gap: 40px; }
.hero__copy { max-width: 700px; }
.hero__copy .lead { text-align: left; color: var(--white-70); font-size: 18px; line-height: 27px; margin-top: 20px; max-width: 618px; }
.hero__copy .btn { margin-top: 20px; }
.hero .btn--light { height: 41px; }

/* Generic section */
.section { padding: var(--section-pad) 0; }

/* The quote carousel and its styles are gone (owner, 2026-11-06: the client quotes are captions in Expert guidance, styled in home.css). */

/* Closing */
.closing { position: relative; height: 810px; background: var(--dark-2); color: #fff; display: flex; align-items: center; justify-content: center; text-align: center; overflow: hidden; }
.closing__content { position: relative; }
.closing .h1 { text-align: center; }
.closing .h1 .line { display: block; text-wrap: balance; } /* one sentence per line at every width */
.closing .lead { color: #fff; font-size: 20px; line-height: 30px; margin-top: 18px; text-wrap: pretty; }
.closing .btn { margin-top: 20px; }

/* Tablet (810 to 1199) */
@media (max-width: 1199px) {
  :root { --gutter: 40px; --section-pad: 120px; }
  .h1 { font-size: 56px; }
  .h2 { font-size: 44px; line-height: 44px; }
  .hero__content { flex-direction: column; align-items: flex-start; gap: 30px; }
}

/* Mobile (< 810) */
@media (max-width: 809px) {
  :root { --gutter: 20px; --section-pad: 100px; }
  .btn--nav { height: 36px; padding: 0 12px; font-size: 13px; }
  .h1 { font-size: 44px; }
  .h2 { font-size: 36px; line-height: 38px; }
  .hero { height: 810px; min-height: 0; }
  .hero__content { bottom: 40px; }
  .hero__copy .lead { font-size: 16px; line-height: 24px; }
  .closing { height: 810px; }
  .closing .h1 { font-size: 36px; line-height: 1.04; }
}

/* Mobile refinements measured from biograph.com at 390 wide */
@media (max-width: 809px) {
  .h1 { font-size: 36px; line-height: 1; }
  .hero__copy .lead { max-width: none; }
  .hero__content { flex-direction: column; align-items: flex-start; }
  .h2 { font-size: 30px; line-height: 32px; }
}

/* ================= The Preambient advantage (product tour) ================= */
.advantage { padding: 120px 0; background: var(--surface); }
.advantage__wrap { display: grid; grid-template-columns: 460px 1fr; gap: 70px; align-items: center; }
.advantage__h { text-align: left; margin-top: 0; }
.tsteps { list-style: none; margin: 40px 0 0; padding: 0; border-top: 1px solid var(--line); }
.tstep__tab { display: grid; grid-template-columns: 34px 1fr; gap: 10px; width: 100%; padding: 18px 0 16px; text-align: left; border-bottom: 1px solid var(--line); color: var(--muted); }
/* The number drops 3px with top, not padding-top: padding made it 27px tall, 3px taller than the title, so a closed step's row
   held at 27px while the open sentence animated, and the list changed height mid-change. Same look. */
.tstep i { font-style: normal; font-size: 11px; letter-spacing: 1px; color: var(--muted); position: relative; top: 3px; font-variant-numeric: tabular-nums; }
.tstep strong { display: block; font-family: var(--font-body-medium); font-weight: 400; font-size: 17px; line-height: 24px; color: var(--muted); transition: color .3s; }
.tstep span { display: block; font-size: 14px; line-height: 20px; color: var(--muted); max-height: 0; opacity: 0; overflow: hidden; transition: max-height .45s cubic-bezier(.2,.65,.3,1), opacity .35s, margin .45s; }
.tstep__bar { display: block; height: 2px; margin-top: 0; background: var(--line); border-radius: 2px; overflow: hidden; position: relative; max-height: 0; transition: max-height .3s, margin .3s; }
.tstep__bar::after { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 100%; background: var(--ink); transform: scaleX(0); transform-origin: left; }
.tstep.is-active strong, .tstep.is-active i { color: var(--ink); }
.tstep.is-active span { max-height: 60px; opacity: 1; margin-top: 4px; }
.tstep.is-active .tstep__bar { max-height: 2px; margin-top: 12px; }
/* Every sentence opens to the height of the tallest one (site.js measures it into --tstep-desc), and the closing and opening
   sentences animate height over the same curve, so the list keeps one height through the change and the window under it
   (phones and tablets) does not jump as the tour advances. */
.tsteps.has-desc .tstep span[id] { max-height: none; height: 0; transition: height .45s cubic-bezier(.2,.65,.3,1), opacity .35s, margin .45s; }
.tsteps.has-desc .tstep.is-active span[id] { height: var(--tstep-desc); }
/* After the opening (site.js adds .is-open), the open sentence can grow past the measured height: with the reader's own text
   spacing or text size it is never cut off. Under normal settings it is never taller, so nothing moves. */
.tsteps.has-desc .tstep.is-active.is-open span[id] { min-height: min-content; }
@media (prefers-reduced-motion: reduce) { .tsteps.has-desc .tstep span[id] { transition: none; } }
/* site.js adds .run to the active step's bar on each show (so the bar restarts from 0) and keeps the tour .is-paused until it is first seen. */
.tstep.is-active .tstep__bar.run::after { animation: stepbar var(--tour, 7s) linear forwards; }
/* Paused (pointer or focus inside, or off screen): the bar waits with the timer. Held (a step was chosen): the tour stops, the bar shows full. */
.advantage.is-paused .tstep.is-active .tstep__bar::after { animation-play-state: paused; }
.advantage.is-held .tstep.is-active .tstep__bar::after { animation: none; transform: scaleX(1); }
@keyframes stepbar { to { transform: scaleX(1); } }
.tstep__tab[role="tab"] { cursor: pointer; } /* a plain list item until site.js makes it a tab */
.tstep__tab[role="tab"]:hover strong { color: var(--ink); }

/* The window is a grid: every pane sits in the same cell, so the window is as tall as its tallest pane and never jumps when panes switch. */
.screen { position: relative; display: grid; grid-template-rows: 40px auto; grid-template-columns: minmax(0, 1fr); min-height: 500px; border-radius: 18px; background: var(--surface); border: 1px solid var(--line); box-shadow: 0 30px 80px rgba(17,18,20,.10), 0 2px 6px rgba(17,18,20,.05); overflow: hidden; font-size: 13px; line-height: 18px; color: var(--ink); }
.screen__bar { display: flex; align-items: center; gap: 6px; height: 40px; padding: 0 16px; border-bottom: 1px solid var(--line); background: #fff; }
.screen__bar span { width: 9px; height: 9px; border-radius: 50%; background: #e4e3e8; }
.screen__bar b { margin-left: 12px; font-family: var(--font-body-medium); font-weight: 400; font-size: 12px; }
.screen__bar small { margin-left: auto; font-size: 10px; letter-spacing: 1px; text-transform: uppercase; color: var(--muted); padding: 3px 8px; border: 1px solid var(--line); border-radius: 999px; }
.pane { position: relative; grid-area: 2 / 1; display: flex; flex-direction: column; min-width: 0; padding: 24px 26px; visibility: hidden; opacity: 0; transform: translateY(10px); transition: opacity .5s, transform .5s, visibility 0s .5s; pointer-events: none; }
.pane.is-active { visibility: visible; opacity: 1; transform: none; pointer-events: auto; transition: opacity .5s, transform .5s; }
.pane:focus-visible { outline: none; }
.screen:has(.pane:focus-visible) { outline: 2px solid var(--ink); outline-offset: 4px; }
.pane__head { display: flex; justify-content: space-between; align-items: baseline; padding-bottom: 14px; border-bottom: 1px solid var(--line); }
.pane__head strong { font-family: var(--font-display); font-weight: 400; font-size: 18px; }
.pane__head span { font-size: 12px; color: var(--muted); } .pane__head em { font-style: normal; }
.pane [data-rise] { opacity: 0; transform: translateY(8px); }
.pane.is-active.play [data-rise] { animation: rise .55s cubic-bezier(.2,.65,.3,1) var(--d) forwards; }
@keyframes rise { to { opacity: 1; transform: none; } }
.pane [data-reveal] { opacity: 0; }
.pane.is-active.play [data-reveal] { animation: fade .5s var(--r, 4s) forwards; }
/* The time-use bar in the guidance pane (home.css) */
@keyframes grow-x { to { transform: scaleX(1); } }
.task { display: grid; grid-template-columns: 22px 1fr auto; gap: 12px; align-items: center; padding: 14px 0; border-bottom: 1px solid var(--line); }
.task i { width: 18px; height: 18px; border-radius: 50%; border: 1.5px solid #c9c8ce; position: relative; }
/* Done: the same check as the deal-team agent cards (ink disc, white tick), so it never reads as a radio button. The empty ring is the pending state. */
.task i::after { content: ""; position: absolute; left: 5px; top: 2.5px; width: 4px; height: 7px; border: solid #fff; border-width: 0 1.5px 1.5px 0; transform: rotate(45deg) scale(0); }
.pane.is-active.play .task i { animation: ring .3s calc(var(--d) + .5s) forwards; }
.pane.is-active.play .task i::after { animation: tick .3s cubic-bezier(.2,.65,.3,1) calc(var(--d) + .5s) forwards; }
@keyframes ring { to { border-color: var(--ink); background: var(--ink); } }
@keyframes tick { to { transform: rotate(45deg) scale(1); } }
.task strong { display: block; font-family: var(--font-body-medium); font-weight: 400; font-size: 14px; }
.task span { display: block; font-size: 12px; color: var(--muted); }
.task b { font-weight: 400; font-size: 11px; color: var(--muted); opacity: 0; }
.pane.is-active.play .task b { animation: fade .3s calc(var(--d) + .6s) forwards; }
.live { display: grid; grid-template-columns: 64px 1fr; gap: 12px; align-items: center; padding: 14px 0; border-bottom: 1px solid var(--line); }
.live b { font-family: var(--font-display); font-weight: 400; font-size: 30px; line-height: 32px; font-variant-numeric: proportional-nums; } /* static values in a fixed 64px column, so the width never moves */
.live b small { font-size: 14px; color: var(--muted); }
.live strong { display: block; font-family: var(--font-body-medium); font-weight: 400; font-size: 14px; }
.live span { display: block; font-size: 12px; color: var(--muted); }
.live--you { background: #fff; border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px; margin-top: 12px; }
.live--you b { color: #2f8f5b; }
.partner { display: flex; align-items: center; gap: 8px; margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line); font-size: 12px; color: var(--muted); --r: 3.2s; }
.partner img { width: 20px; height: 20px; border-radius: 50%; object-fit: cover; object-position: 50% 20%; flex: none; }
.partner span { color: #277a4d; }
/* Reduced motion: every pane shows its final state at once; nothing rises, draws or ticks, and the step bar shows full (the tour never auto-advances). */
@media (prefers-reduced-motion: reduce) {
  .pane, .pane.is-active { transform: none; }
  .pane [data-rise], .pane [data-reveal], .pane .task b, .pane .hold__end, .pane .hold .hold__lb { opacity: 1; transform: none; animation: none !important; }
  .pane .hold path { stroke-dashoffset: 0; animation: none !important; }
  .pane .timeuse i { transform: none; animation: none !important; }
  .pane .task i { border-color: var(--ink); background: var(--ink); animation: none !important; }
  .pane .task i::after { transform: rotate(45deg) scale(1); animation: none !important; }
  .tstep.is-active .tstep__bar::after { animation: none; transform: scaleX(1); }
  .tstep span, .tstep__bar, .tstep strong { transition: none; }
}
@media (min-width: 1200px) { .advantage { padding: 130px 0; } }
@media (max-width: 1199px) { .advantage__wrap { grid-template-columns: 1fr; gap: 40px; } .screen { min-height: 500px; } }
@media (max-width: 809px) { .advantage { padding: 80px 0; } .advantage__h { font-size: 32px; line-height: 34px; } .screen { min-height: 510px; font-size: 12px; } .pane { padding: 18px; } }

/* FINDING-001 + 2026-09-15: closing copy readable over the bright film */
.closing::before { content: ""; position: absolute; inset: 0; background: radial-gradient(ellipse 62% 58% at 50% 50%, rgba(0,0,0,.55), rgba(0,0,0,.22) 70%, rgba(0,0,0,.12) 100%); pointer-events: none; z-index: 1; }
.closing .h1, .closing .lead { text-shadow: 0 2px 28px rgba(0,0,0,.55), 0 1px 3px rgba(0,0,0,.45); }

.closing__content { max-width: 980px; padding: 0 var(--gutter); z-index: 2; }
/* FINDING-005: tour window title stays on one line on phone */
@media (max-width: 809px) { .screen__bar b { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; flex: 1; margin-left: 8px; font-size: 11px; } .screen__bar { padding: 0 12px; } }

/* Shared keyframe: fade in */
@keyframes fade { to { opacity: 1; } }

/* Credits page */
.credits { padding: 150px 0 120px; }
.credits__body .h2, .credits__body .lead { text-align: left; }
.credits__body .lead { max-width: 640px; }
.credits__body h2 { font-family: var(--font-body-medium); font-size: 16px; line-height: 24px; margin: 48px 0 12px; }
.credits__body ul { list-style: none; margin: 0; padding: 0; max-width: 760px; }
.credits__body li { padding: 12px 0; border-top: 1px solid var(--line); font-size: 14px; line-height: 21px; color: var(--muted); }
.credits__body li strong { font-family: var(--font-body-medium); font-weight: 400; color: var(--ink); }
.credits__body li a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.credits__body li a[href^="https://creativecommons.org"] { white-space: nowrap; } /* "CC BY 3.0" never breaks across lines */
.credits .lead { margin-top: 18px; }
/* Privacy: a long-form legal page. One row per topic under a hairline: the topic on the left from 810px, the text at
   16/26 in a 640px measure (about 70 characters a line) on the right; one column on phones. The date is a small footnote. */
.legal__item { display: grid; grid-template-columns: minmax(0, 280px) minmax(0, 640px); gap: 8px 40px; padding: 24px 0 28px; border-top: 1px solid var(--line); }
.legal__item:first-of-type { margin-top: 56px; }
.legal__item h2 { margin: 0; font-family: var(--font-body-medium); font-weight: 400; font-size: 16px; line-height: 26px; color: var(--ink); }
.legal__item p { margin: 0; font-size: 16px; line-height: 26px; color: var(--muted); text-wrap: pretty; }
.legal__item a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.legal__date { margin: 0; padding-top: 24px; border-top: 1px solid var(--line); font-size: 14px; line-height: 21px; color: var(--muted); }
@media (max-width: 809px) { .legal__item { grid-template-columns: minmax(0, 1fr); padding: 20px 0 24px; } .legal__item:first-of-type { margin-top: 40px; } }

/* Phone: closing headlines wrap naturally (no forced breaks) (2026-09-15 review) */
@media (max-width: 809px) {
  .closing .lead { font-size: 17px; line-height: 25px; }
}
/* Design review 2026-09-15 */
/* FINDING-001: themed keyboard focus ring (browser default was the only focus indicator) */
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
[data-theme="dark"] :focus-visible, .hero :focus-visible, .closing :focus-visible, .nav[data-theme="dark"] :focus-visible { outline-color: #fff; }
/* FINDING-003: 44px touch targets on touch devices */
@media (hover: none), (max-width: 809px) { .btn { min-height: 44px; } }
/* FINDING-004: themed text selection */
::selection { background: var(--ink); color: #fff; }
[data-nav-theme="dark"] ::selection, .closing ::selection, .hero ::selection { background: #fff; color: var(--ink); }
/* ISSUE-002: skip link for keyboard users */
.skip { position: fixed; left: 16px; top: -60px; z-index: 1100; padding: 10px 14px; background: var(--ink); color: #fff; border-radius: var(--radius-sm); font-size: 14px; transition: top .2s; }
.skip:focus { top: calc(var(--nav-h) + 8px); outline-color: #fff; } /* below the fixed nav, not under or over it: fully visible on back-tab too (S-1); above everything but the booking dialog */

/* Booking modal: Cal.com inside the page */
.book { position: fixed; inset: 0; z-index: 1200; display: flex; align-items: center; justify-content: center; padding: 24px; }
.book[hidden] { display: none; }
.book__backdrop { position: absolute; inset: 0; background: rgba(17,18,20,.6); backdrop-filter: blur(6px); }
.book__panel { position: relative; display: flex; flex-direction: column; width: min(1040px, 100%); height: min(820px, 100%); background: #fff; border-radius: var(--radius); overflow: hidden; box-shadow: 0 40px 100px rgba(0,0,0,.35); }
/* Header band: the dialog's title on the left, the close button on the right. */
.book__head { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 16px; height: 64px; padding: 0 12px 0 24px; border-bottom: 1px solid var(--line); }
.book__title { font-family: var(--font-body-medium); font-weight: 400; font-size: 16px; line-height: 22px; color: var(--ink); }
.book__frame { flex: 1; min-height: 0; width: 100%; border: 0; display: block; background: #fff; }
.book__close { flex: none; width: 40px; height: 40px; border-radius: 50%; background: #fff; border: 1px solid var(--line); color: var(--ink); display: inline-flex; align-items: center; justify-content: center; z-index: 1; }
.book__close svg { width: 14px; height: 14px; }
.book__close:hover { background: var(--surface); }
/* Loading, fallback and calendar states (site.js). Until the calendar has loaded, the frame is transparent,
   takes no taps and is inert, and three muted dots pulse in the panel (aria-busy on the frame; "Loading the calendar." in the status line).
   .is-blocked (host refused, or no calendar after 8 s): the fallback line shows; the dots stay above it while a slow calendar may still
   arrive. When it does: .is-swapping fades the line out with taps already off, and only then .is-ready shows the frame and gives it the
   taps, so a tap aimed at a fallback link never lands on the calendar mid-swap. */
.book__frame { position: relative; opacity: 0; pointer-events: none; transition: opacity .2s ease; }
.book__panel.is-ready .book__frame { opacity: 1; pointer-events: auto; }
.book__wait { position: absolute; left: 50%; top: calc(50% + 32px); transform: translate(-50%, -50%); display: flex; gap: 8px; }
.book__wait span { width: 6px; height: 6px; border-radius: 50%; background: var(--muted); opacity: .25; animation: book-wait 1.2s ease-in-out infinite; }
.book__wait span:nth-child(2) { animation-delay: .2s; }
.book__wait span:nth-child(3) { animation-delay: .4s; }
@keyframes book-wait { 0%, 80%, 100% { opacity: .25; } 40% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .book__wait span { animation: none; opacity: .6; } .book__frame { transition: none; } }
/* The dots go with the line when a slow calendar takes over (.is-swapping), not back to the centre for the fade. */
.book__panel.is-ready .book__wait, .book__panel.is-refused .book__wait, .book__panel.is-swapping .book__wait { display: none; }
/* Forced colours paint backgrounds as Canvas: the dots keep the text colour, so the panel still shows that it is loading. */
@media (forced-colors: active) { .book__wait span { forced-color-adjust: none; background: CanvasText; } }
.book__panel.is-blocked .book__wait { top: calc(50% - 60px); }
.book__fallback { position: absolute; left: 24px; right: 24px; top: 50%; transform: translateY(-50%); max-width: 30em; margin-inline: auto; text-align: center; font-size: 16px; line-height: 24px; color: var(--ink); text-wrap: balance; visibility: hidden; transition: opacity .2s ease; }
.book__panel.is-blocked .book__fallback { visibility: visible; }
.book__panel.is-swapping .book__fallback { visibility: visible; opacity: 0; pointer-events: none; }
.book__fallback a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; white-space: nowrap; }
/* The focus ring sits 1px out, inside the word spaces, so it does not touch "?" or "or". The room for it is 2px more word
   spacing on the whole line, not margins on the links: every gap in the sentence stays the same width. */
.book__fallback { word-spacing: 2px; }
.book__fallback a:focus-visible { outline-offset: 1px; }
.book__panel.is-blocked .book__frame { visibility: hidden; }
@media (max-width: 809px) { .book { padding: 0; } .book__panel { width: 100%; height: 100%; border-radius: 0; } }

/* Resilience (2026-09-15): nothing is hidden unless the script is confirmed running. If JS is off, blocked, fails to load, or throws, every animated element renders in its final state. */
html:is(:not(.js), .js-failed) :is([data-appear], .pane [data-rise], .pane [data-reveal], .task b) { opacity: 1 !important; transform: none !important; animation: none !important; transition: none !important; }
html:is(:not(.js), .js-failed) .pane { visibility: visible; opacity: 1; transform: none; pointer-events: auto; }
html:is(:not(.js), .js-failed) .pane:not(.is-active) { display: none; }
html:is(:not(.js), .js-failed) .screen { min-height: 0; }
/* Guidance: every step's sentence shows; only the first pane is shown (above). */
html:is(:not(.js), .js-failed) .tstep span { max-height: none; opacity: 1; margin-top: 4px; }
html.js-failed .tsteps.has-desc .tstep span[id] { height: auto; }
html:is(:not(.js), .js-failed) .tstep__bar { display: none; } /* nothing advances, so no progress bar */
/* Mobile QA pass (2026-09-15 night) */
@media (max-width: 809px) {
  .pane.is-active.play [data-rise] { animation-delay: calc(var(--d) * .45); }
}
/* Email links get their href from site.js (data-mail). Without JavaScript they are plain words, not links. */
a[data-mail]:not([href]) { color: inherit; text-decoration: none; cursor: auto; }
