/* The sandbox's texting page: a messages screen beside the demo site's devices on a computer, a sheet under them on a phone. */

/* The brand's fonts, served from this page's own folder, Latin letters only. */
@font-face {
  font-family: "Bricolage Grotesque";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/_stenzil/chat/fonts/bricolage-grotesque-1.001-700-latin.woff2") format("woff2");
  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: "Public Sans";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/_stenzil/chat/fonts/public-sans-2.001-400-latin.woff2") format("woff2");
  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: "Public Sans";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/_stenzil/chat/fonts/public-sans-2.001-600-latin.woff2") format("woff2");
  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: "Public Sans";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/_stenzil/chat/fonts/public-sans-2.001-700-latin.woff2") format("woff2");
  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;
}

/* Kept for a tiny eyebrow; no label on the page uses it, so a browser never fetches it. */
@font-face {
  font-family: "Spline Sans Mono";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("/_stenzil/chat/fonts/spline-sans-mono-1.004-500-latin.woff2") format("woff2");
  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;
}

/* stenzil.tech's colours; buttons rest on its hover teal, since white on its #1088a9 is only 4.1:1. */
:root {
  --ink: #1c1826;
  --muted: #6e6788;
  --muted-on-wash: #5f587a;
  --line: #e5e2f0;
  --card: #ffffff;
  --page: #faf9f6;
  --violet: #5b47d9;
  --violet-wash: #efedf8;
  --chrome: #f4f2fa;
  --teal: #0e7a98;
  --teal-deep: #0c6c87;
  --done: #188a54;
  --ring: #f59e0b;
  /* The placeholders' greys, from stenzil.tech's lavender line and wash. */
  --bone: #ebe8f3;
  --bone-light: #f7f6fb;
  --radius: 1rem;
  /* The quiet white panels' corners: the handoff card and each change's steps. */
  --panel-radius: 24px;
  --display: "Bricolage Grotesque", system-ui, sans-serif;
  --body: "Public Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --shadow: 0 24px 48px -12px rgb(28 24 38 / 0.18), 0 8px 16px -8px rgb(28 24 38 / 0.1);
  /* Stenzil's mark, white on violet, as the ad's avatar draws it. */
  --mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 168 168'%3E%3Crect width='168' height='168' fill='%235B47D9'/%3E%3Cpath fill-rule='evenodd' d='M25.1367 25.7506C25.1367 23.7188 26.7838 22.0718 28.8156 22.0718H138.567C140.599 22.0718 142.246 23.7188 142.246 25.7506V46.5973C142.246 48.6291 140.599 50.2762 138.567 50.2762H28.8156C26.7838 50.2762 25.1367 48.6291 25.1367 46.5973V25.7506ZM32.4944 29.4294V42.9185H134.889V29.4294H32.4944Z' fill='white'/%3E%3Cpath fill-rule='evenodd' d='M94.8474 118.838C95.5402 118.124 96.4925 117.721 97.4872 117.721H138.567C140.599 117.721 142.246 119.369 142.246 121.4V142.247C142.246 144.279 140.599 145.926 138.567 145.926H77.2536C75.7757 145.926 74.4412 145.041 73.8654 143.68C73.2897 142.319 73.5844 140.745 74.6138 139.685L94.8474 118.838ZM99.0433 125.079L85.951 138.568H134.889V125.079H99.0433Z' fill='white'/%3E%3Cpath fill-rule='evenodd' d='M107.284 58.2468C107.975 57.5517 108.915 57.1613 109.895 57.1621L138.737 57.1866C140.224 57.1879 141.563 58.0833 142.132 59.4561C142.702 60.829 142.389 62.4095 141.34 63.4623L60.2402 144.844C59.5499 145.537 58.6123 145.926 57.6344 145.926H28.9333C27.4472 145.926 26.1071 145.032 25.5365 143.66C24.9659 142.288 25.2769 140.707 26.3248 139.653L107.284 58.2468ZM111.421 64.5211L37.7803 138.569H56.1068L129.882 64.5368L111.421 64.5211Z' fill='white'/%3E%3C/svg%3E");
  color-scheme: light;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font: 16px/1.5 var(--body);
  overflow-x: clip;
  -webkit-font-smoothing: antialiased;
}

[hidden] {
  display: none !important;
}

.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

button,
textarea,
a.button {
  font: inherit;
}

:focus-visible {
  outline: 3px solid var(--violet);
  outline-offset: 2px;
}

/* The top bar: Stenzil's mark and name, and the demo business. */
.top {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  max-width: 1280px;
  margin: 0 auto;
}

.top p {
  margin: 0;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--ink);
  text-decoration: none;
  border-radius: 8px;
  font-family: var(--display);
  font-weight: 700;
  font-size: 20px;
  line-height: 1.2;
}

.logo,
.avatar,
.bubble.reply::before,
.bubble.intro::before {
  flex: none;
  background: var(--mark) center / cover no-repeat;
}

.logo {
  width: 28px;
  height: 28px;
  border-radius: 8px;
}

.name {
  min-width: 0;
  padding-left: 12px;
  border-left: 1px solid var(--line);
  color: var(--muted);
  font-size: 15px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.name:empty {
  display: none;
}

/* The headline row. */
.hero {
  text-align: center;
  margin: 4px auto 20px;
  max-width: 760px;
}

.hero h1 {
  margin: 0;
  font-family: var(--display);
  font-weight: 700;
  font-size: 26px;
  line-height: 1.12;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

.hero p {
  margin: 8px auto 0;
  max-width: 60ch;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.45;
  text-wrap: pretty;
}

.demo {
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 16px 16px;
}

/* Back to all demos: a quiet text link, left under the headline on a phone, its own line above the devices. */
.all {
  display: block;
  width: fit-content;
  margin: 0 0 12px;
  padding: 2px 0;
  border-radius: 4px;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.4;
  text-decoration: none;
}

@media (hover: hover) {
  .all:hover {
    text-decoration: underline;
  }
}

.devices {
  display: grid;
  gap: 16px;
  min-width: 0;
}

/* The devices: the computer in a browser window, the phone over its lower right corner. */
.previews {
  position: relative;
  padding-bottom: 40px;
  scroll-margin-top: 8px;
}

.preview {
  margin: 0;
  min-width: 0;
  --s: 0.3;
}

/* Each device is its own layer, so the phone, drawn over the computer, takes its own taps. */
.preview[data-kind="computer"] {
  position: relative;
  z-index: 1;
  width: 88%;
  --bar: 18px;
}

.preview[data-kind="phone"] {
  position: absolute;
  right: 0;
  bottom: 0;
  z-index: 2;
  width: 32%;
  --rim: 4px;
}

.stage {
  position: relative;
}

.screen {
  position: relative;
  overflow: hidden;
  width: 100%;
  background: var(--card);
}

.preview[data-kind="computer"] .screen {
  aspect-ratio: 1920 / 1080;
  border: 1px solid var(--line);
  border-top: 0;
  border-radius: 0 0 10px 10px;
  box-shadow: var(--shadow);
}

/* The browser window's bar: three dots and the address, blank until the business is known. */
.chrome {
  display: flex;
  align-items: center;
  gap: 4px;
  height: var(--bar);
  padding: 0 8px;
  background: var(--card);
  border: 1px solid var(--line);
  border-bottom-color: var(--chrome);
  border-radius: 10px 10px 0 0;
}

.chrome i {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--line);
}

.chrome .address {
  flex: 0 1 46%;
  height: 8px;
  margin: 0 auto;
  border-radius: 999px;
  background: var(--chrome);
}

/* Once the business is known: a lock, its made-up address in muted ink at 4.5:1, and the ad's yellow Preview chip. */
.chrome .address.named {
  flex: 0 1 auto;
  min-width: 0;
  height: 15px;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 3px 0 7px;
  color: var(--muted);
  font: 400 10px/1 var(--body);
}

.chrome .address:not(.named) > * {
  display: none;
}

.chrome .lock {
  flex: none;
  width: 0.75em;
  height: 0.875em;
}

.chrome .host {
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
}

.chrome .chip {
  flex: none;
  padding: 0.15em 0.6em;
  border-radius: 999px;
  background: #fff1c9;
  color: #7a5a00;
  font-weight: 600;
  font-size: 0.9em;
}

/* The phone: a dark outline with rounded corners; it shows the top of the page. */
.preview[data-kind="phone"] .screen {
  aspect-ratio: 390 / 740;
  border: var(--rim) solid var(--ink);
  border-radius: 20px;
  box-shadow: var(--shadow);
}

/*
 * A drawn phone's bar: the time, a camera dot, signal, wifi and battery, in no maker's look.
 * Sizes are the ad's bar on its 430px-wide phone, scaled by the drawn phone's screen width over 430.
 */
.preview[data-kind="phone"] .screen {
  container-type: inline-size;
}

.status {
  --u: calc(100cqw / 430);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: calc(50 * var(--u));
  padding: calc(6 * var(--u)) calc(34 * var(--u)) 0 calc(38 * var(--u));
  background: var(--card);
  color: var(--ink);
  font-size: calc(18 * var(--u));
  font-weight: 600;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.preview[data-kind="phone"] .status {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 2;
}

.status .cam {
  position: absolute;
  left: 50%;
  top: calc(16 * var(--u));
  width: calc(18 * var(--u));
  height: calc(18 * var(--u));
  margin-left: calc(-9 * var(--u));
  border-radius: 50%;
  background: var(--ink);
}

.status .icons {
  display: flex;
  align-items: center;
  gap: calc(7 * var(--u));
}

.status .sig {
  display: flex;
  align-items: flex-end;
  gap: calc(2 * var(--u));
  height: calc(13 * var(--u));
}

.status .sig i {
  display: block;
  width: calc(4 * var(--u));
  border-radius: calc(1 * var(--u));
  background: currentColor;
}

.status .sig i:nth-child(1) {
  height: calc(4 * var(--u));
}

.status .sig i:nth-child(2) {
  height: calc(7 * var(--u));
}

.status .sig i:nth-child(3) {
  height: calc(10 * var(--u));
}

.status .sig i:nth-child(4) {
  height: calc(13 * var(--u));
}

.status .wifi {
  width: calc(19 * var(--u));
  height: calc(14 * var(--u));
}

.status .batt {
  position: relative;
  box-sizing: content-box;
  width: calc(27 * var(--u));
  height: calc(13 * var(--u));
  margin-left: calc(2 * var(--u));
  padding: calc(1.5 * var(--u));
  border: calc(2 * var(--u)) solid currentColor;
  border-radius: calc(4 * var(--u));
}

.status .batt::after {
  content: "";
  position: absolute;
  right: calc(-5 * var(--u));
  top: calc(3 * var(--u));
  width: calc(2.5 * var(--u));
  height: calc(5 * var(--u));
  border-radius: 0 calc(2 * var(--u)) calc(2 * var(--u)) 0;
  background: currentColor;
}

.status .batt i {
  display: block;
  width: 72%;
  height: 100%;
  border-radius: calc(1.5 * var(--u));
  background: currentColor;
}

/* The texting area is a phone only on a computer; on a phone it is a sheet with no bar. */
.chat .status {
  display: none;
}

/* The phone's page starts under its bar, and so do the rings drawn over it. */
.preview[data-kind="phone"] .screen iframe,
.preview[data-kind="phone"] .ring {
  margin-top: calc(100cqw * 50 / 430);
}

.screen iframe {
  position: absolute;
  top: 0;
  left: 0;
  border: 0;
  transform: scale(var(--s));
  transform-origin: 0 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 250ms ease;
}

.screen iframe.on {
  opacity: 1;
  z-index: 1;
  pointer-events: auto;
}

.setting-up .screen::after {
  content: "Setting up…";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--muted);
  font-size: 13px;
}

.enlarge {
  position: absolute;
  inset: 0;
  z-index: 2;
  width: 100%;
  border: 0;
  background: transparent;
  cursor: zoom-in;
  border-radius: 10px;
}

.preview[data-kind="phone"] .enlarge {
  border-radius: 20px;
}

.shut {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 3;
  border: 0;
  border-radius: 999px;
  padding: 8px 16px;
  background: var(--card);
  color: var(--ink);
  font-weight: 700;
  cursor: pointer;
}

/* Up close is CSS alone: the frame never moves in the page, so it never reloads. */
.preview.up {
  z-index: 50;
}

.preview.up .stage {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: grid;
  place-items: center;
  background: rgb(28 24 38 / 0.94);
  padding: 64px 16px 16px;
}

.preview.up .chrome {
  display: none;
}

/* Up close the whole phone page shows under its bar, which is 50/430 of the screen's width tall. */
.preview.up[data-kind="phone"] .screen {
  aspect-ratio: 390 / calc(844 + 390 * 50 / 430);
  width: min(100%, calc((100dvh - 80px) * 390 / (844 + 390 * 50 / 430)));
}

.preview.up[data-kind="computer"] .screen {
  width: min(100%, calc((100dvh - 80px) * 1920 / 1080));
  border-radius: 10px;
}

/*
 * Each device's not-shown note sits in its own screen's top left corner, just under its bar, over the demo banner
 * every copy opens with, so never over the site's headline. It is placed from the bar's own size.
 */
.preview figcaption {
  position: absolute;
  z-index: 5;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  pointer-events: none;
  font-size: 12px;
  line-height: 1.3;
  white-space: nowrap;
}

.preview[data-kind="computer"] figcaption {
  top: calc(var(--bar) + 6px);
  left: 6px;
}

/* The phone's bar is 50/430 of the screen inside its rim; a padding's percentage is of the phone's width. */
.preview[data-kind="phone"] figcaption {
  top: var(--rim);
  left: calc(var(--rim) + 6px);
  padding-top: calc((100% - 2 * var(--rim)) * 50 / 430 + 6px);
}

.note {
  border-radius: 999px;
  padding: 2px 9px;
  box-shadow: 0 2px 6px rgb(28 24 38 / 0.12);
  background: var(--card);
  color: var(--muted);
  font-style: italic;
}

.ring {
  position: absolute;
  z-index: 4;
  border: 3px solid var(--ring);
  border-radius: 8px;
  pointer-events: none;
  animation: ring 1.8s ease-out forwards;
}

/* One ring for both screens: in over 150ms, a breathing hold, then out over 1s to a faint marker that stays. */
@keyframes ring {
  0% {
    opacity: 0;
  }
  8% {
    opacity: 1;
  }
  26% {
    opacity: 0.8;
  }
  44% {
    opacity: 1;
  }
  100% {
    opacity: 0.35;
  }
}

/* After a reveal: up close, Before and After, and the way through several changed parts, as one centred row. */
.done {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
  align-items: center;
}

.done button {
  border: 1px solid var(--line);
  background: var(--card);
  color: var(--ink);
  border-radius: 999px;
  padding: 8px 18px;
  cursor: pointer;
  min-height: 44px;
  font-weight: 600;
}

/* On a phone, with Watch it again in the row, the three are a size smaller and keep to one line, so none drops below
   the fold (coordinator, Oct. 24th). */
@media (max-width: 1023px) {
  .done:has(> #watch-again:not([hidden])) {
    flex-wrap: nowrap;
    gap: 6px;
  }

  .done:has(> #watch-again:not([hidden])) button {
    padding: 8px 10px;
    font-size: 13px;
    white-space: nowrap;
  }

  .done:has(> #watch-again:not([hidden])) #close-up {
    padding: 10px 12px;
  }
}

/* Below 380px the three are wider than the screen: See it up close takes its own line and Watch it again stays beside
   Before/After on the line under it, so none runs off the screen, and See it up close keeps its place as Before/After
   come and go (run-through on test, Oct. 24th). */
@media (max-width: 379px) {
  .done:has(> #watch-again:not([hidden])) {
    flex-wrap: wrap;
  }

  .done:has(> #watch-again:not([hidden]))::before {
    content: "";
    flex-basis: 100%;
    height: 0;
  }

  .done:has(> #watch-again:not([hidden])) #close-up {
    order: -1;
  }
}

/* No clip here, so a focused button's ring shows whole; each end rounds itself. */
.switch {
  display: inline-flex;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--card);
}

