/* DuVoca site. Tokens: DESIGN.md §3 and UI.md §9 (light by default, the night "lamp" in dark mode).
   Headlines: Sora (OFL, self-hosted, Latin only; other scripts fall back to the system face). */
@font-face { font-family: "Sora"; src: url("/assets/fonts/sora-latin.woff2") format("woff2"); font-weight: 600 700; font-display: swap; unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: "Sora"; src: url("/assets/fonts/sora-latin-ext.woff2") format("woff2"); font-weight: 600 700; font-display: swap; unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF; }

:root {
  color-scheme: light dark;
  --bg: #F8F6FC; --surface: #FFFFFF; --text: #1B1530; --text2: #4E4766; --quiet: #6E6880; --hair: #E6E1F2;
  --me: #4B2FBF; --me-fill: #4B2FBF; --me-fill-ink: #FFFFFF;
  --guest: #F5A623; --guest-ink: #996000; --guest-tint: #FFEFC7; --guest-edge: #7A4E00;
  --stage: #2E2159; --head: #1B1530; --accent: #4B2FBF; --link: #4B2FBF;
  --shadow: 0 1px 2px rgba(27, 21, 48, 0.06), 0 8px 24px rgba(27, 21, 48, 0.08);
  --radius: 20px; --gutter: 16px; --max: 1120px;
  --font-head: "Sora", -apple-system, "SF Pro Display", system-ui, "Segoe UI", Roboto, sans-serif;
  --font-body: -apple-system, "SF Pro Text", system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #141021; --surface: #1E1930; --text: #F4F1FB; --text2: #C9C3DB; --quiet: #ABA5BF; --hair: #2B2350;
    --me: #A99BFF; --me-fill: #8B6CFF; --me-fill-ink: #141021;
    --guest: #FFBE45; --guest-ink: #FFD27A; --guest-tint: #3B2D0E; --guest-edge: #FFBE45;
    --head: #FFBE45; --accent: #A99BFF; --link: #C4B2FF;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.35);
  }
}
@media (min-width: 720px) { :root { --gutter: 32px; } }

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: 76px; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body { margin: 0; background: var(--bg); color: var(--text); font: 17px/1.55 var(--font-body); -webkit-font-smoothing: antialiased; }
img { max-width: 100%; height: auto; display: block; }
a { color: var(--link); text-underline-offset: 0.18em; }
a:hover { text-decoration-thickness: 2px; }
:focus-visible { outline: 3px solid var(--me); outline-offset: 3px; border-radius: 6px; }
h1, h2, h3 { font-family: var(--font-head); color: var(--head); line-height: 1.15; margin: 0; letter-spacing: -0.01em; text-wrap: balance; overflow-wrap: break-word; hyphens: auto; }
:lang(ja) h1, :lang(ja) h2, :lang(ja) h3, :lang(ko) h1, :lang(ko) h2, :lang(ko) h3, :lang(zh-Hant) h1, :lang(zh-Hant) h2, :lang(zh-Hant) h3 { letter-spacing: 0; line-height: 1.3; }
/* Korean breaks lines at spaces, never inside a word; Japanese headings only at the <wbr> word boundaries
   the build inserts. */
:lang(ko) { word-break: keep-all; overflow-wrap: break-word; }
:lang(ja) :is(h1, h2, h3) { word-break: keep-all; overflow-wrap: anywhere; }
h2 { font-size: clamp(28px, 4.2vw, 40px); }
h3 { font-size: 20px; }
p { margin: 0; }
.wrap { width: 100%; max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter); }
.skip { position: absolute; left: 8px; top: -60px; z-index: 10; padding: 10px 14px; background: var(--surface); color: var(--text); border-radius: 10px; }
.skip:focus { box-shadow: var(--shadow); }
.skip:focus { top: 8px; }
/* Author display rules beat the browser's own [hidden]. */
[hidden] { display: none !important; }
.vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }

