/* The live-phone demo: one morning with Wakeprint (internal-docs/site-demo/SPEC.md).
   A dawn like the site's hero, made of style.css's tokens.

   The markup is the steps as a list, each beside its screen: the page without
   JavaScript, and with reduced motion. Where demo.js can run it (the snippet's
   inline script sets html.demo-scroll before the first paint), the section
   grows tall and its stage pins to the screen: the visitor's own scrolling
   plays the morning, and scrolling back plays it backwards. demo.js writes
   only transform and opacity, once a frame. */

/* ------------------------------------------------------------------ */
/* Shared: the words                                                  */

.demo__pin::before {
  /* Under the hero: its hill runs on into the demo's sky, which rises out
     of the hill's colour, so no edge shows between the two dawns. */
  content: "";
  position: absolute;
  z-index: 0;
  top: 0;
  right: 0;
  left: 0;
  height: clamp(110px, 14vw, 200px);
  background: linear-gradient(var(--deep), rgba(23, 28, 56, 0));
  pointer-events: none;
}

.demo__body {
  position: relative;
}

.demo__head {
  position: relative;
  z-index: 5;
}

h2.demo__name {
  color: var(--sky-ink);
  font-size: clamp(1rem, 0.94rem + 0.35vw, 1.3rem);
  line-height: 1.25;
  letter-spacing: -0.01em;
}

.demo__steps {
  margin: 0;
  padding: 0;
  list-style: none;
}

.demo__step {
  position: relative;
  z-index: 5;
}

.demo__cues {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  margin: 0 0 14px;
}

.demo__cues .chip {
  margin: 0;
}

.demo__cues .tag {
  margin: 0;
  background: rgba(255, 255, 255, 0.14);
  color: var(--sky-ink);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.22);
}

.dawn .demo__title {
  max-width: 22ch;
  font-size: clamp(1.55rem, 1.2rem + 1.6vw, 2.9rem);
  line-height: 1.08;
  text-wrap: balance;
}

.demo__sub {
  max-width: 30rem;
  margin-top: 10px;
  color: var(--sky-muted);
  font-size: clamp(1rem, 0.95rem + 0.4vw, 1.25rem);
  font-weight: 600;
  line-height: 1.35;
  text-wrap: pretty;
}

/* Step 2: the Morning Note, quoted, with a small speaking glyph. */
.demo__note {
  margin: 12px 0 0;
}