.switch button {
  border: 0;
  border-radius: 0;
}

.switch button:first-child {
  border-radius: 999px 0 0 999px;
}

.switch button:last-child {
  border-radius: 0 999px 999px 0;
}

.switch button:focus-visible {
  position: relative;
  z-index: 1;
}

.switch button[aria-pressed="true"] {
  background: var(--ink);
  color: #fff;
}

/* The primary buttons: texting us, starting their own and seeing the change up close. */
a.button,
#message-link,
.done #close-up {
  display: inline-block;
  border: 0;
  background: var(--teal);
  color: #fff;
  text-decoration: none;
  font-weight: 700;
  border-radius: 999px;
  padding: 12px 24px;
  box-shadow:
    0 10px 15px -3px rgb(16 136 169 / 0.2),
    0 4px 6px -4px rgb(16 136 169 / 0.2);
  cursor: pointer;
}

/* Hover only where a pointer hovers, so a tap on a phone leaves no shade behind. */
@media (hover: hover) {
  a.button:hover,
  #message-link:hover,
  .done #close-up:hover {
    background: var(--teal-deep);
  }

  .pill:hover {
    background: #e4e0f6;
  }
}

/* The ask to get their own site: its own white card between the demo and the questions, as on stenzil.tech. */
.handoff {
  max-width: 728px;
  margin: 32px auto 0;
  padding: 24px 20px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--panel-radius);
  text-align: center;
}

.handoff p {
  margin: 0 auto 16px;
  max-width: 48ch;
  font-family: var(--display);
  font-weight: 700;
  font-size: 22px;
  line-height: 1.25;
  text-wrap: balance;
}

.small {
  font-size: 13px;
  color: var(--muted);
}

.handoff .small {
  margin: 14px auto 0;
  font-family: var(--body);
  font-weight: 400;
  font-size: 13px;
  line-height: 1.45;
  text-wrap: pretty;
}

/* stenzil.tech's consent line under its text-us button: small, quiet, still better than 4.5:1 on the white card. */
.handoff .consent {
  margin: 12px auto 0;
  max-width: 46ch;
  font-family: var(--body);
  font-weight: 400;
  font-size: 11px;
  line-height: 1.6;
  color: var(--muted);
  text-wrap: pretty;
}

/* stenzil.tech's footer: a hairline, then centred quiet lines and its links in ink, underlined. */
.footer {
  margin: 48px 0 0;
  padding: 32px 16px;
  border-top: 1px solid var(--line);
  text-align: center;
  font-size: 14px;
  line-height: 1.5;
  color: var(--muted);
}

.footer p {
  margin: 0 auto 8px;
  max-width: 64ch;
}

.footer a {
  color: var(--ink);
  text-decoration: underline;
}

.footer .links {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 24px;
}

/* The way to another demo once this one is used up or over. */
.again {
  align-self: center;
  color: var(--violet);
  font-weight: 700;
  font-size: 15px;
  text-decoration: underline;
  text-underline-offset: 3px;
  padding: 4px 8px;
  border-radius: 8px;
}

/* A phone keeps the card off the screen's edges. */
@media (max-width: 759px) {
  .handoff {
    margin: 32px 16px 0;
  }

  .handoff p {
    font-size: 20px;
  }
}

/* The example change, named above the devices so it is never read as a message the visitor sent. Only that line: the
   example's message in the texting phone has the class too. :where keeps the old weight, so later rules still win. */
.example:where(#example) {
  margin: 0;
  padding: 10px 16px;
  background: var(--violet-wash);
  color: var(--ink);
  border-radius: var(--radius);
  font-size: 15px;
  line-height: 1.4;
  /* The clock keeps its own room at the end of the first line, so it never wraps alone behind its dot. */
  display: flex;
  align-items: baseline;
  gap: 0.3em;
}

.example:where(#example) .what {
  min-width: 0;
  text-wrap: pretty;
}

.example:where(#example) .label {
  color: var(--violet);
  font-weight: 600;
}

.example:where(#example) .words {
  font-weight: 600;
}

.example:where(#example) .clock {
  flex: none;
  color: var(--muted-on-wash);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.example:where(#example) .clock::before {
  content: "· ";
}

/* The wait card under the steps on a phone; right of them, heights matched, on a computer. */
.record {
  display: grid;
  gap: 12px;
}

/* The one card of steps under See it up close: the latest change's, turning while it is made, then kept ticked. */
.record .card,
.record .change {
  padding: 12px 20px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--panel-radius);
}

/* One step a line, top to bottom, close enough that a phone shows the whole card above the texting sheet. */
.record .steps {
  margin: 0;
  display: grid;
  gap: 4px;
}

/* The earlier ticked steps folded into one line on a short screen, drawn as a ticked step and spaced as one. */
.record .fold {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 4px;
  font-size: 13px;
  color: var(--ink);
}

.record .fold .mark {
  border-color: var(--done);
  background: var(--done);
}