/* Header */
.top { position: sticky; top: 0; z-index: 5; background: color-mix(in srgb, var(--bg) 88%, transparent); -webkit-backdrop-filter: saturate(1.4) blur(14px); backdrop-filter: saturate(1.4) blur(14px); border-bottom: 1px solid var(--hair); }
.top .wrap { display: flex; align-items: center; gap: 16px; min-height: 60px; }
.brand { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; color: var(--text); text-decoration: none; font: 700 19px/1 var(--font-head); }
.brand img { width: 32px; height: 32px; border-radius: 8px; }
.menu { display: none; margin-left: auto; gap: 22px; }
.menu a { color: var(--text2); text-decoration: none; font-size: 15px; font-weight: 500; display: inline-flex; align-items: center; min-height: 44px; }
.menu a:hover { color: var(--text); }
@media (min-width: 900px) { .menu { display: flex; } }
.lang { position: relative; margin-left: auto; }
@media (min-width: 900px) { .lang { margin-left: 8px; } }
.lang summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; padding: 8px 12px; min-height: 44px; border: 1px solid var(--hair); border-radius: 999px; color: var(--text2); font-size: 15px; background: var(--surface); }
.lang summary::-webkit-details-marker { display: none; }
.lang summary svg { width: 16px; height: 16px; }
.lang ul { position: absolute; right: 0; top: calc(100% + 8px); margin: 0; padding: 8px; list-style: none; background: var(--surface); border: 1px solid var(--hair); border-radius: 14px; box-shadow: var(--shadow); display: grid; grid-template-columns: repeat(2, minmax(130px, 1fr)); gap: 2px; width: max-content; max-width: calc(100vw - 2 * var(--gutter)); max-height: calc(100vh - 76px); max-height: calc(100dvh - 76px); overflow-y: auto; overscroll-behavior: contain; }
.lang li a { display: flex; align-items: center; min-height: 44px; padding: 0 10px; border-radius: 8px; color: var(--text); text-decoration: none; font-size: 15px; }
.lang li a:hover { background: var(--bg); }
.lang li a[aria-current="page"] { color: var(--me); font-weight: 600; }

/* Hero */
.hero { padding: 40px 0 56px; }
.hero .wrap { display: grid; gap: 32px; align-items: center; }
.hero .wrap > * { min-width: 0; }
@media (min-width: 1000px) { .hero .wrap { grid-template-columns: 5fr 7fr; gap: 48px; } .hero { padding: 72px 0 88px; } .hero h1.long { font-size: clamp(38px, 5vw, 54px); } }
.kicker { color: var(--accent); font-weight: 600; font-size: 15px; letter-spacing: 0.02em; margin-bottom: 14px; }
/* The app's name is never hyphenated; a long local name gets a smaller size in the two-column hero (.long). */
.hero h1 { font-size: clamp(38px, 6.2vw, 64px); line-height: 1.04; hyphens: manual; }
.hero h1 { color: var(--text); }
.hero h1 .local { color: var(--head); }
@media (prefers-color-scheme: light) { .hero h1 .local { color: var(--me); } }
.subtitle { margin-top: 14px; font-size: 20px; font-weight: 600; color: var(--text2); }
.lead { margin-top: 18px; font-size: 19px; color: var(--text); max-width: 34em; }
.soon { margin-top: 26px; display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
.pill { display: inline-flex; align-items: center; gap: 10px; min-height: 48px; padding: 10px 20px; border-radius: 999px; background: var(--me-fill); color: var(--me-fill-ink); font-weight: 650; font-size: 16px; }
.pill svg { width: 18px; height: 18px; }
.requires { margin-top: 12px; font-size: 14px; color: var(--quiet); }
.hero-media { position: relative; margin: 0; border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); background: var(--surface); aspect-ratio: 16 / 9; }
.hero-media img { width: 100%; height: 100%; object-fit: cover; }

/* The lift (public/assets/js/motion.js; only with JS, IntersectionObserver and no reduced motion): a copy of the
   "How it works" screen flies from the phone in the photo to the device, on a matrix3d() the script writes per
   frame; the phone in the photo shows a switched-off screen meanwhile (.lift-off, tools/composite.py --off). The
   copy lives in the document, not fixed, so between frames it scrolls with the page. */