.demo__note-label {
  color: var(--gold);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.demo__quote {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 6px 0 0;
  color: var(--sky-ink);
  font-size: clamp(1.02rem, 0.97rem + 0.4vw, 1.3rem);
  font-weight: 600;
  line-height: 1.35;
}

.demo__speaking {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 3px;
  height: 22px;
}

.demo__speaking i {
  width: 4px;
  height: 100%;
  border-radius: 2px;
  background: var(--gold);
  transform: scaleY(0.45);
}

.demo__speaking i:nth-child(2) {
  transform: scaleY(0.85);
}

/* The end card: the slogan over the badge. */
.dawn .demo__end .demo__title {
  max-width: 16ch;
  font-size: clamp(2.1rem, 1.5rem + 2.6vw, 3.6rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
}

.demo__end .store-badge {
  margin-top: 28px;
}

/* ------------------------------------------------------------------ */
/* Shared: the phone, its screen and its lifted cards                  */

.demo__island {
  /* The hardware's Dynamic Island: it covers the Lock Screen captures' own
     exactly, and completes the app's captures, which have none. */
  position: absolute;
  z-index: 4;
  top: 1.46%;
  left: 35.76%;
  width: 28.48%;
  height: 3.84%;
  border-radius: 999px;
  background: #000;
}

.demo__mark {
  /* SAMPLE DATA: on the foot of a card whose numbers are seeded, at its
     trailing end, split by the edge, as in the store's frames. */
  position: absolute;
  z-index: 2;
  top: 100%;
  inset-inline-end: 16px;
  padding: 0.55em 0.9em 0.5em;
  border-radius: 999px;
  background: var(--deep);
  box-shadow: 0 0 0 1.5px rgba(255, 255, 255, 0.32);
  color: var(--sky-ink);
  font-family: var(--font-display);
  font-size: 0.62rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  transform: translateY(-50%);
}

/* ------------------------------------------------------------------ */
/* The list: no JavaScript, or reduced motion                          */

html:not(.demo-scroll) .demo__pin {
  position: relative;
  padding: clamp(28px, 5vw, 56px) 0 calc(var(--hill) + clamp(36px, 6vw, 64px));
}

html:not(.demo-scroll) :is(.demo__night, .demo__bar, .demo__stage, .demo__hint, .demo__skip, .demo__rim) {
  display: none;
}

html:not(.demo-scroll) .demo__steps {
  display: grid;
  gap: clamp(56px, 9vw, 96px);
  margin-top: clamp(24px, 4vw, 40px);
}

html:not(.demo-scroll) .demo__step {
  display: grid;
  gap: 24px;
}

/* Each step's screen, in a phone of its own: the screen at rest, its card
   lifted a little over its place, as the scroll leaves it. */
.demo__still {
  --sw: min(62vw, 232px);
  position: relative;
  justify-self: center;
  width: var(--sw);
  padding: calc(var(--sw) * 0.034);
  border-radius: calc(var(--sw) * 0.155);
  background: linear-gradient(160deg, #3a4066, #12152c 45%, #0b0e22);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.16), 0 34px 64px -30px rgba(4, 6, 20, 0.85), 0 0 90px rgba(255, 115, 61, 0.16);
}

.demo__still-screen {
  position: relative;
  aspect-ratio: 1320 / 2868;
  overflow: hidden;
  isolation: isolate;
  border-radius: calc(var(--sw) * 0.121);
  background: var(--screen-bg);
}

.demo__still-shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
}

.demo__still-dim {
  position: absolute;
  z-index: 2;
  inset: 0;
  background: var(--deep);
  opacity: 0.35;
}

.demo__still-dim--lock {
  opacity: 0.5;
}

.demo__still-hero {
  position: absolute;
  z-index: 3;
  transform: scale(1.06);
  box-shadow: 0 14px 28px -10px rgba(4, 6, 20, 0.55);
}

.demo__still-hero--line {
  transform: scale(1.14);
}

.demo__still-hero--light {
  box-shadow: 0 0 0 1px rgba(23, 28, 56, 0.08), 0 14px 28px -10px rgba(4, 6, 20, 0.5);
}

.demo__still-hero img {
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  border-radius: inherit;
}

.demo__still .demo__mark {
  inset-inline-end: 10px;
  font-size: 0.56rem;
}

@media (min-width: 760px) {
  html:not(.demo-scroll) .demo__step {
    grid-template-columns: minmax(0, 34rem) auto;
    justify-content: start;
    align-items: center;
    column-gap: clamp(32px, 6vw, 96px);
  }

  .demo__still {
    --sw: 240px;
  }
}

/* ------------------------------------------------------------------ */
/* The scroll: the section grows tall and its stage pins to the screen */

html.demo-scroll .demo {
  /* Room to scroll per step: under two thirds of a screen, nearly all of
     it moving something, so a step takes one easy swipe and never drags.
     The small viewport (svh) is Safari's height with its toolbars out:
     nothing here moves as they come and go. */
  --pin-h: 100vh;
  --step-scroll: clamp(360px, 62vh, 560px);
  /* The phone's width; demo.js fits it to the room under the words. */
  --phone-w: clamp(150px, min(54vw, (100vh - 330px) / 2.09), 248px);
  --bezel: calc(var(--phone-w) * 0.034);
  /* The screen keeps the captures' 1320 x 2868. */
  --phone-h: calc(var(--phone-w) * 2.09298);
  /* The hill covers the foot of the phone. */
  --cover: calc(var(--phone-h) * 0.12);
  --hill: calc(var(--cover) + var(--sag) + 10px + var(--rise));
  height: calc(var(--pin-h) + (var(--demo-steps, 6) - 0.75) * var(--step-scroll));
  /* Not a scroll container, or the stage could not stick. */
  overflow: visible;
  /* Under the stage, where Safari's toolbars were: the hill runs on. */
  background: var(--deep);
}

@supports (height: 1svh) {
  html.demo-scroll .demo {
    --pin-h: 100svh;
    --step-scroll: clamp(360px, 62svh, 560px);
    --phone-w: clamp(150px, min(54vw, (100svh - 330px) / 2.09), 248px);
  }
}

html.demo-scroll .demo__pin {
  position: sticky;
  top: 0;
  height: var(--pin-h);
  overflow: hidden;
  isolation: isolate;
  background-color: var(--ground);
  contain: layout paint;
}

html.demo-scroll .demo__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto auto 1fr;
  align-content: start;
  height: 100%;
  padding-top: 14px;
}

/* One step's words at a time: they stand in one place, the tallest step's
   height, so the phone under them never moves. */
html.demo-scroll .demo__steps {
  display: grid;
}

html.demo-scroll .demo__step {
  grid-area: 1 / 1;
  position: static;
  pointer-events: none;
}

html.demo-scroll .demo__step.is-current {
  pointer-events: auto;
}

/* Until demo.js has taken over, the first step only. */
html.demo-scroll .demo:not(.demo--live) .demo__step:not(:first-child) {
  opacity: 0;
}

/* Then the current step's: the words change at one point in the scroll
   (demo.js says which step is current), the old ones gone in 0.12 s before
   the new ones rise in, so that wherever the scroll stops, one step's words
   show whole within a third of a second. Scrolling back changes them back. */
html.demo-scroll .demo--live .demo__step {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.12s ease-in, transform 0s linear 0.12s;
}

html.demo-scroll .demo--live .demo__step.is-current {
  opacity: 1;
  transform: none;
  transition: opacity 0.2s ease-out 0.12s, transform 0.34s cubic-bezier(0.2, 0.7, 0.3, 1) 0.12s;
}

html.demo-scroll .demo__still {
  display: none;
}

/* On a phone or a tablet the end card stands where the phone was, over the
   hill, once it has gone; on a desktop it takes the words' place, beside
   the sun coming up where the phone was. */
@media (max-width: 959px) {
  html.demo-scroll .demo__end {
    position: absolute;
    z-index: 5;
    inset: 0 0 var(--hill);
    display: grid;
    place-content: center;
    justify-items: center;
    padding: 72px 0 16px;
    text-align: center;
  }

  html.demo-scroll .demo__end .demo__title {
    margin-inline: auto;
  }

  /* It covers the stage, the rail's row included: only its badge takes a
     tap, so the rail and "Skip the demo" over it still answer. */
  html.demo-scroll .demo__end.is-current {
    pointer-events: none;
  }

  html.demo-scroll .demo__end.is-current .store-badge {
    pointer-events: auto;
  }
}

html.demo-scroll .demo__stage {
  position: absolute;
  bottom: 0;
  left: 50%;
  width: var(--phone-w);
  height: calc(var(--phone-h) - var(--cover) + var(--hill));
  margin-left: calc(var(--phone-w) / -2);
}

html.demo-scroll .demo__pin > .horizon {
  z-index: 3;
}

/* The words "Scroll to watch", on the hill under the phone: gone once the
   visitor has scrolled into the morning. */
html.demo-scroll .demo__hint {
  position: absolute;
  z-index: 6;
  right: 0;
  bottom: 12px;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  margin: 0;
  color: var(--sky-muted);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  pointer-events: none;
}

.demo__hint svg,
.demo__skip svg {
  flex: none;
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Skip: quiet, at the end of the rail's row, there while the stage stands.
   Its target reaches 44 px high, past the row's 32. */
.demo__skip {
  position: relative;
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 4px;
  min-height: 32px;
  margin-inline-start: auto;
  padding-inline-start: 14px;
  color: var(--sky-muted);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  white-space: nowrap;
}

.demo__skip:hover {
  color: var(--sky-ink);
  text-decoration: underline;
}

.demo__skip::after {
  content: "";
  position: absolute;
  inset: -6px -4px;
}

.demo__after {
  position: absolute;
  bottom: 0;
  scroll-margin-top: 0;
}

.demo__after:focus {
  outline: none;
}

/* ------------------------------------------------------------------ */
/* The stage                                                          */

html.demo-scroll .demo__night {
  /* Pre-dawn: a flat night over the sky that fades as the sun comes up. */
  position: absolute;
  z-index: 0;
  inset: 0;
  background: var(--deep);
  opacity: 0.7;
  pointer-events: none;
}

.demo__glow {
  position: absolute;
  z-index: 1;
  top: calc(var(--phone-h) - var(--cover));
  left: 50%;
  width: calc(var(--phone-w) * 3.4);
  height: calc(var(--phone-w) * 1.6);
  margin-top: calc(var(--phone-w) * -0.8);
  margin-left: calc(var(--phone-w) * -1.7);
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 115, 61, 0.7), rgba(255, 115, 61, 0.26) 48%, rgba(255, 115, 61, 0));
  opacity: 0.35;
  pointer-events: none;
}