.record .fold .mark::after {
  content: "";
  position: absolute;
  left: 4.5px;
  top: 1.5px;
  width: 4px;
  height: 8px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.record .which {
  margin: 0 0 4px;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
}

/* The card's name, and on a phone the example's running clock at the end of the same line. */
.record .topline {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.record .topline .clock {
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* A computer shows the example's clock on the step line, so the card's own stays down. */
@media (min-width: 1024px) {
  .record.of-example .topline .clock {
    display: none;
  }
}

/* Grey placeholders while the copy is set up: calm shimmering blocks, never shown once the real parts are in. */
.skeleton {
  display: none;
}

.bone,
.loading .screen,
.loading .hero h1:empty,
.loading #close-up {
  background: linear-gradient(100deg, var(--bone) 40%, var(--bone-light) 50%, var(--bone) 60%) 0 0 / 300% 100%;
  animation: shimmer 1.8s ease-in-out infinite;
}

@keyframes shimmer {
  from {
    background-position: 100% 0;
  }
  to {
    background-position: 0 0;
  }
}

.bone {
  display: block;
  border-radius: 999px;
}

.loading .skeleton {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.skeleton .said {
  width: 72%;
  height: 40px;
  border-radius: 20px 20px 20px 6px;
}

.skeleton .said.short {
  width: 48%;
}

.skeleton .bones {
  display: flex;
  gap: 8px;
}

.skeleton .chip {
  width: 46%;
  height: 44px;
  border-radius: 18px;
}

.skeleton .box {
  align-items: center;
  padding: 4px 4px 4px 14px;
  border: 1px solid var(--line);
  border-radius: 22px;
}

.skeleton .line {
  flex: 1;
  height: 14px;
}

.skeleton .send {
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: 50%;
}

/* While the copy is set up only the placeholders show in the texting area. */
.loading .thread,
.loading .dock > :not(.skeleton) {
  display: none !important;
}

.loading .hero h1:empty {
  width: min(80%, 18ch);
  height: 1.12em;
  margin: 0 auto;
  border-radius: 10px;
}

.loading #close-up {
  color: transparent;
  box-shadow: none;
}

/* The texting area. */
.chat {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: var(--card);
}

/* The messages header: back, Stenzil's avatar and name, and the changes left. */
.head {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
}

.head p {
  margin: 0;
}

.avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
}

.who {
  font-weight: 600;
  font-size: 15px;
}

.left {
  margin-left: auto !important;
  max-width: 62%;
  text-align: right;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.3;
}

.thread {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
  overflow-y: auto;
  overscroll-behavior: contain;
}

.bubble {
  max-width: 80%;
  animation: pop 150ms ease-out both;
}

@keyframes pop {
  from {
    opacity: 0;
    transform: translateY(6px) scale(0.97);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

.bubble p {
  margin: 0;
  padding: 9px 14px;
  border-radius: 20px;
  font-size: 15px;
  line-height: 1.38;
  overflow-wrap: anywhere;
}

.bubble.sent,
.bubble.queued {
  align-self: flex-end;
  text-align: right;
}

.bubble.sent p,
.bubble.queued p {
  border-bottom-right-radius: 6px;
  text-align: left;
}

.bubble.sent p {
  background: var(--violet);
  color: #fff;
}

.bubble.queued p {
  background: var(--card);
  color: var(--ink);
  border: 1px dashed var(--violet);
}

/* The example's pill, over the box while its words type and on its message once it is sent: orange, dark words at
   better than 4.5:1. */
.example-tag,
.bubble .tag {
  display: inline-block;
  margin: 0 0 4px;
  padding: 2px 9px;
  border-radius: 999px;
  background: #ffe8c2;
  color: #7a3e00;
  font-size: 12px;
  font-weight: 700;
  line-height: 1.3;
}

.compose .example-tag {
  margin: 0 0 6px 4px;
}

/* A message that did not go: drawn as an outline, so its words keep their contrast. */
.bubble.unsent p {
  background: var(--card);
  color: var(--muted);
  border: 1px dashed var(--muted);
}

/* Stenzil's messages: lavender, on the left, with its avatar at their foot. */
.bubble.reply,
.bubble.intro {
  position: relative;
  align-self: flex-start;
  padding-left: 32px;
  max-width: 88%;
}

.bubble.reply::before,
.bubble.intro::before {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 24px;
  height: 24px;
  border-radius: 50%;
}

.bubble.reply p,
.bubble.intro p {
  background: var(--violet-wash);
  color: var(--ink);
  border-bottom-left-radius: 6px;
}

/* Delivered and Read sit under the last message sent, as on a phone; a message not sent keeps its line. */
.receipt {
  display: block;
  margin-top: 3px;
  padding-right: 4px;
  font-size: 12px;
  color: var(--muted);
}

.bubble.sent:not(.unsent):has(~ .bubble.sent) .receipt {
  display: none;
}

.dock {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* The change being made: a typing bubble that says so, with the steps under it. */
.progress {
  align-self: flex-start;
  max-width: 100%;
  background: var(--violet-wash);
  border-radius: 20px 20px 20px 6px;
  padding: 10px 14px 12px;
}

.clock {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  align-items: center;
  margin: 0;
  font-weight: 600;
  font-size: 15px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.dots {
  display: inline-flex;
  gap: 4px;
}

.dots i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--muted-on-wash);
  animation: blink 1.2s ease-in-out infinite;
}

.dots i:nth-child(2) {
  animation-delay: 0.2s;
}

.dots i:nth-child(3) {
  animation-delay: 0.4s;
}

@keyframes blink {
  0%,
  60%,
  100% {
    opacity: 0.35;
    transform: translateY(0);
  }
  30% {
    opacity: 1;
    transform: translateY(-2px);
  }
}

/* A shown change being revealed: the dots stop until the reply comes. */
.progress.stopped .dots {
  display: none;
}

.slow {
  color: var(--muted-on-wash);
  font-weight: 400;
  font-size: 13px;
}

.steps {
  list-style: none;
  padding: 0;
}

.steps li {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 13px;
  color: var(--muted-on-wash);
}

.steps li[data-state="doing"] {
  color: var(--violet);
  font-weight: 600;
}

/* How long a slow step usually takes, under its words once it has turned past the still time. */
.steps li:has(.hint) {
  align-items: flex-start;
}

.steps li .hint {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  font-weight: 400;
  color: var(--muted-on-wash);
}

.steps li[data-state="done"] {
  color: var(--ink);
}

.mark {
  flex: none;
  position: relative;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid #d6d1e8;
  background: var(--card);
}

.steps li[data-state="done"] .mark {
  border-color: var(--done);
  background: var(--done);
}

.steps li[data-state="done"] .mark::after {
  content: "";
  position: absolute;
  left: 4.5px;
  top: 1.5px;
  width: 4px;
  height: 8px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

.mark.spin {
  border-color: #d6d1e8;
  border-top-color: var(--violet);
  animation: spin 0.9s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

/* The wait card, edged like the steps. */
.card {
  font-size: 14px;
  line-height: 1.45;
}

.card p {
  margin: 0 0 8px;
}

/* The card's ask to text us, quieter than its line. */
.card .quiet {
  color: var(--muted);
  font-size: 13px;
}

/* The suggestions: lavender chips, tapped to send. */
/* Over the suggestions while the example is made: the visitor's own change can be lined up now. */
.pills .meanwhile {
  margin: 0 0 8px;
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}

.pills .label {
  margin: 0 0 6px;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
}

.pills .row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.pill {
  border: 0;
  background: var(--violet-wash);
  color: var(--violet);
  border-radius: 18px;
  padding: 8px 14px;
  min-height: 44px;
  text-align: left;
  font-weight: 600;
  font-size: 15px;
  line-height: 1.3;
  cursor: pointer;
}

.pills .small {
  margin: 6px 0 0;
  font-size: 12px;
}

/* The composer: one rounded field with a round send button inside it. */
.compose label {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* While a change is made, the hint over the box says the next one waits, once there is one. */
.compose .hint {
  margin: 0 0 6px 4px;
  font-size: 12px;
  font-weight: 600;
  color: var(--muted);
}

.field {
  display: flex;
  gap: 6px;
  align-items: flex-end;
  border: 1px solid #d6d1e8;
  border-radius: 22px;
  padding: 4px 4px 4px 14px;
  background: var(--card);
}

.field:focus-within {
  border-color: var(--violet);
  box-shadow: 0 0 0 3px rgb(91 71 217 / 0.18);
}

.field textarea {
  flex: 1;
  min-width: 0;
  resize: none;
  field-sizing: content;
  min-height: 36px;
  max-height: 120px;
  border: 0;
  padding: 7px 0;
  background: transparent;
  color: var(--ink);
  font-size: 16px;
  line-height: 1.4;
}

.field textarea::placeholder {
  color: var(--muted);
}

/* The field's own border shows its focus, so the box draws no second ring inside it. */
.field textarea:focus-visible {
  outline: none;
}

.field button {
  flex: none;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: 50%;
  background: var(--violet);
  color: #fff;
  cursor: pointer;
}

/* Waiting Send: a pale fill with dark words, still 4.5:1, plainly not ready. */
.field button:disabled {
  background: var(--violet-wash);
  color: #57506f;
  cursor: default;
}

/* The example is typed and the start is not answered yet: the send button is ready-looking and its halo breathes. */
.field button.halo,
.field button.halo:disabled {
  background: var(--violet);
  color: #fff;
  animation: halo 1.2s ease-in-out infinite;
}

@keyframes halo {
  0%,
  100% {
    box-shadow: 0 0 0 2px rgb(91 71 217 / 0.35);
  }
  50% {
    box-shadow: 0 0 0 8px rgb(91 71 217 / 0.12);
  }
}

:root.calm .field button.halo {
  animation: none;
  box-shadow: 0 0 0 4px rgb(91 71 217 / 0.25);
}

/* No changes left: the box stays in sight, switched off, its words saying so at better than 4.5:1. */
.compose.out .field {
  background: var(--chrome);
  border-style: dashed;
}

.compose.out textarea:disabled {
  color: var(--muted-on-wash);
  -webkit-text-fill-color: var(--muted-on-wash);
  opacity: 1;
  cursor: not-allowed;
}

.compose.out textarea:disabled::placeholder {
  color: var(--muted-on-wash);
  -webkit-text-fill-color: var(--muted-on-wash);
  opacity: 1;
}

/* A page-wide message: a white card with its way forward beside it. */
.message {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 20px;
  max-width: 728px;
  margin: 8px 16px 20px;
  padding: 16px 20px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.message p {
  flex: 1 1 260px;
  margin: 0;
  font-size: 17px;
  line-height: 1.45;
}

@media (min-width: 760px) {
  .message {
    margin: 8px auto 24px;
  }
}

/* The start page: the headline centred, then a card per demo business; a row each on a phone, side by side on a computer. */
.start {
  max-width: 1120px;
  margin: 4px auto 24px;
  padding: 0 16px;
}

.start h1 {
  margin: 0 auto;
  max-width: 22ch;
  text-align: center;
  font-family: var(--display);
  font-weight: 700;
  font-size: 26px;
  line-height: 1.12;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

.start .lede {
  margin: 8px auto 20px;
  max-width: 56ch;
  text-align: center;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.45;
  text-wrap: pretty;
}

.businesses {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 12px;
}

.business {
  display: grid;
  grid-template-columns: 104px minmax(0, 1fr);
  grid-template-areas:
    "photo biz"
    "photo kind"
    "photo go";
  grid-template-rows: auto auto 1fr;
  column-gap: 14px;
  height: 100%;
  padding: 8px;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 20px;
  color: var(--ink);
  text-decoration: none;
  box-shadow:
    0 12px 24px -12px rgb(28 24 38 / 0.12),
    0 2px 6px -2px rgb(28 24 38 / 0.06);
  transition:
    border-color 150ms ease,
    box-shadow 150ms ease;
}

/* Its own shape, whatever the picture's: the clip keeps a taller picture from stretching it. */
.business .photo {
  grid-area: photo;
  display: block;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: 14px;
  background: var(--violet-wash);
}

.business img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The picture element only chooses the size; the img fills the photo as before. */
.business .photo picture {
  display: contents;
}

.business .biz {
  grid-area: biz;
  padding-top: 6px;
  font-family: var(--display);
  font-weight: 700;
  font-size: 18px;
  line-height: 1.2;
}

.business .kind {
  grid-area: kind;
  color: var(--muted);
  font-size: 14px;
}

.business .go {
  grid-area: go;
  align-self: end;
  justify-self: start;
  margin: 8px 0 4px;
  padding: 6px 14px;
  border-radius: 999px;
  background: var(--teal);
  color: #fff;
  font-weight: 700;
  font-size: 14px;
}

@media (hover: hover) {
  .business:hover {
    border-color: var(--violet);
    box-shadow:
      0 18px 32px -14px rgb(28 24 38 / 0.2),
      0 2px 6px -2px rgb(28 24 38 / 0.08);
  }

  .business:hover .go {
    background: var(--teal-deep);
  }
}

/* A computer: the cards side by side in columns, a picture across each card's top. */
@media (min-width: 760px) {
  .start {
    margin-top: 16px;
  }

  .start h1 {
    font-size: 40px;
  }

  .start .lede {
    margin: 12px auto 36px;
    font-size: 17px;
  }

  .businesses {
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
    gap: 20px;
  }

  .business {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "photo"
      "biz"
      "kind"
      "go";
    grid-template-rows: auto auto auto 1fr;
    padding: 10px;
  }

  .business .photo {
    aspect-ratio: 16 / 10;
  }

  .business .biz {
    padding: 14px 8px 0;
    font-size: 20px;
  }

  .business .kind {
    padding: 2px 8px 0;
    font-size: 15px;
  }

  .business .go {
    margin: 14px 8px 8px;
    padding: 8px 18px;
    font-size: 15px;
  }
}

/* The questions: one white card of rows, each with a plus that turns to a minus. */
.faq {
  max-width: 760px;
  margin: 40px auto 96px;
  padding: 0 16px;
  scroll-margin-top: 8px;
}

.faq h2 {
  font-family: var(--display);
  font-weight: 700;
  font-size: 26px;
  line-height: 1.2;
  text-align: center;
  margin: 0 0 16px;
}

#faq-list {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 24px;
  padding: 4px 20px;
}

.faq details + details {
  border-top: 1px solid var(--line);
}

.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  list-style: none;
  cursor: pointer;
  padding: 16px 0;
  font-weight: 600;
  font-size: 17px;
  line-height: 1.35;
  border-radius: 8px;
}

.faq summary::-webkit-details-marker {
  display: none;
}

.faq summary::after {
  content: "";
  flex: none;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background:
    linear-gradient(var(--violet), var(--violet)) center / 12px 2px no-repeat,
    linear-gradient(var(--violet), var(--violet)) center / 2px 12px no-repeat,
    var(--violet-wash);
}

.faq details[open] summary::after {
  background:
    linear-gradient(var(--violet), var(--violet)) center / 12px 2px no-repeat,
    var(--violet-wash);
}

.faq details p {
  margin: -4px 0 18px;
  color: var(--muted);
  font-size: 16px;
  max-width: 64ch;
}

.faq a,
.card a,
.handoff p a {
  color: var(--violet);
}

.sticky {
  position: fixed;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  z-index: 30;
  border: 0;
  border-radius: 999px;
  padding: 12px 20px;
  background: var(--ink);
  color: #fff;
  font-weight: 700;
  box-shadow: 0 10px 15px -3px rgb(28 24 38 / 0.3);
  cursor: pointer;
  white-space: nowrap;
}

/* A phone or tablet: the devices under the headline, the texting area a sheet held at the bottom of the screen. */
@media (max-width: 1023px) {
  body {
    padding-bottom: calc(var(--sheet, 0px) + 16px);
  }

  .devices {
    max-width: 720px;
    margin: 0 auto;
  }

  .chat {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 20;
    max-width: 560px;
    margin: 0 auto;
    padding: 16px 14px calc(12px + env(safe-area-inset-bottom));
    gap: 10px;
    border-radius: 24px 24px 0 0;
    box-shadow:
      0 -12px 32px -8px rgb(28 24 38 / 0.18),
      0 -1px 0 var(--line);
  }

  /* The page fades out above the sheet, so nothing is cut sharply behind it. */
  .chat::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 100%;
    height: 28px;
    background: linear-gradient(to top, var(--page), rgb(250 249 246 / 0));
    pointer-events: none;
  }

  .top {
    padding: 10px 16px;
  }

  .brand {
    font-size: 18px;
    gap: 8px;
  }

  .logo {
    width: 24px;
    height: 24px;
    border-radius: 7px;
  }

  .name {
    font-size: 14px;
  }

  .hero {
    margin: 0 auto 16px;
  }

  .hero h1 {
    font-size: 24px;
  }

  .hero p {
    margin-top: 6px;
    font-size: 14px;
  }

  .faq {
    margin-top: 48px;
  }

  /* The sheet's handle. */
  .chat::before {
    content: "";
    position: absolute;
    top: 6px;
    left: 50%;
    width: 36px;
    height: 4px;
    margin-left: -18px;
    border-radius: 999px;
    background: var(--line);
  }

  /* Lower still where the steps card needs the room: the page's script sets --fit. */
  .thread {
    max-height: min(128px, var(--fit, 128px));
  }

  .thread:empty {
    display: none;
  }

  /* One row of pills that scrolls sideways, so the sheet stays low. */
  .pills .row {
    flex-wrap: nowrap;
    overflow-x: auto;
    margin: 0 -14px;
    padding: 0 14px 2px;
    scroll-padding: 0 14px;
    scroll-snap-type: x proximity;
    scrollbar-width: none;
  }

  .pill {
    flex: none;
    width: max-content;
    max-width: min(84vw, 340px);
    scroll-snap-align: start;
  }

  /* While a change is made the sheet shrinks to its last message and status, so the devices stay in view. */
  .chat.busy .thread > li {
    display: none;
  }

  .chat.busy .thread > li.queued,
  .chat.busy .thread > li.sent:not(:has(~ li.sent)),
  .chat.busy .thread > li.sent:not(:has(~ li.sent)) ~ li.reply {
    display: block;
  }

  .sticky {
    bottom: calc(var(--sheet, 0px) + 12px);
  }
}

@media (min-width: 600px) and (max-width: 1023px) {
  .hero h1 {
    font-size: 32px;
  }

  .preview[data-kind="phone"] {
    width: 26%;
  }
}

/* A computer: the headline across the top, the texting phone on the left, the devices to its right. */
@media (min-width: 1024px) {
  .top {
    padding: 18px 32px;
  }

  .demo {
    display: grid;
    grid-template-columns: 380px minmax(0, 1fr);
    grid-template-areas:
      "hero hero"
      "chat devices"
      "all devices"
      "calm devices";
    grid-template-rows: auto auto auto 1fr;
    column-gap: 56px;
    align-items: start;
    padding: 0 32px 32px;
  }

  .record:has(> .card:not([hidden])) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* Centred just under the texting phone, and the calm switch just under it. */
  .all {
    grid-area: all;
    justify-self: center;
    margin: 16px 0 0;
  }

  .demo > .calm-switch {
    grid-area: calm;
    justify-self: center;
    margin: 8px 0 0;
  }

  .hero {
    grid-area: hero;
    max-width: 980px;
    margin: 0 auto 28px;
  }

  .hero h1 {
    font-size: 40px;
  }

  .hero p {
    font-size: 17px;
    margin-top: 12px;
  }

  .devices {
    grid-area: devices;
    gap: 20px;
    padding-top: 24px;
  }

  .previews {
    padding-bottom: 56px;
  }

  /* The row sits just under the browser window, centred on it, in the room left of the phone with 16px kept clear of
     it; a third button wraps below. */
  .done {
    position: relative;
    z-index: 3;
    width: 88%;
    padding: 0 calc(12% + 16px);
    margin-top: calc(12px - 56px - 20px);
  }

  /* With Watch it again, the row takes the whole room left of the phone, so all three keep to one line where it is wide
     enough, as at 1440 (run-through on test, Oct. 24th). */
  .done:has(> #watch-again:not([hidden])) {
    padding-left: 0;
  }

  .preview[data-kind="phone"] {
    width: 24%;
    --rim: 7px;
  }

  .preview[data-kind="computer"] {
    --bar: 30px;
  }

  .chrome {
    gap: 6px;
    padding: 0 12px;
  }

  .chrome i {
    width: 9px;
    height: 9px;
  }

  .chrome .address {
    height: 14px;
  }

  .chrome .address.named {
    height: 22px;
    gap: 6px;
    padding: 0 4px 0 11px;
    font-size: 13px;
  }

  .preview[data-kind="computer"] .screen,
  .chrome {
    border-color: var(--line);
  }

  .preview[data-kind="computer"] .screen {
    border-radius: 0 0 12px 12px;
  }

  .chrome {
    border-radius: 12px 12px 0 0;
  }

  .preview[data-kind="phone"] .screen {
    border-radius: 30px;
  }

  .preview[data-kind="phone"] .enlarge {
    border-radius: 30px;
  }

  .preview[data-kind="computer"] figcaption {
    left: 10px;
  }

  /* The texting phone: a dark outline, its bar with the camera dot, and a messages screen. */
  .chat {
    grid-area: chat;
    position: relative;
    height: clamp(600px, calc(100dvh - 224px), 780px);
    border: 12px solid var(--ink);
    border-radius: 52px;
    box-shadow: var(--shadow);
    overflow: hidden;
    container-type: inline-size;
  }

  .chat .status {
    display: flex;
    flex: none;
  }

  /* The header sits right under the bar, which now holds the camera dot. */
  .head {
    flex: none;
    flex-direction: column;
    gap: 4px;
    padding: 10px 16px 10px;
    border-bottom: 1px solid var(--line);
  }

  .avatar {
    width: 44px;
    height: 44px;
  }

  .left {
    position: absolute;
    right: 16px;
    top: 24px;
    max-width: 30%;
  }

  .dock {
    flex: none;
  }

  .thread {
    flex: 1;
    padding: 16px 14px 8px;
  }

  .loading .skeleton.talk {
    flex: 1;
    padding: 16px 14px 8px;
  }

  .dock {
    padding: 8px 14px 14px;
  }

  .bubble p {
    font-size: 16px;
  }

  .faq {
    margin-top: 64px;
  }

  .faq h2 {
    font-size: 30px;
  }

  #faq-list {
    padding: 8px 28px;
  }

  /* A shared link: the devices alone, centred, and the calm switch under them. */
  .demo.look {
    grid-template-columns: minmax(0, 960px);
    grid-template-areas:
      "devices"
      "calm";
    grid-template-rows: auto auto;
    justify-content: center;
  }
}

/* A shared link has no texting phone, so no way back beside it. */
.demo.look .all {
  display: none;
}

/* Less motion: fades only, no turning spinner, no growing ring, no popping bubbles, still dots. The page sets the calm
   class from the system's less-motion setting or its own calm switch. */
:root.calm .mark.spin {
  animation: none;
  border-color: var(--violet);
  background: radial-gradient(circle, var(--violet) 0 3px, transparent 4px);
}

:root.calm .ring,
:root.calm .bubble,
:root.calm .dots i,
:root.calm .bone,
:root.calm .loading .screen,
:root.calm .loading .hero h1:empty,
:root.calm .loading #close-up {
  animation: none;
}

:root.calm .dots i {
  opacity: 0.7;
}

/* While the demo is paused: its banner across the top, and the start page's cards shown still, with no way in. */
.paused {
  background: var(--violet-wash);
  border-bottom: 1px solid var(--line);
}

.paused p {
  max-width: 1280px;
  margin: 0 auto;
  padding: 12px 16px;
  color: var(--ink);
  font-weight: 600;
  font-size: 15px;
  line-height: 1.45;
  text-wrap: pretty;
}

.start .lede[hidden] + .businesses {
  margin-top: 20px;
}

.business.still {
  grid-template-rows: auto auto 1fr;
  cursor: default;
}

@media (hover: hover) {
  .business.still:hover {
    border-color: var(--line);
    box-shadow:
      0 12px 24px -12px rgb(28 24 38 / 0.12),
      0 2px 6px -2px rgb(28 24 38 / 0.06);
  }
}

@media (min-width: 760px) {
  .paused p {
    text-align: center;
    font-size: 16px;
  }

  .start .lede[hidden] + .businesses {
    margin-top: 32px;
  }

  .business.still {
    grid-template-rows: auto auto 1fr;
    padding-bottom: 18px;
  }
}

/* A demo's top bar is the 48px the slim header later takes, at every width, from the first paint. */
body[data-demo] .top {
  height: 48px;
  padding-top: 0;
  padding-bottom: 0;
}

/* The calm switch: a quiet button just under All demos, shown when the settings name it. */
.calm-switch {
  display: block;
  width: fit-content;
  margin: 0 0 12px;
  padding: 6px 12px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--card);
  color: var(--ink);
  font-size: 13px;
  line-height: 1.2;
  cursor: pointer;
}

.calm-switch[aria-pressed="true"] {
  border-color: var(--violet);
  background: var(--violet-wash);
}

/* A demo draws its words before the copy is ready, so no placeholder ever stands in for them. */
body[data-demo] .demo.loading .skeleton {
  display: none;
}

body[data-demo] .demo.loading .thread {
  display: flex !important;
}

body[data-demo] .demo.loading .dock > .compose:not([hidden]) {
  display: block !important;
}

/* The first paint: the headline, the line under it and the texting phone, large and centred, held still; the
   devices join once the copy is ready. */
.demo.first .devices,
.demo.first > .all {
  display: none;
}

.demo.first .bubble,
.bubble.placed {
  animation: none;
}

/* The messages sit at the foot of the texting phone, as on a real one, so the greeting never moves. */
body[data-demo] .thread > :first-child {
  margin-top: auto;
}

@media (max-width: 1023px) {
  body[data-demo]:has(.demo.first) {
    padding-bottom: 16px;
  }

  .demo.first .chat {
    position: relative;
    left: auto;
    right: auto;
    bottom: auto;
    z-index: auto;
    width: calc(100% - 28px);
    max-width: 380px;
    height: clamp(300px, calc(100svh - 236px), 452px);
    margin: 0 auto;
    padding: 0;
    gap: 0;
    border: 8px solid var(--ink);
    border-radius: 34px;
    box-shadow: var(--shadow);
    overflow: hidden;
    container-type: inline-size;
  }

  .demo.first .chat::before,
  .demo.first .chat::after {
    display: none;
  }

  .demo.first .chat .status {
    display: flex;
    flex: none;
  }

  .demo.first .head {
    flex: none;
    padding: 4px 12px 6px;
    border-bottom: 1px solid var(--line);
  }

  .demo.first .avatar {
    width: 26px;
    height: 26px;
  }

  .demo.first .who {
    font-size: 14px;
  }

  .demo.first .thread {
    flex: 1;
    max-height: none;
    padding: 8px 10px;
  }

  .demo.first .dock {
    flex: none;
    padding: 0 10px 10px;
  }
}

/* Option C slice 1. The site's phone view waits out of sight, still drawn, until the double-check of both screens. */
.preview[data-kind="phone"] {
  transition: opacity 600ms ease;
}

.previews.hold-phone .preview[data-kind="phone"]:not(.up) {
  opacity: 0;
  pointer-events: none;
}

/* The badges while both screens are double-checked, gone once the change shows in both. */
.badge {
  position: absolute;
  z-index: 5;
  display: none;
  padding: 3px 8px;
  border-radius: 6px;
  background: var(--ink);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  line-height: 1.3;
  white-space: nowrap;
  pointer-events: none;
}

.previews.checking .badge {
  display: block;
}

.preview[data-kind="computer"] .badge {
  left: 8px;
  top: calc(var(--bar) + 8px);
}

.preview[data-kind="phone"] .badge {
  right: 0;
  bottom: calc(100% + 6px);
}

/* Done and the preview link, one message: the words, then the link under them in the same lavender; the message
   breathes until the link is opened. */
.bubble.linked .msg {
  border-radius: 20px 20px 20px 6px;
}

.bubble.linked p {
  padding-bottom: 2px;
  border-radius: 20px 20px 0 0;
}

.bubble.linked .preview-link {
  display: block;
  padding: 0 14px 9px;
  border-radius: 0 0 20px 6px;
  background: var(--violet-wash);
  color: var(--teal-deep);
  font-size: 15px;
  line-height: 1.38;
  text-decoration: underline;
  text-underline-offset: 2px;
  /* The page puts a soft break after each dot and hyphen; a name is split only when one alone is wider than the line. */
  overflow-wrap: break-word;
}

.bubble.breathe .msg {
  animation: breathe 1.2s ease-in-out infinite;
}

@keyframes breathe {
  0%,
  100% {
    box-shadow: 0 0 0 3px rgb(14 122 152 / 0.3);
  }
  50% {
    box-shadow: 0 0 0 9px rgb(14 122 152 / 0.12);
  }
}

/* Opening the link in the computer's view: one brief dip as the page comes in. */
.screen.dip {
  animation: dip 700ms ease-in-out;
}

@keyframes dip {
  50% {
    opacity: 0.55;
  }
}

.cue {
  margin: 10px auto 0;
  max-width: 56ch;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.4;
  text-align: center;
}

/* The big ask: a white card under the computer, or over the texting sheet on a phone. */
.ask {
  margin: 16px auto 0;
  max-width: 560px;
  padding: 16px 18px;
  background: var(--card);
  border-radius: 20px;
  box-shadow: var(--shadow);
}

.ask h2 {
  margin: 0;
  font-family: var(--display);
  font-size: 19px;
  line-height: 1.25;
}

.ask p {
  margin: 6px 0 0;
  font-size: 14px;
  line-height: 1.4;
}

.ask .lead {
  margin-bottom: 12px;
}

.ask a.button {
  display: block;
  text-align: center;
}

.ask .reassure,
.ask .meta {
  color: var(--muted);
  font-size: 13px;
}

.ask .call {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
  font-weight: 600;
}

/* On a computer the code a phone scans sits beside the number, its room kept before it is drawn, and the text-us button,
   which opens nothing there, is left out. */
.ask .scan {
  display: none;
}

@media (pointer: fine) {
  .ask:not([hidden]) {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 18px;
    align-content: start;
  }

  .ask > * {
    grid-column: 1;
  }

  .ask:not([hidden]) > .scan {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    grid-column: 2;
    grid-row: 1 / span 9;
    align-self: center;
  }

  .ask .code {
    flex: none;
    width: 104px;
    height: 104px;
    background: #fff;
  }

  .ask .code svg {
    display: block;
    width: 100%;
    height: 100%;
    fill: var(--ink);
  }

  .ask .scan .words {
    max-width: 15ch;
    margin: 0;
    color: var(--muted);
    font-size: 12px;
    line-height: 1.3;
    text-align: center;
  }

  .ask a.button {
    display: none;
  }

  /* Arm B's ask goes to the web chat, so a computer shows its button too, where the text ask shows a code. */
  .ask a.button[data-web] {
    display: block;
  }
}

.ask .copy,
.ask .again-link {
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 4px 12px;
  background: var(--card);
  color: var(--ink);
  font-size: 13px;
  cursor: pointer;
}

.ask .again-link {
  margin-top: 10px;
  border: 0;
  padding: 0;
  color: var(--teal-deep);
  text-decoration: underline;
  font-size: 14px;
}

.ask .consent {
  color: var(--muted);
  font-size: 11px;
  line-height: 1.5;
}

@media (max-width: 1023px) {
  .ask {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 25;
    margin: 0 auto;
    max-height: 70dvh;
    overflow-y: auto;
    padding: 16px 16px calc(14px + env(safe-area-inset-bottom));
    border-radius: 24px 24px 0 0;
  }

  body.asked .chat {
    visibility: hidden;
  }

  /* While the preview link waits for its tap, the sheet shows that one message whole. */
  .chat .thread:has(> .breathe) {
    max-height: none;
  }

  .chat .thread:has(> .breathe) > li:not(.breathe) {
    display: none;
  }
}

:root.calm .preview[data-kind="phone"] {
  transition: none;
}

:root.calm .ring {
  opacity: 0.6;
}

:root.calm .bubble.breathe .msg {
  animation: soft 2s ease-in-out infinite;
}

:root.calm .screen.dip {
  animation: none;
}

/* The preview link opened: after the dip, the changed spot's ring breathes once more until the open's beat ends
   (cueFor in app.js), so the stretch before the big ask is never still; with less motion it fades from the start. */
.ring.again {
  animation: ring-again 1300ms ease-in-out 700ms both;
}

@keyframes ring-again {
  0%,
  100% {
    opacity: 0.35;
  }
  50% {
    opacity: 1;
  }
}

:root.calm .ring.again {
  animation: ring-calm 2s ease-in-out both;
}

@keyframes ring-calm {
  0%,
  100% {
    opacity: 0.6;
  }
  50% {
    opacity: 1;
  }
}

@keyframes soft {
  50% {
    opacity: 0.65;
  }
}

@media (min-width: 1024px) {
  .demo.first {
    grid-template-columns: minmax(0, 1fr) 380px minmax(0, 1fr);
    grid-template-areas:
      "hero hero hero"
      ". chat ."
      ". calm .";
    grid-template-rows: auto auto auto;
  }
}

/* Option C slice 2. The demo area is the screen less the 48px bar, scrolled inside, so the page stays put through a
   change; the texting phone is drawn in the page at every width, never a sheet. */
body[data-demo] {
  padding-bottom: 16px;
}

body[data-demo] .demo {
  height: calc(100dvh - 48px);
  padding-bottom: 16px;
  overflow-y: auto;
  /* A scrollbar coming or going as a line wraps never shifts what is drawn across. */
  scrollbar-gutter: stable;
}

/* The greeting is there from the first paint and never pops in again. */
body[data-demo] .bubble.intro {
  animation: none;
}

/* The step line carries a change: no seven-step card, no wait card, no typing bubble. */
body[data-demo] #record,
body[data-demo] #progress {
  display: none !important;
}

/* Until both screens are first drawn, the devices wait out of the layout. */
body[data-demo] .demo.stage-phone .devices {
  display: none;
}

@media (max-width: 1023px) {
  body[data-demo] .demo {
    display: flex;
    flex-direction: column;
  }

  body[data-demo] .chat {
    position: relative;
    left: auto;
    right: auto;
    bottom: auto;
    z-index: auto;
    flex: none;
    width: calc(100% - 28px);
    max-width: 380px;
    margin: 0 auto;
    padding: 0;
    gap: 0;
    border: 8px solid var(--ink);
    border-radius: 34px;
    box-shadow: var(--shadow);
    overflow: hidden;
    container-type: inline-size;
  }

  body[data-demo] .chat::before,
  body[data-demo] .chat::after {
    display: none;
  }

  body[data-demo] .chat .status {
    display: flex;
    flex: none;
  }

  body[data-demo] .head {
    flex: none;
    padding: 4px 12px 6px;
    border-bottom: 1px solid var(--line);
  }

  body[data-demo] .avatar {
    width: 26px;
    height: 26px;
  }

  body[data-demo] .who {
    font-size: 14px;
  }

  body[data-demo] .thread {
    flex: 1;
    max-height: none;
    padding: 8px 10px;
  }

  body[data-demo] .chat.busy .thread > li {
    display: block;
  }

  body[data-demo] .dock {
    flex: none;
    padding: 0 10px 10px;
  }

  /* While the change is on the phone side, the phone is large. */
  body[data-demo] .demo.stage-phone .chat {
    height: clamp(300px, calc(100svh - 236px), 452px);
  }

  /* Once both screens are drawn, the phone is a strip of its newest messages while a change is made, and has room
     for the suggestions and the box when they show. */
  body[data-demo] .demo.stage-box .thread {
    flex: 0 1 120px;
    max-height: none;
  }

  /* The suggestions wrap inside the phone: the row stays within the phone's edge, and no suggestion is wider than it. */
  body[data-demo] .pills .row {
    margin: 0;
    padding: 0 0 2px;
    scroll-padding: 0;
  }

  body[data-demo] .pill {
    max-width: 100%;
  }

  /* On the narrowest phones the suggestions and their line are a size smaller, so the phone, the step line and both
     previews all fit the demo area during the double-check. */
  @media (max-width: 360px) {
    body[data-demo] .pill {
      padding: 6px 12px;
      font-size: 14px;
    }

    body[data-demo] .pills .meanwhile {
      font-size: 14px;
    }
  }

  body[data-demo] .demo.stage-box .chat.busy .dock:not(:has(> #pills:not([hidden]))) {
    display: none;
  }

  /* Once both screens are drawn the phone takes only the room the demo area leaves over them, measured by the page;
     its messages give way first. */
  body[data-demo] .demo.stage-box .chat {
    max-height: var(--room, none);
  }

  body[data-demo] .demo.stage-box .thread {
    min-height: 0;
  }

  /* While the preview link waits for its tap, the strip shows it; the suggestions come in once it is opened, in the
     room they keep meanwhile, so nothing under the phone moves when they do. */
  body[data-demo] .demo.stage-box .chat:has(.bubble.breathe) .dock {
    visibility: hidden;
  }

  /* Once both screens are drawn, a change being made on a phone is named by the step line; the example's line waits. */
  body[data-demo] .demo.stage-box:has(.chat.busy) > .example {
    margin: 0 0 6px;
    padding: 4px 12px;
    font-size: 13px;
  }

  body[data-demo] .demo.stage-box:has(.chat.busy) > .example .what {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  body[data-demo] .demo.stage-box:has(.chat.busy) > .example .clock {
    display: none;
  }

  body[data-demo] .demo > .example {
    margin: 0 0 10px;
  }

  /* During the double-check the strip shows the suggestions in one row under their line, and no more, so both
     screens stay in sight under it. */
  body[data-demo] .demo.stage-box .chat.busy #pills-label,
  body[data-demo] .demo.stage-box .chat.busy #wait-hint,
  body[data-demo] .demo.stage-box .chat.busy .compose {
    display: none;
  }

  body[data-demo] .devices {
    width: 100%;
    margin-top: 12px;
  }

  body[data-demo] .demo > .all {
    order: 9;
    margin: 16px 0 0;
  }

  /* The calm switch is last in the demo area, just under All demos. */
  body[data-demo] .demo > .calm-switch {
    flex: none;
    order: 9;
    margin: 8px 0 0;
  }

  body[data-demo].asked .chat {
    visibility: visible;
  }

  /* The big ask sits under both previews in the demo area, which scrolls to put their change at the top above it,
     so the change and the ask's button are in sight together; never a sheet over them. */
  body[data-demo] .ask {
    position: static;
    width: calc(100% - 28px);
    max-height: none;
    margin: 16px auto 0;
    overflow: visible;
    padding: 16px;
    border-radius: 20px;
  }

  body[data-demo] .sticky {
    bottom: 16px;
  }
}

@media (min-width: 1024px) {
  /* The step line stays under the texting phone, so its icon never jumps across the page. The computer's layout holds
     from the first paint (marketing, Oct. 24th): the phone sits where it ends up and the devices keep their room. */
  body[data-demo] .demo:is(.first, .stage-phone, .stage-box) {
    grid-template-columns: 380px minmax(0, 1fr);
    grid-template-areas:
      "hero hero"
      "ex devices"
      "chat devices"
      "step devices"
      "all devices"
      "calm devices";
    grid-template-rows: auto auto auto auto auto 1fr;
  }

  body[data-demo] .demo > .example {
    grid-area: ex;
    margin: 0 0 8px;
  }

  body[data-demo] .hero {
    margin-bottom: 20px;
  }

  /* The big ask is snug, so at 1440×900 the whole card, consent line included, fits under the sub-line. */
  body[data-demo] .ask {
    margin-top: 0;
    padding-block: 10px;
  }

  /* The ask stays under Before and After from the example on; the preview link's line comes and goes under it, so it
     never moves the ask. */
  body[data-demo] .devices > .cue {
    order: 1;
  }

  body[data-demo] .ask p {
    margin-top: 4px;
  }

  body[data-demo] .ask .lead {
    margin-bottom: 8px;
  }

  body[data-demo] .ask .call,
  body[data-demo] .ask .again-link {
    margin-top: 6px;
  }

  /* Rows keep their own height: the room the screen has over is never shared out among them, so the phone and the step
     line sit where they do at every height and never shift as the example's line comes and goes. */
  body[data-demo] .demo {
    align-content: start;
  }

  body[data-demo] .stepline {
    grid-area: step;
    margin: 12px 0 0;
  }

  body[data-demo] .demo:is(.first, .stage-phone, .stage-box) .devices {
    padding-top: 0;
  }

  /* Until both screens are first drawn, the devices keep their room unseen and held still. */
  body[data-demo] .demo:is(.first, .stage-phone) .devices {
    display: grid;
    visibility: hidden;
  }

  body[data-demo] .demo:is(.first, .stage-phone) .devices,
  body[data-demo] .demo:is(.first, .stage-phone) .devices *,
  body[data-demo] .demo:is(.first, .stage-phone) .devices *::before,
  body[data-demo] .demo:is(.first, .stage-phone) .devices *::after {
    animation: none;
    transition: none;
  }

  /* The texting phone takes what the screen leaves under the 48px bar for the headline, the example's line, the
     two-line step line and the way back, so none of them is cut or scrolled under the bar at 1440×900. */
  body[data-demo] .chat {
    height: clamp(520px, calc(100dvh - 378px), 780px);
  }
}

/* The example's line after the visitor's own change begins: gone, but on a computer its room stays so nothing under it
   moves. */
.example.away {
  display: none;
}

@media (min-width: 1024px) {
  body[data-demo] .demo > .example.away {
    display: flex;
    visibility: hidden;
  }
}

/* The one step line: the real step, its looping icon in a fixed spot, the clock, and the step's hint. */
.stepline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px 8px;
  width: calc(100% - 28px);
  max-width: 380px;
  margin: 10px auto 0;
  font-size: 14px;
  line-height: 1.35;
}

.stepline .words {
  flex: 1;
  min-width: 0;
}

/* Not the top bar's business name: it wraps, never cut. */
.stepline .name {
  padding: 0;
  border: 0;
  overflow: visible;
  font-size: inherit;
  white-space: normal;
  color: var(--violet);
}

.stepline .clock {
  flex: none;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.stepline .hint {
  flex-basis: 100%;
  color: var(--muted);
  font-size: 13px;
}

.stepline .hint:empty,
.stepline .n:empty {
  display: none;
}

.stepline .icon {
  position: relative;
  flex: none;
  width: 22px;
  height: 22px;
}

.stepline .icon svg {
  position: absolute;
  inset: 0;
  display: none;
  width: 100%;
  height: 100%;
  fill: none;
  stroke: var(--violet);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.stepline[data-icon="look"] svg[data-icon="look"],
.stepline[data-icon="reading"] svg[data-icon="reading"],
.stepline[data-icon="change"] svg[data-icon="change"],
.stepline[data-icon="screens"] svg[data-icon="screens"],
.stepline[data-icon="check"] svg[data-icon="check"] {
  display: block;
}

/* Each icon loops in its own spot, about every 2.2s, the spec's 2 to 2.5s. */
svg[data-icon="look"] {
  transform-origin: 45% 45%;
  animation: look 2.2s ease-in-out infinite;
}

svg[data-icon="reading"] .turn {
  transform-origin: 54% 50%;
  animation: turn 2.2s ease-in-out infinite;
}

svg[data-icon="change"] {
  animation: write 2.2s ease-in-out infinite;
}

svg[data-icon="screens"] .second {
  animation: second 2.2s ease-in-out infinite;
}

svg[data-icon="check"] path {
  stroke-dasharray: 14;
  animation: tick 2.2s linear infinite;
}

@keyframes look {
  50% {
    transform: rotate(-14deg);
  }
}

@keyframes turn {
  50% {
    transform: scaleX(-1);
  }
}

@keyframes write {
  50% {
    transform: translate(1.5px, -1.5px);
  }
}

@keyframes second {
  50% {
    opacity: 0.25;
  }
}

@keyframes tick {
  0% {
    stroke-dashoffset: 14;
  }
  100% {
    stroke-dashoffset: -14;
  }
}

/* While something else on the page moves, the icon holds still, so one thing moves at a time. */
.stepline.hush .icon svg,
.stepline.hush .icon svg * {
  animation-play-state: paused;
}

/* Out of the visitor's sight the loops hold, and what changes meanwhile changes at once, so nothing plays on return. */
:root.away *,
:root.away *::before,
:root.away *::after {
  animation-play-state: paused !important;
  transition: none !important;
}

/* The calm page: the icon only pulses. */
:root.calm .stepline .icon svg,
:root.calm .stepline .icon svg * {
  animation: none;
}

:root.calm .stepline .icon svg {
  animation: soft 2s ease-in-out infinite;
}

/* The connection line takes the step's place, with no icon. */
.stepline.offline .icon {
  display: none;
}

/* The box draws itself once, as both screens are first drawn: the line goes round it, then the site fills it. */
.preview[data-kind="computer"] .outline {
  position: absolute;
  inset: 0;
  z-index: 6;
  display: none;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.outline rect {
  fill: none;
  stroke: var(--violet);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}

.devices.pre {
  visibility: hidden;
}

.devices.lining .outline {
  display: block;
}

.devices.lining .outline rect {
  animation: line 800ms ease-out forwards;
}

.devices.lining .preview[data-kind="computer"] .stage > :not(.outline) {
  opacity: 0;
}

.devices.filling .preview[data-kind="computer"] .stage > :not(.outline) {
  animation: fill 300ms ease-out both;
}

@keyframes line {
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes fill {
  from {
    opacity: 0;
  }
}

/* The phone's badge sits in its own screen, never over the computer's address bar. */
.preview[data-kind="phone"] .badge {
  top: 14%;
  right: 4px;
  bottom: auto;
  left: 4px;
  padding: 2px 4px;
  font-size: 10px;
  white-space: normal;
  text-align: center;
}

/* The computer's bar drops its Preview chip before it cuts the address. */
.chrome .address.tight .chip {
  display: none;
}

/* The slim header, after the first change: it takes the bar's place and never more room. */
body[data-demo] .top {
  position: relative;
}

.slim {
  display: flex;
  flex: 1;
  align-items: center;
  gap: 10px;
  min-width: 0;
  font-weight: 600;
  font-size: 14.5px;
  animation: slim 400ms ease-out both;
}

/* On a phone the longest business names wrap to two lines, whole, and on the narrowest phones the logo stands for the
   Stenzil name. */
@media (max-width: 480px) {
  body[data-demo] .top .name {
    padding-left: 8px;
    font-size: 13px;
    line-height: 1.15;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
  }
}

@media (max-width: 360px) {
  body[data-demo] .top .brand {
    gap: 0;
    font-size: 0;
  }
}

.slim span {
  min-width: 0;
  line-height: 1.15;
}

@media (max-width: 400px) {
  .slim {
    gap: 6px;
    font-size: 13px;
  }

  .slim a.button {
    padding: 6px 10px;
    font-size: 13px;
  }
}

.slim a.button {
  margin-left: auto;
  padding: 7px 14px;
  font-size: 14px;
  white-space: nowrap;
}

.top.slimmed .brand,
.top.slimmed .name {
  display: none;
}

@keyframes slim {
  from {
    opacity: 0;
    transform: translateY(-100%);
  }
}

:root.calm .slim,
:root.calm .devices.filling .preview[data-kind="computer"] .stage > :not(.outline) {
  animation: none;
}

/* The typing caret blinks in the empty box before the example's first letter, so the screen is never still; with less
   motion it only pulses. */
.field {
  position: relative;
}

.field .caret {
  position: absolute;
  left: 12px;
  bottom: 12px;
  width: 2px;
  height: 20px;
  border-radius: 1px;
  background: var(--violet);
  pointer-events: none;
  animation: caret 1s ease-in-out infinite;
}

.field .caret[hidden] {
  display: none;
}

@keyframes caret {
  50% {
    opacity: 0.1;
  }
}

:root.calm .field .caret,
:root.calm .compose .example-tag:not([hidden]) {
  animation: soft 2s ease-in-out infinite;
}

/* While the example types, the box keeps its one line and shows the newest words, so its height never moves the
   messages over it (run-through on test, Oct. 24th). */
.compose:has(> .example-tag:not([hidden])) .field textarea {
  field-sizing: fixed;
}

/* Space kept on a phone (marketing, 12:49am Oct. 24th): the step line, the devices, the preview link's line and the
   texting phone's height take their room from the first paint, so the previews never move; a little empty space shows.
   Phones narrower than 380px keep it too, with a smaller texting phone from the double-check on (Claire, option B,
   11:16am Oct. 24th). */
@media (max-width: 1023px) {
  body[data-demo] .demo:not(.look) > .stepline {
    min-height: 38px;
  }

  body[data-demo] .demo:not(.look) > .stepline[hidden] {
    display: flex !important;
    visibility: hidden;
  }

  body[data-demo] .demo:is(.first, .stage-phone) .devices {
    display: grid;
    visibility: hidden;
  }

  /* While they only keep their room, the devices are held still, as when they were out of the layout. */
  body[data-demo] .demo:is(.first, .stage-phone) .devices,
  body[data-demo] .demo:is(.first, .stage-phone) .devices *,
  body[data-demo] .demo:is(.first, .stage-phone) .devices *::before,
  body[data-demo] .demo:is(.first, .stage-phone) .devices *::after,
  body[data-demo] .demo:is(.first, .stage-phone) .devices #close-up,
  body[data-demo] .demo .done[hidden] #close-up {
    animation: none;
    transition: none;
  }

  body[data-demo] .demo .done[hidden],
  body[data-demo] .demo .cue[hidden] {
    display: flex !important;
    visibility: hidden;
  }

  /* The example's label keeps its room over the box until both screens are drawn, so it coming and going with the
     example's typing and send never moves the messages (run-through on test, Oct. 24th). */
  body[data-demo] .demo:is(.first, .stage-phone) .compose .example-tag[hidden] {
    display: inline-block !important;
    visibility: hidden;
  }

  /* While both screens are double-checked the suggestions show under their own line; the suggestions' label, their
     hint and the box keep their room unseen, and the two lines share one slot, so the bottom area keeps its height when
     the change lands and they come in (run-through on test, Oct. 24th). */
  body[data-demo] .demo:not(.look) .pills {
    display: grid;
  }

  body[data-demo] .demo:not(.look) .pills > .meanwhile,
  body[data-demo] .demo:not(.look) .pills > .label {
    grid-area: 1 / 1;
  }

  body[data-demo] .demo:not(.look) .pills > .meanwhile[hidden] {
    display: block !important;
    visibility: hidden;
  }

  body[data-demo] .demo.stage-box .chat.busy #pills-label,
  body[data-demo] .demo.stage-box .chat.busy #wait-hint,
  body[data-demo] .demo.stage-box .chat.busy .compose {
    display: block;
    visibility: hidden;
  }

  body[data-demo] .demo .done {
    min-height: 48px;
  }

  /* The devices are as wide as the demo area, never as wide as the row under them, so the phone preview never runs off
     the screen and the previews never resize as the row's buttons come and go (run-through on test, Oct. 24th). */
  body[data-demo] .devices {
    grid-template-columns: minmax(0, 1fr);
  }

  body[data-demo] .demo .cue {
    min-height: 39px;
  }

  /* The older messages stay while the preview link waits for its tap, the thread scrolled to the link's message, so
     none of them moves when the link opens. */
  body[data-demo] .chat:not(.busy) .thread:has(> .breathe) > li:not(.breathe) {
    display: block;
  }

  /* The texting phone keeps the large stage's height in every stage; the messages take what its dock leaves. */
  body[data-demo] .demo:is(.first, .stage-phone, .stage-box) .chat {
    flex: none;
    height: clamp(300px, calc(100svh - 236px), 452px);
    min-height: 0;
    max-height: none;
  }

  body[data-demo] .demo.stage-box .thread {
    flex: 1 1 0;
  }
}

/* The ask pinned to the bottom of a phone's screen once the example lands; its height comes out of the demo area, so
   it never sits over the previews. A computer has the big ask under the previews instead. */
.askbar {
  display: none;
}

@media (max-width: 1023px) {
  body[data-demo] .askbar:not([hidden]) {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 26;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
    background: var(--card);
    border-top: 1px solid var(--line);
    box-shadow: 0 -8px 16px -8px rgb(28 24 38 / 0.12);
    font-weight: 600;
    font-size: 14.5px;
  }

  .askbar span {
    min-width: 0;
    line-height: 1.15;
  }

  .askbar a.button {
    margin-left: auto;
    padding: 9px 14px;
    font-size: 14px;
    white-space: nowrap;
  }

  body[data-demo] .demo {
    height: calc(100dvh - 48px - var(--askbar, 0px));
  }

  /* The page's foot scrolls clear of the bar. */
  body[data-demo] {
    padding-bottom: calc(16px + var(--askbar, 0px));
  }

  body[data-demo] .sticky {
    bottom: calc(16px + var(--askbar, 0px));
  }
}

/* Option B (Claire, 11:16am Oct. 24th): below 380px the phone, both previews and the bar cannot all fit at once, so from
   the double-check on (.checked) the texting phone takes only the room the page measures over both previews, and keeps it; the
   bar's room is kept from the first paint, so that room never changes when the bar comes in. The Done message is cut
   there; the bar carries the ask. */
@media (max-width: 379px) {
  /* Until the example lands the bar is an empty strip, so the page under it never shows through. */
  body[data-demo] .askbar[hidden] {
    display: flex !important;
  }

  body[data-demo] .askbar[hidden] > * {
    visibility: hidden;
  }

  body[data-demo] .askbar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 26;
    align-items: center;
    box-sizing: content-box;
    height: 38px;
    padding: 10px 16px calc(10px + env(safe-area-inset-bottom));
    background: var(--card);
    border-top: 1px solid var(--line);
  }

  body[data-demo] .demo:not(.look).stage-box.checked .chat {
    max-height: var(--room, none);
  }

  /* While a change is made the messages give their padding to the suggestions, so a whole row of them fits. */
  body[data-demo] .demo:not(.look).stage-box .chat.busy:has(#pills:not([hidden])) .thread {
    padding-block: 0;
  }
}

@media (max-width: 400px) {
  body[data-demo] .askbar:not([hidden]) {
    gap: 6px;
    font-size: 13px;
  }

  .askbar a.button {
    padding: 8px 12px;
    font-size: 13px;
  }
}

/*
 * Round 3's computer layout (Claire, 8:27pm Oct. 24th), on only when the settings' computerR3 is, at 1024px and wider.
 * Everything is placed as the board places it at 1440×900, in units of --r, one board pixel at the screen's size, so the
 * page keeps the board's proportions at every computer size. Phones and the page with the switch off never match.
 */
.r3-sub {
  display: none;
}

@media (min-width: 1024px) {
  body[data-r3][data-demo] {
    --r: min(calc(100vw / 1440), calc(100dvh / 900));
    padding-bottom: 0;
  }

  body[data-r3][data-demo] .top {
    max-width: none;
    height: calc(56 * var(--r));
    padding: 0 calc(120 * var(--r));
    gap: calc(12 * var(--r));
    border-bottom: 1px solid var(--line);
  }

  body[data-r3][data-demo] .top .brand {
    gap: calc(12 * var(--r));
    font-size: calc(17 * var(--r));
  }

  body[data-r3][data-demo] .top .logo {
    width: calc(28 * var(--r));
    height: calc(28 * var(--r));
  }

  body[data-r3][data-demo] .top .name {
    padding-left: calc(12 * var(--r));
    font-size: calc(14 * var(--r));
  }

  body[data-r3][data-demo] .top .slim {
    display: none !important;
  }

  body[data-r3][data-demo] #demo:not(.look) {
    position: relative;
    display: block;
    max-width: none;
    width: 100%;
    height: calc(872 * var(--r));
    margin: 0;
    padding: 0;
    overflow: visible;
    transition: transform 500ms cubic-bezier(0.45, 0, 0.55, 1);
  }

  /* The sticky header takes the top bar's place; the page moves down only by the difference (marketing, 8:37pm). */
  body[data-r3][data-demo] #demo:not(.look).r3-pushed {
    transform: translateY(calc(28 * var(--r)));
  }

  body[data-r3][data-demo] #demo:not(.look) > .hero {
    position: absolute;
    top: calc(14 * var(--r));
    left: 0;
    right: 0;
    max-width: none;
    margin: 0;
  }

  body[data-r3][data-demo] #demo:not(.look) > .hero h1 {
    font-size: calc(34 * var(--r));
    letter-spacing: -0.015em;
  }

  body[data-r3][data-demo] #demo:not(.look) > .hero p {
    max-width: none;
    margin-top: calc(6 * var(--r));
    font-size: calc(15 * var(--r));
  }

  /* The running sub-line from the first frame, in the setting-up line's place (marketing, 9:20pm). */
  body[data-r3][data-demo] #demo:not(.look) > .hero #sub {
    display: none;
  }

  body[data-r3][data-demo] #demo:not(.look) > .hero .r3-sub:not([hidden]) {
    display: block;
  }

  /* All demos is in the top bar from the first frame. */
  body[data-r3][data-demo] #demo:not(.look).first > .all {
    display: block;
  }

  /* The conversation grows up from the text box, as on a phone. */
  body[data-r3][data-demo] #demo:not(.look) .thread::before {
    content: "";
    margin-top: auto;
  }

  body[data-r3][data-demo] #demo:not(.look) .cue,
  body[data-r3][data-demo] #demo:not(.look) .ask,
  body[data-r3][data-demo] #demo:not(.look) .record,
  body[data-r3][data-demo] #demo:not(.look) .outline,
  body[data-r3][data-demo] #demo:not(.look) #left,
  body[data-r3][data-demo] #demo:not(.look) .bubble.intro,
  body[data-r3][data-demo] #demo:not(.look) .bubble .tag,
  body[data-r3][data-demo] #demo:not(.look) .example-tag,
  body[data-r3][data-demo] #demo:not(.look) #wait-hint,
  body[data-r3][data-demo] #demo:not(.look) .chrome .chip,
  body[data-r3][data-demo] .sticky {
    display: none !important;
  }

  /* All demos and the calm switch sit at the right of the top bar. */
  body[data-r3][data-demo] #demo:not(.look) > .all,
  body[data-r3][data-demo] #demo:not(.look) > .calm-switch {
    position: absolute;
    top: calc(-28 * var(--r));
    right: calc(50% - 600 * var(--r));
    margin: 0;
    transform: translateY(-50%);
    font-size: calc(14 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) > .all {
    right: calc(50% - 600 * var(--r) + 124 * var(--r));
  }

  /* The example's line shows only when it did not finish, in the step line's spot under the box. */
  body[data-r3][data-demo] #demo:not(.look) > .example {
    position: absolute;
    top: calc(634 * var(--r));
    left: calc(50% - 160 * var(--r));
    width: calc(740 * var(--r));
    margin: 0;
    justify-content: center;
    font-size: calc(15 * var(--r));
  }

  /* The texting phone: 330×640 at y 186, centred until it slides 405 to the left. */
  body[data-r3][data-demo] #demo:not(.look) > .chat {
    position: absolute;
    top: calc(130 * var(--r));
    left: calc(50% - 165 * var(--r));
    z-index: 3;
    width: calc(330 * var(--r));
    height: calc(640 * var(--r));
    max-height: none;
    margin: 0;
    border: calc(10 * var(--r)) solid var(--ink);
    border-radius: calc(46 * var(--r));
    transition: transform 600ms cubic-bezier(0.45, 0, 0.55, 1);
  }

  body[data-r3][data-demo] #demo:not(.look).r3-slid > .chat {
    transform: translateX(calc(-405 * var(--r)));
  }

  body[data-r3][data-demo] #demo:not(.look) .chat .head {
    height: calc(64 * var(--r));
    flex-direction: column;
    justify-content: center;
    gap: calc(3 * var(--r));
    padding: 0;
  }

  body[data-r3][data-demo] #demo:not(.look) .chat .avatar {
    width: calc(32 * var(--r));
    height: calc(32 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .chat .who {
    font-size: calc(13 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .thread {
    flex: 1 1 0;
    min-height: 0;
    gap: calc(8 * var(--r));
    padding: calc(6 * var(--r)) calc(14 * var(--r)) calc(10 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .bubble {
    max-width: 86%;
    animation: r3-up 400ms ease both;
  }

  body[data-r3][data-demo] #demo:not(.look) .bubble.placed {
    animation: none;
  }

  body[data-r3][data-demo] #demo:not(.look) .bubble p,
  body[data-r3][data-demo] #demo:not(.look) .bubble.linked .preview-link {
    font-size: calc(13.5 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .bubble p {
    padding: calc(8 * var(--r)) calc(11 * var(--r));
    border-radius: calc(16 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .bubble.sent p {
    border-bottom-right-radius: calc(4 * var(--r));
  }

  /* Stenzil's replies are plain lavender bubbles, each with its own time under it. */
  body[data-r3][data-demo] #demo:not(.look) .bubble.reply {
    padding-left: 0;
  }

  body[data-r3][data-demo] #demo:not(.look) .bubble.reply::before {
    display: none;
  }

  body[data-r3][data-demo] #demo:not(.look) .bubble.reply p {
    border-bottom-left-radius: calc(4 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .bubble.linked p {
    border-radius: calc(16 * var(--r)) calc(16 * var(--r)) 0 0;
  }

  body[data-r3][data-demo] #demo:not(.look) .bubble.linked .msg {
    position: relative;
    border-radius: calc(16 * var(--r)) calc(16 * var(--r)) calc(16 * var(--r)) calc(4 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .bubble.linked .preview-link {
    padding: 0 calc(11 * var(--r)) calc(8 * var(--r));
    border-radius: 0 0 calc(16 * var(--r)) calc(4 * var(--r));
    transition:
      background-color 100ms ease,
      transform 100ms ease;
  }

  /* The link shown being clicked: it presses for 0.3s under the pointer. */
  body[data-r3][data-demo] #demo:not(.look) .bubble.linked .preview-link.r3-press {
    background: #cdeaf1;
    transform: scale(0.95);
  }

  body[data-r3][data-demo] #demo:not(.look) .r3-pointer {
    position: absolute;
    z-index: 2;
    width: calc(26 * var(--r));
    height: calc(26 * var(--r));
    pointer-events: none;
    animation: r3-fade 200ms ease-out both;
    transition: transform 100ms ease;
  }

  body[data-r3][data-demo] #demo:not(.look) .r3-pointer.r3-press {
    transform: scale(0.85);
  }

  body[data-r3][data-demo] #demo:not(.look) .bubble.breathe .msg {
    animation: none;
  }

  body[data-r3][data-demo] #demo:not(.look) .receipt,
  body[data-r3][data-demo] #demo:not(.look) .bubble.sent:not(.unsent):has(~ .bubble.sent) .receipt {
    display: block;
    margin-top: calc(3 * var(--r));
    padding: 0 calc(2 * var(--r));
    font-size: calc(11 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .dock {
    gap: calc(8 * var(--r));
    padding: 0 calc(12 * var(--r)) calc(10 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .compose .hint {
    font-size: calc(11 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .field {
    align-items: center;
    gap: calc(6 * var(--r));
    border-radius: 999px;
    padding: calc(1 * var(--r)) calc(1 * var(--r)) calc(1 * var(--r)) calc(12 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .field textarea {
    field-sizing: fixed;
    height: calc(34 * var(--r));
    min-height: 0;
    padding: calc(8 * var(--r)) 0;
    font-size: calc(13 * var(--r));
    line-height: calc(18 * var(--r));
    overflow: hidden;
  }

  body[data-r3][data-demo] #demo:not(.look) .field button {
    width: calc(34 * var(--r));
    height: calc(34 * var(--r));
    transition:
      transform 100ms ease,
      background-color 100ms ease;
  }

  body[data-r3][data-demo] #demo:not(.look) .field button svg {
    width: calc(16 * var(--r));
    height: calc(16 * var(--r));
  }

  /* The send button presses as the example is sent: smaller and darker, for 0.3s. */
  body[data-r3][data-demo] #demo:not(.look) .field button.r3-press {
    transform: scale(0.84);
    background: #3b2fa8;
    color: #fff;
  }

  body[data-r3][data-demo] #demo:not(.look) .field .caret {
    top: 50%;
    bottom: auto;
    left: calc(13 * var(--r));
    height: calc(17 * var(--r));
    margin-top: calc(-8.5 * var(--r));
  }

  /* From the first paint the empty box shows its caret, never its placeholder, until the example is sent. */
  body[data-r3][data-demo]:not(.r3-typed) #demo:not(.look).first .field .caret[hidden] {
    display: block !important;
  }

  body[data-r3][data-demo]:not(.r3-sent) #demo:not(.look) .field textarea::placeholder {
    color: transparent;
  }

  body[data-r3][data-demo] #demo:not(.look) .pills .meanwhile,
  body[data-r3][data-demo] #demo:not(.look) .pills .label {
    margin: 0 0 calc(6 * var(--r));
    font-size: calc(12.5 * var(--r));
    color: #3e3a4f;
  }

  body[data-r3][data-demo] #demo:not(.look) .pills .row {
    flex-direction: column;
    align-items: flex-start;
    gap: calc(6 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .pill {
    max-width: 100%;
    min-height: 0;
    padding: calc(8 * var(--r)) calc(11 * var(--r));
    border: 1px dashed #a99cf0;
    border-radius: calc(12 * var(--r));
    background: #f4f2fd;
    color: #3b2fa8;
    font-weight: 400;
    font-size: calc(13 * var(--r));
  }

  /* While both screens are double-checked: the line and one suggestion slide up; after the change, the label and
     each suggestion slide in from the right with their label, a little apart. */
  body[data-r3][data-demo] #demo:not(.look) .chat.busy #pills-label,
  body[data-r3][data-demo] #demo:not(.look) .chat.busy .pills .pill:not(:first-child) {
    display: none;
  }

  body[data-r3][data-demo] #demo:not(.look) .chat.busy .pills :is(.meanwhile, .pill) {
    animation: r3-up 400ms ease both;
  }

  body[data-r3][data-demo] #demo:not(.look) .chat.busy .pills .pill {
    animation-delay: 200ms;
  }

  body[data-r3][data-demo] #demo:not(.look) .chat:not(.busy) .pills :is(.label, .pill) {
    animation: r3-right 400ms ease both;
  }

  body[data-r3][data-demo] #demo:not(.look) .chat:not(.busy) .pills .pill:nth-child(1) {
    animation-delay: 150ms;
  }

  body[data-r3][data-demo] #demo:not(.look) .chat:not(.busy) .pills .pill:nth-child(2) {
    animation-delay: 300ms;
  }

  body[data-r3][data-demo] #demo:not(.look) .chat:not(.busy) .pills .pill:nth-child(n + 3) {
    animation-delay: 450ms;
  }

  body[data-r3][data-demo] #demo:not(.look).r3-hold #pills {
    display: none !important;
  }

  /* "3 changes left. Try one of your own." under the phone, once the first change is done. */
  body[data-r3][data-demo] #demo:not(.look) > #r3-left {
    position: absolute;
    top: calc(782 * var(--r));
    left: calc(50% - 570 * var(--r));
    width: calc(330 * var(--r));
    margin: 0;
    color: var(--muted);
    font-size: calc(13 * var(--r));
    text-align: center;
    opacity: 0;
    transition: opacity 500ms ease;
  }

  body[data-r3][data-demo] #demo:not(.look).r3-turn > #r3-left {
    opacity: 1;
  }

  /* The step line under the box, centred on it, at y 690; the controls row takes its spot after the update. */
  body[data-r3][data-demo] #demo:not(.look) > .stepline {
    position: absolute;
    top: calc(634 * var(--r));
    left: calc(50% - 160 * var(--r));
    width: calc(740 * var(--r));
    max-width: none;
    min-height: 0;
    margin: 0;
    justify-content: center;
    gap: calc(4 * var(--r)) calc(10 * var(--r));
    font-size: calc(17 * var(--r));
    font-weight: 600;
    color: #3b2fa8;
  }

  body[data-r3][data-demo] #demo:not(.look) > .stepline .words {
    flex: none;
  }

  body[data-r3][data-demo] #demo:not(.look) > .stepline .name {
    color: #3b2fa8;
  }

  body[data-r3][data-demo] #demo:not(.look) > .stepline .clock {
    font-size: calc(15 * var(--r));
    font-weight: 400;
  }

  body[data-r3][data-demo] #demo:not(.look) > .stepline .hint {
    font-size: calc(13 * var(--r));
    font-weight: 400;
    text-align: center;
  }

  body[data-r3][data-demo] #demo:not(.look) > .stepline .icon {
    width: calc(22 * var(--r));
    height: calc(22 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look):not(.r3-steps) > .stepline {
    visibility: hidden;
  }

  /* The devices: placed on the page, out of the way of the texting phone's taps. */
  body[data-r3][data-demo] #demo:not(.look) .devices {
    position: absolute;
    inset: 0;
    z-index: 2;
    display: block !important;
    visibility: visible !important;
    padding: 0;
    pointer-events: none;
  }

  body[data-r3][data-demo] #demo:not(.look) .previews {
    position: static;
    padding: 0;
  }

  body[data-r3][data-demo] #demo:not(.look) .preview,
  body[data-r3][data-demo] #demo:not(.look) .done {
    pointer-events: auto;
  }

  /* Until the box is filled the previews take no room on screen and no taps. */
  body[data-r3][data-demo] #demo:not(.look):not(.r3-site) .preview[data-kind="computer"],
  body[data-r3][data-demo] #demo:not(.look):not(.r3-site) .preview[data-kind="phone"] {
    opacity: 0;
    pointer-events: none;
  }

  body[data-r3][data-demo] #demo:not(.look) .preview[data-kind="computer"] {
    position: absolute;
    top: calc(140 * var(--r));
    left: calc(50% - 160 * var(--r));
    z-index: 1;
    width: calc(740 * var(--r));
    --bar: calc(37 * var(--r));
    transition: opacity 600ms ease;
  }

  body[data-r3][data-demo] #demo:not(.look) .preview[data-kind="computer"] .stage {
    overflow: hidden;
    border: 1px solid #e2ded3;
    border-radius: calc(14 * var(--r));
    background: var(--card);
  }

  body[data-r3][data-demo] #demo:not(.look) .preview[data-kind="computer"] .chrome {
    position: relative;
    height: calc(37 * var(--r));
    gap: calc(5 * var(--r));
    padding: 0 calc(14 * var(--r)) calc(3 * var(--r));
    border: 0;
    border-bottom: 1px solid #e2ded3;
    border-radius: 0;
    background: linear-gradient(#f3f1ec 0 calc(34 * var(--r)), #e2ded3 0);
  }

  body[data-r3][data-demo] #demo:not(.look) .preview[data-kind="computer"] .chrome i {
    width: calc(9 * var(--r));
    height: calc(9 * var(--r));
    background: #d8d3c7;
  }

  body[data-r3][data-demo] #demo:not(.look) .preview[data-kind="computer"] .chrome .address,
  body[data-r3][data-demo] #demo:not(.look) .preview[data-kind="computer"] .chrome .address.named {
    flex: 1 1 auto;
    justify-content: center;
    height: auto;
    margin: 0 calc(39 * var(--r)) 0 calc(10 * var(--r));
    padding: 0;
    background: transparent;
    color: #3e3a4f;
    font-size: calc(12.5 * var(--r));
  }

  /* The load bar under the address: it runs once as the preview address opens. */
  body[data-r3][data-demo] #demo:not(.look) .preview[data-kind="computer"] .chrome::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 0;
    height: calc(3 * var(--r));
    background: var(--violet);
  }

  body[data-r3][data-demo] #demo:not(.look) .previews.r3-load .preview[data-kind="computer"] .chrome::after {
    animation: r3-load 800ms linear forwards;
  }

  body[data-r3][data-demo] #demo:not(.look) .preview[data-kind="computer"] .screen {
    border: 0;
    border-radius: 0;
    box-shadow: none;
  }

  /* A light dim of about 30%, under 0.4s, as the preview address loads; the site stays in sight (marketing, 9:20pm). */
  body[data-r3][data-demo] #demo:not(.look) .preview .stage::after {
    content: "";
    position: absolute;
    z-index: 3;
    background: var(--ink);
    opacity: 0;
    pointer-events: none;
  }

  body[data-r3][data-demo] #demo:not(.look) .preview[data-kind="computer"] .stage::after {
    inset: var(--bar) 0 0;
  }

  body[data-r3][data-demo] #demo:not(.look) .preview[data-kind="phone"] .stage::after {
    inset: var(--rim);
    border-radius: calc(20 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .previews.r3-veil .preview .stage::after {
    animation: r3-dim 350ms ease-in-out;
  }

  /* The new page swaps in at once under the dim: no crossfade, so the old and new pages are never drawn together. */
  body[data-r3][data-demo] #demo:not(.look) .screen iframe {
    transition: none;
  }

  /* The site's phone view, 172 wide, over the box's lower right at x 1124, y 336. */
  body[data-r3][data-demo] #demo:not(.look) .preview[data-kind="phone"] {
    position: absolute;
    top: calc(280 * var(--r));
    left: calc(50% + 404 * var(--r));
    right: auto;
    bottom: auto;
    z-index: 2;
    width: calc(172 * var(--r));
    --rim: calc(7 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .preview[data-kind="phone"] .screen {
    border-radius: calc(26 * var(--r));
    box-shadow: 0 calc(8 * var(--r)) calc(24 * var(--r)) rgb(29 27 46 / 0.25);
  }

  body[data-r3][data-demo] #demo:not(.look) .previews.hold-phone .preview[data-kind="phone"]:not(.up) {
    transition: opacity 500ms ease;
  }

  body[data-r3][data-demo] #demo:not(.look) .previews .badge {
    display: none;
    padding: calc(5 * var(--r)) calc(10 * var(--r));
    border-radius: calc(7 * var(--r));
    font-size: calc(12 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .previews .preview[data-kind="computer"] .badge {
    left: calc(14 * var(--r));
    top: calc(var(--bar) + 10 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look) .previews .preview[data-kind="phone"] .badge {
    padding: calc(3 * var(--r)) calc(6 * var(--r));
    font-size: calc(8 * var(--r));
  }

  body[data-r3][data-demo] #demo:not(.look).r3-site .previews.r3-check .preview[data-kind="computer"] .badge,
  body[data-r3][data-demo] #demo:not(.look) .previews.checking .preview[data-kind="phone"] .badge {
    display: block;
  }

  /* The ring holds about 4.5s, then fades to its faint marker. */
  body[data-r3][data-demo] #demo:not(.look) .ring {
    animation: r3-ring 5.6s ease-out forwards;
  }

  /* The controls row under the box, after the update. */
  body[data-r3][data-demo] #demo:not(.look) .done {
    position: absolute;
    top: calc(624 * var(--r));
    left: calc(50% - 160 * var(--r));
    flex-wrap: nowrap;
    width: calc(740 * var(--r));
    height: calc(44 * var(--r));
    min-height: 0;
    margin: 0;
    padding: 0;
    gap: calc(12 * var(--r));
    opacity: 0;
    visibility: hidden;
    transition:
      opacity 400ms ease,
      visibility 0s linear 400ms;
  }

  body[data-r3][data-demo] #demo:not(.look).r3-controls .done {
    opacity: 1;
    visibility: visible;
    transition: opacity 400ms ease;
  }

  body[data-r3][data-demo] #demo:not(.look) .done button {
    min-height: 0;
    padding: calc(9 * var(--r)) calc(16 * var(--r));
    font-size: calc(14 * var(--r));
  }

  /* The line the spark draws: out of the phone, round the box and back. */
  body[data-r3][data-demo] #demo:not(.look) > .r3-line {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 4;
    width: 100%;
    height: 100%;
    overflow: visible;
    pointer-events: none;
    transition: opacity 600ms ease;
  }

  body[data-r3][data-demo] #demo:not(.look) > .r3-line.out {
    opacity: 0;
  }

  .r3-line path {
    fill: none;
    stroke: var(--violet);
    stroke-linejoin: round;
  }

  .r3-line .spark {
    fill: #fff;
    stroke: #8b7cf6;
    filter: drop-shadow(0 0 6px rgb(139 124 246 / 0.75));
  }

  /* The sticky header: it slides down over the top bar after the change and stays at the top. */
  body[data-r3][data-demo] #r3-head {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 30;
    display: flex;
    align-items: center;
    gap: calc(28 * var(--r));
    height: calc(84 * var(--r));
    padding: 0 calc(120 * var(--r));
    background: #1f1a4d;
    color: #fff;
    transform: translateY(-100%);
    visibility: hidden;
    transition:
      transform 500ms cubic-bezier(0.45, 0, 0.55, 1),
      visibility 0s linear 500ms;
  }

  body[data-r3][data-demo] #r3-head.on {
    transform: none;
    visibility: visible;
    transition: transform 500ms cubic-bezier(0.45, 0, 0.55, 1);
  }

  body[data-r3][data-demo]:has(#demo[hidden]) #r3-head {
    display: none;
  }

  #r3-head .tile {
    flex: none;
    width: calc(40 * var(--r));
    height: calc(40 * var(--r));
    border-radius: calc(11 * var(--r));
    background: var(--mark) center / cover no-repeat;
  }

  #r3-head .words {
    display: flex;
    flex: 1;
    flex-direction: column;
    gap: calc(2 * var(--r));
    min-width: 0;
  }

  #r3-head .title {
    margin: 0;
    font-family: var(--display);
    font-weight: 700;
    font-size: calc(20 * var(--r));
    line-height: 1.2;
  }

  #r3-head .line {
    margin: 0;
    color: #c9c3f2;
    font-size: calc(13.5 * var(--r));
  }

  #r3-head .pill {
    display: flex;
    align-items: center;
    gap: calc(8 * var(--r));
    padding: calc(6 * var(--r)) calc(6 * var(--r)) calc(6 * var(--r)) calc(18 * var(--r));
    border-radius: 999px;
    background: #fff;
    color: var(--ink);
  }

  #r3-head .label {
    color: var(--muted);
    font-weight: 600;
    font-size: calc(12 * var(--r));
  }

  #r3-head .number {
    font-weight: 700;
    font-size: calc(18 * var(--r));
    font-variant-numeric: tabular-nums;
  }

  #r3-head .copy,
  #r3-head a.button {
    border: 0;
    border-radius: 999px;
    padding: calc(8 * var(--r)) calc(14 * var(--r));
    background: var(--teal-deep);
    color: #fff;
    font-weight: 600;
    font-size: calc(13 * var(--r));
    text-decoration: none;
    cursor: pointer;
  }

  #r3-head .scan {
    display: flex;
    align-items: center;
    gap: calc(10 * var(--r));
  }

  #r3-head .code {
    flex: none;
    width: calc(58 * var(--r));
    height: calc(58 * var(--r));
    border-radius: calc(8 * var(--r));
    background: #fff;
  }

  #r3-head .code svg {
    display: block;
    width: 100%;
    height: 100%;
    fill: var(--ink);
  }

  #r3-head .scan p {
    width: calc(70 * var(--r));
    margin: 0;
    color: #c9c3f2;
    font-size: calc(12 * var(--r));
    line-height: 1.3;
  }

  /* Placed at once, as after a reload or with less motion: nothing slides. */
  body[data-r3][data-demo] #demo.r3-now,
  body[data-r3][data-demo] #demo.r3-now *,
  body[data-r3][data-demo]:has(#demo.r3-now) #r3-head {
    transition: none !important;
  }

  :root.calm body[data-r3][data-demo] #demo:not(.look) .bubble,
  :root.calm body[data-r3][data-demo] #demo:not(.look) .pills * {
    animation: none;
  }
}

@keyframes r3-up {
  from {
    opacity: 0;
    transform: translateY(calc(14 * var(--r, 1px)));
  }
}

@keyframes r3-right {
  from {
    opacity: 0;
    transform: translateX(calc(240 * var(--r, 1px)));
  }
}

@keyframes r3-fade {
  from {
    opacity: 0;
  }
}

@keyframes r3-dim {
  30%,
  60% {
    opacity: 0.3;
  }
}

@keyframes r3-load {
  to {
    width: 100%;
  }
}

@keyframes r3-ring {
  0% {
    opacity: 0;
  }
  3% {
    opacity: 1;
  }
  80% {
    opacity: 1;
  }
  100% {
    opacity: 0.35;
  }
}