.hero-media .lift-off { position: absolute; width: auto; height: auto; max-width: none; pointer-events: none; visibility: hidden; }
.hero-media .lift-off.is-on { visibility: visible; }
.lift { position: absolute; left: 0; top: 0; z-index: 4; transform-origin: 0 0; pointer-events: none; visibility: hidden; opacity: 0; }
.lift-bezel { position: absolute; inset: -11px; border-radius: 54px; background: #0E0B17; box-shadow: 0 0 0 1px #3A3450 inset, var(--shadow); opacity: 0; }
.lift .lift-screen { position: relative; border-radius: 43px; overflow: hidden; }
/* The copy starts as the photo's own screen: the hero picture, cropped around the display and mapped back through
   the inverse of the copy's first matrix (motion.js writes both), over the live screen; it fades out by 25 %. */
.lift .lift-photo { position: absolute; left: 0; top: 0; overflow: hidden; transform-origin: 0 0; pointer-events: none; }
.lift .lift-photo img { position: absolute; max-width: none; }
/* The device waits for the copy; its caption, the mock's only text description, stays. */
.device.is-lifting .device-frame { visibility: hidden; }

/* Sections */
.section { padding: 64px 0; border-top: 1px solid var(--hair); }
@media (min-width: 900px) { .section { padding: 88px 0; } }
.section-lead { margin-top: 14px; color: var(--text2); font-size: 18px; max-width: 40em; }

/* How it works: the live screen mock beside three steps; from 900 px the device stands on the right, under the
   hero picture, so the lift is a short drop rather than a diagonal across the heading. */
.how-grid { display: grid; gap: 40px; margin-top: 36px; align-items: center; }
@media (min-width: 900px) {
  .how-grid { grid-template-columns: 1fr minmax(260px, 340px); gap: 64px; }
  .how .device { grid-column: 2; grid-row: 1; }
  .how .steps { grid-column: 1; grid-row: 1; }
}
.device { margin: 0 auto; width: min(320px, 82vw); }
.device-frame { padding: 11px; border-radius: 54px; background: #0E0B17; box-shadow: 0 0 0 1px #3A3450 inset, var(--shadow); }
.device-frame .dv-display { border-radius: 43px; overflow: hidden; }
/* On the page the guest chip may use its padding: the label stays whole (the app itself ellipsizes, UI.md). */
:is(.device, .talk-fig, .lift) .dv-chip > span { overflow: visible; text-overflow: clip; }
.device figcaption { margin-top: 14px; text-align: center; color: var(--quiet); font-size: 14px; }
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 28px; counter-reset: step; }
.steps li { position: relative; padding-left: 60px; counter-increment: step; }
.steps li::before, .steps h3::before { content: counter(step); position: absolute; left: 0; top: -2px; width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; background: var(--guest-tint); color: var(--guest-ink); border: 1px solid var(--guest-edge); font: 700 18px/1 var(--font-head); }
.steps h3::before { content: none; }
.steps p { margin-top: 6px; color: var(--text2); }
/* Wide, tall windows (the same query as STICKY_QUERY in motion.js): the device stays in view while the steps go
   by, by CSS alone; with JS its screen follows the active step. Screen only: a landscape page (A4 or Letter, small
   margins) is wide and tall enough too, and print gets the compact list (a sticky device split across pages and
   printed over the conversation, a screen of empty paper per step, the inactive steps greyed). */
@media screen and (min-width: 900px) and (min-height: 760px) {
  .how-grid { align-items: start; }
  .how .device { position: sticky; top: 76px; width: min(320px, calc((100vh - 180px) * 0.4613 + 22px)); width: min(320px, calc((100svh - 180px) * 0.4613 + 22px)); }
  /* A screen of scroll per step only where motion.js drives the device: scripts on, no reduced motion, no forced
     colours, from the first paint (no shift when the script starts). Without JS, with reduced motion or forced
     colours the steps stay a compact list, and so they do when the script runs but does not drive the device (no
     IntersectionObserver, an error): motion.js then marks the section data-static. Browsers without the scripting
     media feature (Safari before 17, Chrome before 120, Firefox before 113) skip this block: a compact list that
     the device still follows. The step number moves onto the title, so it stays beside it when a step's text is
     centred in its block. */
  @media (scripting: enabled) and (prefers-reduced-motion: no-preference) and (forced-colors: none) {
    .how:not([data-static]) .steps { gap: 0; }
    .how:not([data-static]) .steps li { min-height: 58vh; min-height: 58svh; display: flex; flex-direction: column; justify-content: center; padding-top: 24px; padding-bottom: 24px; }
    .how:not([data-static]) .steps li:first-child { justify-content: flex-start; padding-top: 4px; }
    .how:not([data-static]) .steps li:last-child { min-height: calc(100vh - 76px); min-height: calc(100svh - 76px); justify-content: flex-start; padding-top: 25vh; padding-top: 25svh; }
    .how:not([data-static]) .steps li::before { content: none; }
    .how:not([data-static]) .steps h3 { position: relative; }
    .how:not([data-static]) .steps h3::before { content: counter(step); left: -60px; top: 50%; margin-top: -20px; }
  }
  .how[data-step="1"] .steps li:not([data-step="1"]) :is(h3, p),
  .how[data-step="2"] .steps li:not([data-step="2"]) :is(h3, p),
  .how[data-step="3"] .steps li:not([data-step="3"]) :is(h3, p) { color: var(--quiet); }
  @media (prefers-reduced-motion: no-preference) {
    .how .steps :is(h3, p) { transition: color 0.4s ease; }
  }
}

/* The conversation (#talk): the place buttons and under them Pause / Start over / Listen, beside the phone on wide
   windows (level with its top, not centred beside it, so Pause is in sight early: the loop waits for it) and above
   it on narrow ones, so Pause comes before the conversation that moves by itself (WCAG 2.2.2);
   above the phone the person across the table, below it you, each with what they say (word by word while they
   speak, with JS). Wide windows size the phone by the small viewport height (svh; without svh support it keeps its
   narrow width). */
.talk-grid { display: grid; gap: 28px; align-items: center; }
@media (min-width: 900px) { .talk-grid { grid-template-columns: 1fr minmax(280px, 360px); gap: 64px; } .talk-stage { grid-column: 2; grid-row: 1; } .talk-side { grid-column: 1; grid-row: 1; align-self: start; } }
.talk-side { display: grid; gap: 16px; align-content: start; min-width: 0; }
.talk-side .section-lead { margin: 0 0 8px; }
.talk-places, .talk-controls { display: flex; flex-wrap: wrap; gap: 10px; }
/* The playback row sits a little apart from the places, a group of its own. */
.talk-controls { margin-top: 6px; }
.talk :is(.talk-places, .talk-controls) button { min-height: 44px; padding: 10px 18px; border-radius: 999px; border: 1px solid var(--hair); background: var(--surface); color: var(--text); font: 600 16px/1.2 var(--font-body); cursor: pointer; }
.talk :is(.talk-places, .talk-controls) button:hover { border-color: color-mix(in srgb, var(--me) 45%, var(--hair)); }
.talk-places button[aria-pressed="true"] { background: var(--me-fill); color: var(--me-fill-ink); border-color: var(--me-fill); }
.talk-note { margin-top: -6px; color: var(--quiet); font-size: 14px; }
.talk-stage { min-width: 0; width: 100%; max-width: 360px; justify-self: center; }
.talk-fig { margin: 0; display: grid; gap: 14px; }
.talk-fig .device-frame { justify-self: center; width: min(272px, 70vw); border-radius: 46px; padding: 9px; }
.talk-fig .device-frame .dv-display { border-radius: 37px; }
/* The other person's half keeps the room of its "Hearing" chip without JS too, so going live moves no text. */
.talk-fig .dv-pane--guest .dv-units { padding-bottom: calc(var(--pt) * 56); }
@media (min-width: 900px) { .talk-fig .device-frame { width: clamp(240px, calc((100svh - 330px) * 0.4613 + 18px), 290px); } }
.talk-say { min-width: 0; padding-left: 12px; border-left: 3px solid var(--me); }
.talk-say--guest { border-left-color: var(--guest); }
.talk-who { font-size: 13px; line-height: 1.4; font-weight: 600; color: var(--quiet); letter-spacing: 0.01em; }
.talk-lines { display: grid; margin-top: 2px; }
.talk-lines > .talk-line { grid-area: 1 / 1; }
.talk-line { font-size: 17px; line-height: 1.4; color: var(--text); }
/* Without JS: each person's last sentence (yours is o2; o1 shares its place). */
.talk-lines > [data-say="o1"] { visibility: hidden; }
.talk-fig figcaption { text-align: center; color: var(--quiet); font-size: 14px; }
/* Live (motion.js): a sentence shows while it is said and stays, quieter, until the same person speaks again. */
.talk-fig[data-live] .talk-line { visibility: hidden; }
.talk-fig[data-live] .talk-line:is(.is-saying, .is-said) { visibility: visible; }
.talk-fig[data-live] .talk-line.is-said { color: var(--text2); }
.talk-fig[data-live] .talk-line.is-saying .w:not(.is-on) { opacity: 0; }
@media (prefers-reduced-motion: no-preference) {
  .talk-fig[data-live] .talk-line .w { transition: opacity 0.18s ease-out; }
  .talk-fig[data-live] :is(.talk-line, .dv-units) { transition: opacity 0.3s ease; }
  .talk-fig.is-fading :is(.talk-line, .dv-units) { opacity: 0; }
  .talk-say.is-speaking .talk-who::after { content: ""; display: inline-block; width: 7px; height: 7px; margin-left: 8px; border-radius: 50%; background: currentColor; vertical-align: 1px; animation: talk-dot 0.9s ease-in-out infinite alternate; }
  @keyframes talk-dot { from { opacity: 0.25; } to { opacity: 1; } }
}
/* Pause, a hidden tab or the section out of view freeze what still moves: the ring and the speaking dot (motion.js
   sets data-paused while the loop waits; WCAG 2.2.2). !important: the rules that start them use the animation
   shorthand, which resets the play state, and they are more specific than this one. */
.talk[data-paused] .dv-ring, .talk[data-paused] .talk-who::after { animation-play-state: paused !important; }

/* Scenes */
.scene-grid { list-style: none; margin: 32px 0 0; padding: 0; display: grid; gap: 20px; }
.scene-grid li:only-child { grid-column: 1 / -1; justify-self: center; width: min(100%, 720px); }
@media (min-width: 720px) { .scene-grid { grid-template-columns: repeat(2, 1fr); } }
.scene-grid figure { margin: 0; }
.scene-grid img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border-radius: var(--radius); box-shadow: var(--shadow); background: var(--surface); }
.scene-grid figcaption { margin-top: 12px; font-weight: 600; }