/* The sun's light on the phone, stronger as the sun rises. */
.demo__halo {
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
  width: var(--phone-w);
  height: var(--phone-h);
  border-radius: calc(var(--phone-w) * 0.155);
  box-shadow: 0 0 120px rgba(255, 115, 61, 0.3);
  opacity: 0.45;
}

.demo__phone {
  position: absolute;
  z-index: 2;
  top: 0;
  left: 0;
  width: var(--phone-w);
  height: var(--phone-h);
  padding: var(--bezel);
  border-radius: calc(var(--phone-w) * 0.155);
  background: linear-gradient(160deg, #3a4066, #12152c 45%, #0b0e22);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.16), 0 40px 80px -30px rgba(4, 6, 20, 0.85);
}

.demo__screen {
  --screen-bg: #111435;
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  isolation: isolate;
  border-radius: calc(var(--phone-w) * 0.121);
  background: var(--screen-bg);
}

/* The screens stack in the morning's order, each later one over the one
   before, so a change fades the new one in over the old: no dip through
   the screen's colour. */
.demo__shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
}

/* demo.js stacks them (the app's, then the Lock Screen's over them) and
   writes each one's opacity in the same task. */
.demo--live .demo__shot {
  opacity: 0;
}

/* When a card lifts, the rest of the screen dims; the place a card lifted
   away from (on a phone, "I'm up" rises to the middle of the phone) dims
   further, so that the card shows once. */
.demo__dim,
.demo__socket {
  position: absolute;
  z-index: 2;
  background: var(--deep);
  opacity: 0;
  pointer-events: none;
}

.demo__dim {
  inset: 0;
}

.demo__lift {
  position: absolute;
  z-index: 4;
  top: 0;
  left: 0;
  width: var(--phone-w);
  height: var(--phone-h);
  pointer-events: none;
}

.demo__hero {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: 0 0;
  visibility: hidden;
}

/* The lift's shadow, its own layer so that it fades by opacity. */
.demo__hero-shadow {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: 0 24px 48px -12px rgba(4, 6, 20, 0.55);
  opacity: 0;
}

.demo__hero--light {
  box-shadow: 0 0 0 1px rgba(23, 28, 56, 0.08);
}

.demo__hero img {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  max-width: none;
  border-radius: inherit;
}

/* The tap at Stop and "I'm up": a touch like an iOS screen recording's, and
   the button's area flashing as it is pressed. */
.demo__ghost {
  position: absolute;
  z-index: 3;
  width: 46px;
  height: 46px;
  margin: -23px 0 0 -23px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.42);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.55), 0 4px 14px rgba(4, 6, 20, 0.35);
  opacity: 0;
  pointer-events: none;
}

.demo__flash {
  position: absolute;
  z-index: 1;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.24);
  opacity: 0;
  pointer-events: none;
}

/* Step 1's ringing: three gold arcs each side of the phone's top third. */
.demo__arcs {
  position: absolute;
  z-index: 1;
  top: calc(var(--phone-h) * 0.12);
  left: 50%;
  width: calc(var(--phone-w) + 120px);
  height: calc(var(--phone-h) * 0.22);
  transform: translateX(-50%);
  pointer-events: none;
}

.demo__arcs i {
  position: absolute;
  top: 50%;
  width: var(--arc);
  height: var(--arc);
  margin-top: calc(var(--arc) / -2);
  border: 3px solid transparent;
  border-radius: 50%;
  opacity: 0;
}

.demo__arcs i:nth-child(-n + 3) {
  left: calc(48px - var(--arc) / 2);
  border-left-color: var(--gold);
}

.demo__arcs i:nth-child(n + 4) {
  right: calc(48px - var(--arc) / 2);
  border-right-color: var(--gold);
}

.demo__arcs i:nth-child(3n + 1) { --arc: 30px; }
.demo__arcs i:nth-child(3n + 2) { --arc: 54px; }
.demo__arcs i:nth-child(3n + 3) { --arc: 78px; }

/* The gold horizon grows to full strength as the sun comes up. */
.demo__rim {
  position: absolute;
  top: 0;
  left: 50%;
  width: 320%;
  height: calc(var(--sag) * 40);
  border-radius: 50%;
  box-shadow: 0 -6px clamp(28px, 4vw, 56px) clamp(6px, 1vw, 14px) rgba(255, 199, 107, 0.5);
  opacity: 0;
  transform: translateX(-50%);
}

/* What moves, on its own layer while the stage is on screen. */
.demo--active :is(.demo__night, .demo__halo, .demo__rim, .demo__dim, .demo__socket, .demo__flash, .demo__hero-shadow, .demo__hint) {
  will-change: opacity;
}

.demo--active :is(.demo__glow, .demo__shot, .demo__step, .demo__ghost) {
  will-change: transform, opacity;
}