/* Privacy */
.privacy-card { margin-top: 28px; padding: 28px; border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow); display: grid; gap: 18px; }
@media (min-width: 900px) { .privacy-card { padding: 36px 40px; } }
.privacy-card .lead { margin: 0; font-weight: 600; }
.checks { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.checks li { position: relative; padding-left: 32px; }
.checks li::before { content: ""; position: absolute; left: 2px; top: 0.3em; width: 18px; height: 18px; border-radius: 50%; background: var(--me-fill) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M5.5 10.5l3 3 6-7' stroke='white' stroke-width='2.2' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 14px no-repeat; }
.note { color: var(--text2); font-size: 16px; }

/* Languages */
.chips { list-style: none; margin: 22px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 10px; }
.chips li { padding: 10px 16px; min-height: 44px; display: inline-flex; align-items: center; border-radius: 999px; background: var(--surface); border: 1px solid var(--hair); font-weight: 600; }
.chips li:nth-child(odd) { border-color: color-mix(in srgb, var(--me) 45%, var(--hair)); }
.chips li:nth-child(even) { border-color: color-mix(in srgb, var(--guest) 60%, var(--hair)); }
.ui-only { margin-top: 18px; color: var(--text2); }

/* Price */
.price-card { margin-top: 28px; padding: 28px; border-radius: var(--radius); background: var(--surface); box-shadow: var(--shadow); max-width: 760px; display: grid; gap: 14px; }
.price-card p:first-child { font-size: 19px; }

/* FAQ */
.faq-list { margin-top: 28px; display: grid; gap: 12px; max-width: 860px; }
.faq-list details { background: var(--surface); border: 1px solid var(--hair); border-radius: 16px; padding: 0 20px; }
.faq-list summary { cursor: pointer; list-style: none; padding: 18px 28px 18px 0; position: relative; font-weight: 600; min-height: 44px; }
.faq-list summary::-webkit-details-marker { display: none; }
.faq-list summary::after { content: ""; position: absolute; right: 2px; top: 50%; width: 10px; height: 10px; margin-top: -7px; border-right: 2px solid var(--quiet); border-bottom: 2px solid var(--quiet); transform: rotate(45deg); transition: transform 0.15s; }
.faq-list details[open] summary::after { transform: rotate(-135deg); margin-top: -2px; }
@media (prefers-reduced-motion: reduce) { .faq-list summary::after { transition: none; } }
.faq-list details p { padding: 0 0 18px; color: var(--text2); }

/* Text pages (privacy, support, 404) */
.doc { padding: 48px 0 80px; }
.doc .wrap { max-width: 780px; }
.doc h1 { font-size: clamp(24px, 7vw, 46px); }
.doc .meta { margin-top: 10px; color: var(--quiet); font-size: 15px; }
.doc .intro { margin-top: 20px; font-size: 19px; }
.doc h2 { font-size: 22px; margin-top: 40px; }
.doc p + p { margin-top: 12px; }
.doc h2 + p { margin-top: 10px; }
.doc .toc { margin: 28px 0 0; padding: 18px 22px; background: var(--surface); border: 1px solid var(--hair); border-radius: 14px; columns: 2 220px; list-style: none; }
.doc .toc a { display: inline-flex; align-items: center; min-height: 44px; }

/* Footer */
.foot { border-top: 1px solid var(--hair); padding: 40px 0 56px; color: var(--text2); font-size: 15px; }
.foot .wrap { display: grid; gap: 16px; }
@media (min-width: 900px) { .foot .wrap { grid-template-columns: 1fr auto; align-items: start; } }
.foot nav { display: flex; flex-wrap: wrap; gap: 0 20px; }
.foot a { color: var(--text2); }
.foot nav a, .foot .brand { display: inline-flex; align-items: center; min-height: 44px; }
.foot .brand { margin-bottom: 6px; }
.foot-langs { display: flex; flex-wrap: wrap; gap: 0 16px; margin-top: 8px; font-size: 14px; }
.foot-langs a { text-decoration: none; }
.foot-langs a[aria-current="page"] { color: var(--text); font-weight: 600; }

/* Print: the finished page, never a screen in mid-flight. The header stays at the top of the first page (sticky,
   it printed where the visitor had scrolled to, across the conversation's phone). */
@media print {
  .top { position: static !important; }
  .lift, .hero-media .lift-off { display: none !important; }
  .device.is-lifting .device-frame { visibility: visible; }
  /* The conversation: each person's last sentence, whole, without the buttons. */
  .talk-places, .talk-controls, .talk-note { display: none !important; }
  .talk-fig[data-live] .talk-line { visibility: visible !important; color: var(--text) !important; }
  .talk-fig .talk-lines > [data-say="o1"] { visibility: hidden !important; }
  .talk-fig .talk-line .w, .talk-fig :is(.talk-line, .dv-units) { opacity: 1 !important; }
  /* No speaking dot after the speaker's label: a live sign, on a page printed while someone spoke. */
  .talk-say .talk-who::after { content: none !important; }
}
/* A landscape page (A4, Letter) is about as tall as a phone: a phone that does not fit on what is left of a page
   starts the next one instead of being cut across two. The phones' frames only: on their whole figures Chromium
   printed an empty page. Portrait pages print as before. */
@media print and (orientation: landscape) {
  .how .device-frame, .talk-fig .device-frame { break-inside: avoid; }
}