.demo--active :is(.demo__hero, .demo__phone, .demo__lift, .demo__fill, .demo__end .demo__words) {
  will-change: transform;
}

/* ------------------------------------------------------------------ */
/* The rail: where the morning is, and a way to jump in it             */

/* Over the end card, which covers the stage on a phone or a tablet. Where
   "Skip the demo" is long (Portuguese, German, Dutch on a narrow phone), it
   goes under the rail rather than squeeze its bars under 24 px. */
html.demo-scroll .demo__bar {
  position: relative;
  z-index: 6;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  row-gap: 2px;
  min-height: 32px;
  max-width: 34rem;
  margin: 8px 0 12px;
}

.demo__rail {
  display: flex;
  flex: 1;
  gap: 6px;
  /* Each bar at least 24 px wide, with 6 px between. */
  min-width: calc(var(--demo-steps, 6) * 30px - 6px);
}

/* "Skip the demo" comes first for the keyboard, and stands at the row's end. */
html.demo-scroll .demo__skip {
  order: 2;
}

/* Each step's bar is a 4 px line in a button 32 px high, whose target
   reaches 44 px, the site's smallest, past the row. */
.demo__tab {
  position: relative;
  flex: 1;
  min-width: 0;
  height: 32px;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.demo__tab::after {
  content: "";
  position: absolute;
  inset: -6px 0;
}

.demo__tab::before,
.demo__fill {
  content: "";
  position: absolute;
  top: 14px;
  right: 0;
  left: 0;
  height: 4px;
  border-radius: 2px;
}

/* A step to come: 3.5:1 or more against the sky, the night's included. */
.demo__tab::before {
  background: rgba(255, 255, 255, 0.4);
}

/* The current step: a gold track (3:1 or more) under its gold fill. */
.demo__tab.is-current::before {
  background: rgba(255, 199, 107, 0.55);
}

.demo__fill {
  background: rgba(255, 255, 255, 0.85);
  transform: scaleX(0);
  transform-origin: left center;
}

/* Right to left, the rail fills from the right. */
[dir="rtl"] .demo__fill {
  transform-origin: right center;
}

.demo__tab.is-current .demo__fill {
  background: var(--gold);
}

.demo__tab:focus-visible {
  outline-offset: 0;
}

/* Windows' high contrast: the bars in the theme's own colours, which would
   otherwise paint them as the page's background. */
@media (forced-colors: active) {
  .demo__tab::before,
  .demo__fill {
    forced-color-adjust: none;
  }

  .demo__tab::before,
  .demo__tab.is-current::before {
    background: GrayText;
  }

  .demo__fill {
    background: CanvasText;
  }

  .demo__tab.is-current .demo__fill {
    background: Highlight;
  }
}

/* ------------------------------------------------------------------ */
/* A phone: the words a little closer, so that the phone has more room */

@media (max-width: 639px) {
  html.demo-scroll .demo__body {
    padding-top: 10px;
  }

  html.demo-scroll .demo__bar {
    margin: 6px 0 8px;
  }

  .demo__cues {
    margin-bottom: 8px;
  }

  .demo__sub {
    margin-top: 6px;
  }

  .demo__note {
    margin-top: 8px;
  }
}

/* A short screen (an iPhone SE in Safari with its toolbars out): smaller
   words, so that the phone under them keeps its room. demo.js says when. */
html.demo-scroll .demo--short .demo__body {
  padding-top: 6px;
}

html.demo-scroll .demo--short .demo__step:not(.demo__end) .demo__title {
  font-size: 1.35rem;
}

html.demo-scroll .demo--short :is(.demo__sub, .demo__quote) {
  font-size: 0.95rem;
}

html.demo-scroll .demo--short .demo__cues {
  margin-bottom: 6px;
}

html.demo-scroll .demo--short .demo__note {
  margin-top: 6px;
}

/* ------------------------------------------------------------------ */
/* Tablet: one column, centred                                        */

@media (min-width: 640px) {
  html.demo-scroll .demo {
    --phone-w: clamp(180px, (100vh - 380px) / 2.09, 280px);
  }

  html.demo-scroll .demo__body {
    justify-items: center;
    text-align: center;
  }

  html.demo-scroll :is(.demo__head, .demo__bar, .demo__steps) {
    width: min(100%, 36rem);
  }

  html.demo-scroll :is(.demo__title, .demo__sub) {
    margin-inline: auto;
  }

  html.demo-scroll :is(.demo__cues, .demo__quote) {
    justify-content: center;
  }
}

@supports (height: 1svh) {
  @media (min-width: 640px) {
    html.demo-scroll .demo {
      --phone-w: clamp(180px, (100svh - 380px) / 2.09, 280px);
    }
  }
}

/* ------------------------------------------------------------------ */
/* Desktop: the words on the left, the phone in a 440 px column        */

@media (min-width: 960px) {
  html.demo-scroll .demo {
    --phone-w: clamp(220px, min(24vw, (100vh - 250px) / 2.09), 300px);
  }

  html.demo-scroll .demo__body {
    grid-template-columns: minmax(0, 1fr) 440px;
    grid-template-rows: auto auto 1fr;
    column-gap: clamp(40px, 6vw, 96px);
    justify-items: start;
    padding-top: clamp(28px, 7vh, 72px);
    padding-bottom: var(--hill);
    text-align: start;
  }

  html.demo-scroll .demo__head {
    grid-column: 1;
    width: 100%;
    max-width: 34rem;
  }

  html.demo-scroll .demo__bar {
    grid-column: 1;
    width: 100%;
    max-width: 30rem;
    margin: 18px 0 0;
  }

  html.demo-scroll .demo__steps {
    grid-column: 1;
    align-self: center;
    width: 100%;
    max-width: 34rem;
  }

  html.demo-scroll :is(.demo__title, .demo__sub) {
    margin-inline: 0;
  }

  html.demo-scroll :is(.demo__cues, .demo__quote) {
    justify-content: flex-start;
  }

  .dawn .demo__end .demo__title {
    font-size: clamp(2.2rem, 1.4rem + 1.6vw, 3rem);
  }

  .demo__end .store-badge {
    margin-top: 22px;
  }

  /* The phone in the middle of its column, at the foot of the stage. */
  html.demo-scroll .demo__stage {
    left: auto;
    margin-left: 0;
    inset-inline-end: calc(220px - var(--phone-w) / 2);
  }
}

@supports (height: 1svh) {
  @media (min-width: 960px) {
    html.demo-scroll .demo {
      --phone-w: clamp(220px, min(24vw, (100svh - 250px) / 2.09), 300px);
    }
  }
}

/* ------------------------------------------------------------------ */
/* Ambient motion: only where motion is allowed, and only on the step  */
/* that shows. Nothing waits on it.                                    */

@media (prefers-reduced-motion: no-preference) {
  .demo--ringing .demo__arcs i {
    animation: demo-arc 1.2s ease-out infinite;
  }

  .demo--ringing .demo__arcs i:nth-child(3n + 2) { animation-delay: 0.15s; }
  .demo--ringing .demo__arcs i:nth-child(3n + 3) { animation-delay: 0.3s; }

  .demo--speaking .demo__step[data-step="s2"] .demo__speaking i {
    animation: demo-speak 0.9s ease-in-out infinite alternate;
  }

  .demo--speaking .demo__step[data-step="s2"] .demo__speaking i:nth-child(2) { animation-delay: -0.3s; }
  .demo--speaking .demo__step[data-step="s2"] .demo__speaking i:nth-child(3) { animation-delay: -0.6s; }
}

@keyframes demo-arc {
  0% { opacity: 0; transform: scale(0.85); }
  35% { opacity: 0.95; }
  100% { opacity: 0; transform: scale(1.12); }
}

@keyframes demo-speak {
  from { transform: scaleY(0.3); }
  to { transform: scaleY(1); }
}

/* ------------------------------------------------------------------ */
/* Right to left: the layout mirrors through logical properties; the  */
/* phone, its screens and the glow stay as they are (hardware).       */

[dir="rtl"] .demo__note-label {
  letter-spacing: 0;
}

/* Japanese: no small kana or long-vowel mark starts a line, and where the
   browser can (Chrome), a line breaks between phrases, not inside one. The
   catalog's <br> sets the break where a line must wrap on a phone. */
.demo:lang(ja) {
  line-break: strict;
  word-break: auto-phrase;
}

/* A <br class="soft"> is a phrase break that only a narrow line needs: a
   sub-line or the quote of at most 22 full-width characters, which fits on
   one line on a tablet and on a desktop from 1100 px (480 px of words at up
   to 20 px). There the line runs on; on a phone, and in a desktop's narrower
   column below 1100 px, it breaks at the phrase. */
@media (min-width: 640px) and (max-width: 959px), (min-width: 1100px) {
  .demo br.soft {
    display: none;
  }
}
