/* Chirpedly landing page.
   Standalone: no app code, no framework, no shared tokens. Direction follows
   fish.audio (white ground, ink text, black pill buttons, 24px cards) with
   frosted-silk imagery in the brand blue (owner, 2026-09-11). Type follows
   elevenlabs.io: Waldenburg for display at weight 300, Figtree for everything
   else.

   Waldenburg is a licensed typeface and is not shipped here. The display stack
   names it first and renders Figtree until the file exists: license it, put the
   woff2 at site/fonts/Waldenburg-Buch.woff2, and uncomment the block below. */

/*
@font-face {
  font-family: "Waldenburg";
  src: url("fonts/Waldenburg-Buch.woff2") format("woff2");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
*/

:root {
  /* Chirpedly's colours, as the app resolves them (src/styles/astryx-theme.css
     over the Astryx neutral theme): brand ink and blue, true neutrals, white
     and #f1f1f1 as the two grounds. Colour lives on marks; text stays ink. */
  --bg: #ffffff;
  --ink: #0a0a0a;
  --ink-soft: #171717;
  --muted: #707070;
  --faint: #9b9b9b;
  --tile: #f1f1f1;
  --tile-deep: #e5e5e5;
  --line: rgba(0, 0, 0, .08);
  --white: #ffffff;
  --mark: #0073e6;
  /* The same value in channels, for translucent washes and rings: `rgba()`
     needs an alpha and a hex token cannot carry one. */
  --mark-rgb: 0, 115, 230;
  /* Hover for a solid brand surface. A blue primary darkens on hover where the
     yellow one lightened — the label on it is white now (see the band), and
     lightening would walk that toward the 4.5:1 floor rather than away. */
  --mark-deep: #0062c4;
  --font-display: Waldenburg, "Figtree", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --font-text: "Figtree", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --container: 1172px;
  --radius-card: 24px;
  --radius-tile: 20px;
  --nav-h: 64px;
  --ease: cubic-bezier(.2, .7, .2, 1);
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: 14px;
  line-height: 1.5;
  letter-spacing: 0.005em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-feature-settings: "kern", "liga", "cv11";
}
[hidden] { display: none !important; }
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
h1, h2, h3, h4 { margin: 0; font-family: var(--font-display); font-weight: 300; letter-spacing: -0.02em; }
p { margin: 0; }
ul { margin: 0; padding: 0; list-style: none; }
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; border-radius: 999px; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

.page { padding: 0 16px; }
.container { max-width: var(--container); margin: 0 auto; }

/* ---------- type scale ---------- */
.h1 { font-size: clamp(32px, 3.24vw, 47px); line-height: 1.08; }
.h2 { font-size: clamp(27px, 2.34vw, 34px); line-height: 1.16; }

/* NO ORPHANS (owner, 2026-09-11). A heading balances its lines rather than
   dropping one word onto the last; a paragraph never ends on a single word.
   Where a break has to be exact the markup binds it with a non-breaking
   space, because balancing is the browser's judgement and pinning is ours. */
/* `text-wrap` is inherited, so `pretty` is declared once on the body and
   reaches every caption and label, not only the elements someone listed. */
body { text-wrap: pretty; }
h1, h2, h3, h4, .h1, .h2 { text-wrap: balance; }
.lead { font-size: 14px; line-height: 1.55; color: var(--ink); }
.muted { color: var(--muted); }
.eyebrow { font-family: var(--font-text); font-size: 11.5px; letter-spacing: .12em; text-transform: uppercase; font-weight: 600; color: var(--ink); }
em, .italic { font-style: italic; }
strong { font-weight: 600; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  height: 44px; padding: 0 20px;
  border-radius: 999px;
  font-family: var(--font-text); font-size: 14px; font-weight: 500; line-height: 1;
  white-space: nowrap;
  transition: transform .18s var(--ease), background-color .18s var(--ease), box-shadow .18s var(--ease);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn .arrow { width: 14px; height: 14px; }
.btn-black { background: var(--ink); color: var(--white); }
.btn-black:hover { background: #262626; }
.btn-white { background: var(--white); color: var(--ink); box-shadow: 0 1px 2px rgba(0, 0, 0, .06), 0 0 0 1px rgba(0, 0, 0, .1); }
.btn-ghost { color: var(--ink); padding: 0 14px; }
.btn-ghost:hover { background: rgba(0, 0, 0, .05); }
.btn-sm { height: 36px; padding: 0 14px; font-size: 13px; }
.text-link { color: var(--muted); font-size: 14px; }
.text-link:hover { color: var(--ink); }

/* ---------- header ---------- */
/* The bar spans the viewport; what it holds sits in the same column as the
   content, so the logo and the buttons align with every section's edges. */
.header {
  position: sticky; top: 0; z-index: 40;
  padding: 0 16px;
  background: linear-gradient(to bottom, var(--bg) 40%, rgba(255, 255, 255, 0));
  transition: background-color .25s var(--ease), box-shadow .25s var(--ease);
}
/* Once the page has moved, the bar turns solid so content never runs under
   the links. */
.header.scrolled { background: rgba(255, 255, 255, .92); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); box-shadow: 0 1px 0 var(--line); }
.header-inner {
  max-width: var(--container); margin: 0 auto;
  height: var(--nav-h);
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
.brand { display: inline-flex; align-items: center; gap: 10px; font-family: var(--font-text); font-weight: 600; font-size: 14px; letter-spacing: -0.01em; }
/* The mark draws in `currentColor` (2026-09-11): it is the real logo now, a
   bare C rather than the black rounded square that carried its own ground, so
   every surface it lands on has to say what colour it is. Brand blue is the
   default because every surface here is white except the band, which overrides
   it below. 4.57:1 on white, which clears 1.4.11's 3:1 for a mark. */
/* `fill: currentColor` on the host as well as inside the symbol. What PAINTS is
   the shadow content, which takes the symbol's own `fill="currentColor"`; the
   <use> host keeps the initial black, which is never drawn but is what any
   inspection reads. Declaring it here makes the computed value agree with the
   pixel, so a contrast check cannot be fooled in either direction. */
.brand-mark { width: 30px; height: 30px; color: var(--mark); fill: currentColor; }
/* THE LOCKUP, from `assets/chirpedly-logo.svg` (2026-09-11). The header and the
   footer used to draw the mark with the word "Chirpedly" set beside it in the
   interface font; that word is the file's own wordmark now. Height only, and the
   width follows the viewBox, so nothing can stretch it: the lockup is 4.387 times
   wider than it is tall.

   Two colours, which is what lets a dark surface white the whole thing out: the
   mark half reads `--mark`, the wordmark inherits `currentColor`. On these white
   surfaces that is the official file exactly -- blue mark, ink wordmark.

   The mark's fill is declared on the <g> inside the symbol, as `var(--mark)`,
   and NOT as a rule here — a `<use>` renders the symbol into a shadow tree that
   an ordinary selector cannot reach, so `.brand-logo .logo-mark` matched nothing
   and the mark came out ink. Custom properties do inherit across that boundary,
   which is why the element can read the token even though a rule cannot set it.

   The viewBox is on the outer <svg> in the markup as well as on the symbol: with
   no viewBox an <svg> takes the replaced-element default of 300x150, so
   `width: auto` left the lockup 300px wide and the height did nothing. */
.brand-logo { height: 26px; width: auto; color: #111111; fill: currentColor; } /* the official wordmark ink */
.header-actions { display: flex; justify-content: flex-end; align-items: center; gap: 6px; }
.header-actions .header-link,
.header-actions .login { color: var(--muted); font-size: 14px; font-weight: 500; padding: 8px 14px; }
.header-actions .header-link:hover,
.header-actions .login:hover { color: var(--ink); }

/* ---------- hero ---------- */
/* The centred promise, then the three-step story on the brand silk. */
.hero {
  display: flex; flex-direction: column; align-items: center;
  text-align: center;
  padding: 72px 0 0;
}
.hero > .eyebrow { margin-bottom: 18px; color: var(--muted); }
/* The tagline is two sentences, one a line (owner, 2026-09-21: "Great conversations. Real
   outcomes."), and the break is typed in the markup, so the box sets no measure of its own. */
.hero .h1 { font-size: clamp(40px, 5.76vw, 83px); line-height: 1.02; letter-spacing: -0.03em; }
.hero-lead { margin-top: 26px; max-width: 640px; font-size: 16px; line-height: 1.55; color: var(--muted); }
.hero-cta { margin-top: 32px; display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; }
.hero-cta .btn { height: 48px; padding: 0 22px; }
.hero-note { margin-top: 16px; font-size: 13px; color: var(--muted); }
.hero-art {
  position: relative;
  width: 100%; margin-top: 64px;
  min-height: 440px;
  border-radius: var(--radius-card); overflow: hidden;
  background: var(--tile) center / cover no-repeat;
  padding: 48px 24px;
  display: flex; align-items: center; justify-content: center;
  text-align: left;
}
/* The frost. A white haze over the silk, heaviest at the top and the foot and
   thinnest behind the card, so the blue reads through the glass without
   competing with the words on it. */
.hero-art::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to bottom, rgba(255, 255, 255, .60) 0%, rgba(255, 255, 255, .28) 30%, rgba(255, 255, 255, .16) 62%, rgba(255, 255, 255, .36) 100%); pointer-events: none; }

/* ---------- hero: the three steps ---------- */
/* HOW IT WORKS, PLAYED (owner, 2026-09-13: "3 animated steps: user writes prompt,
   chirpedly presents the skill, the conversation between the agent the
   customer"). It replaces the one static exchange that sat on the silk.

   Each scene redraws a surface the product has, in the site's type: the New skill
   box and its Write it; the skill's guided fields in the editor's order (the name
   and Use when, a rule, then Flow, Rules and Reply); and the website chat, the
   customer on the brand blue and the AI agent on the tint, with the lookup between
   them as a tool call (owner, 2026-09-22: "like the actual tool response"). The
   reply says only what the Shopify order lookup returns: the status, the carrier
   and the carrier's expected date, never a day of its own.

   The scenes share one grid cell, so the card is as tall as its tallest scene and
   nothing beneath it moves when the step changes. Every scene is complete in the
   markup: script.js adds `is-animated` and hides what has not happened yet, so
   without the script, and under reduced motion, each step is read whole. */
/* 600px, not the exchange's 520: the bar above the card carries all three step
   names on one line, and it has to fit inside the card's width with room to spare. */
.story { position: relative; z-index: 1; width: 100%; max-width: 600px; display: flex; flex-direction: column; align-items: center; gap: 16px; }

/* The bar: Pause, then the steps. Solid white rather than frosted, so the muted
   labels keep their 4.95:1 whatever the silk behind them is doing. */
.story-bar { display: flex; align-items: center; gap: 4px; max-width: 100%; padding: 4px; border-radius: 999px; background: var(--white); box-shadow: 0 12px 32px -14px rgba(0, 0, 0, .3), 0 0 0 1px rgba(0, 0, 0, .04); }
/* Motion that starts by itself and runs past five seconds must be stoppable
   (WCAG 2.2.2). This is the control that does it, first in the bar so a keyboard
   reaches it before the steps. */
.story-toggle { flex: none; width: 32px; height: 32px; border-radius: 50%; display: grid; place-items: center; color: var(--ink); transition: background-color .18s var(--ease); }
.story-toggle:hover { background: var(--tile); }
.story-toggle svg { width: 12px; height: 12px; fill: currentColor; }
.story-play, .story.is-paused .story-pause { display: none; }
.story.is-paused .story-play { display: block; }
.story-steps { display: flex; gap: 2px; min-width: 0; }
.story-step { position: relative; display: inline-flex; align-items: center; gap: 7px; height: 32px; padding: 0 12px 0 6px; border-radius: 999px; font-size: 13px; font-weight: 500; color: var(--muted); white-space: nowrap; transition: background-color .25s var(--ease), color .25s var(--ease); }
.story-step:hover { color: var(--ink); }
.story-step[aria-selected="true"] { background: var(--tile); color: var(--ink); }
/* An outlined number, not a grey disc: the muted figure on #f1f1f1 would be
   4.47:1, under 1.4.3's 4.5:1, and on white it is 4.95:1. */
.story-num { flex: none; width: 20px; height: 20px; border-radius: 50%; display: grid; place-items: center; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12); font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; transition: background-color .25s var(--ease), color .25s var(--ease), box-shadow .25s var(--ease); }
.story-step[aria-selected="true"] .story-num { background: var(--ink); color: var(--white); box-shadow: none; }
/* How far through its step the story is. The brand blue is allowed here because
   the line is a mark, not text. */
.story-meter { position: absolute; left: 14px; right: 14px; bottom: 3px; height: 2px; border-radius: 2px; overflow: hidden; }
.story-meter span { display: block; height: 100%; background: var(--mark); transform: scaleX(0); transform-origin: left; }
.story:not(.is-animated) .story-meter { display: none; }

.story-card { width: 100%; display: grid; overflow: hidden; background: var(--white); border-radius: 16px; box-shadow: 0 30px 70px -20px rgba(0, 0, 0, .35), 0 0 0 1px rgba(0, 0, 0, .03); font-size: 14px; line-height: 1.5; }
.story-scene { grid-area: 1 / 1; min-width: 0; display: flex; flex-direction: column; opacity: 0; visibility: hidden; transform: translateY(6px); transition: opacity .2s var(--ease), transform .2s var(--ease), visibility 0s linear .2s; }
.story-scene.is-active { opacity: 1; visibility: visible; transform: none; transition: opacity .45s var(--ease) .12s, transform .45s var(--ease) .12s, visibility 0s; }
/* What has not happened yet is transparent and a few pixels low. A scene that
   comes round again is emptied under `is-reset`, for the one frame that takes, so
   it is never seen to empty. */
.story.is-animated [data-at] { transition: opacity .4s var(--ease), transform .4s var(--ease); }
.story.is-animated [data-at]:not(.is-on) { opacity: 0; transform: translateY(6px); }
.story-scene.is-reset [data-at], .story-scene.is-reset .story-write { transition: none; }
.story.is-paused .story-caret, .story.is-paused .story-dots i, .story.is-paused .story-busy { animation-play-state: paused; }

/* 1. The New skill box, asked the way the app asks it. */
.story-prompt { padding: 24px; }
.story-eyebrow { font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase; font-weight: 600; color: var(--muted); }
.story-question { margin-top: 6px; font-size: 18px; font-weight: 500; letter-spacing: -0.01em; line-height: 1.35; text-wrap: balance; }
.story-busy { display: block; height: 2px; margin: 12px 0 10px; border-radius: 2px; background: linear-gradient(90deg, transparent, var(--mark), transparent) -75% 0 / 40% 100% no-repeat, rgba(var(--mark-rgb), .14); animation: story-busy 1.1s linear infinite; }
@keyframes story-busy { from { background-position: -75% 0; } to { background-position: 175% 0; } }
.story:not(.is-animated) .story-busy { visibility: hidden; }
/* The sentence being typed. It sits in place, transparent, holding the lines the
   typed copy over it fills, so the box never changes size as it is written.
   Plain wrapping, not `pretty`: a paragraph balanced as it grows would move its
   words between lines with every letter. */
.story-field { position: relative; flex: 1; min-height: 104px; padding: 12px 14px; border: 1px solid rgba(0, 0, 0, .14); border-radius: 12px; text-wrap: wrap; }
.story.is-animated .story-text { color: transparent; }
.story-typed { position: absolute; inset: 12px 14px; }
.story:not(.is-animated) .story-typed { display: none; }
.story-caret { display: inline-block; width: 1.5px; height: 1.15em; margin-left: 1px; vertical-align: -0.2em; background: var(--ink); animation: story-blink 1.05s steps(1) infinite; }
.story-caret:not(.is-on) { visibility: hidden; }
@keyframes story-blink { 50% { opacity: 0; } }
.story-actions { display: flex; justify-content: flex-end; margin-top: 14px; }
/* Write it, then Writing: the app's own label, which says what it is doing. */
.story-write { display: inline-grid; place-items: center; height: 34px; padding: 0 16px; border-radius: 999px; background: var(--ink); color: var(--white); font-size: 13px; font-weight: 500; line-height: 1; transition: transform .15s var(--ease), background-color .2s var(--ease); }
.story-write > span { grid-area: 1 / 1; }
.story-write > span + span, .story-write.is-busy > span:first-child { visibility: hidden; }
.story-write.is-busy > span + span { visibility: visible; }
.story-write.is-pressed { transform: scale(.95); }
.story-write.is-busy { background: #3d3d3d; }

/* 2. The skill, in the guided editor's order. */
.story-skill { padding: 24px; }
.story-title { font-size: 20px; font-weight: 500; letter-spacing: -0.015em; line-height: 1.3; }
.story-doc { margin: 14px 0 0; display: grid; gap: 14px; }
.story-doc dt { font-size: 12.5px; font-weight: 500; color: var(--muted); }
.story-doc dd { margin: 2px 0 0; }
.story-doc ol { margin: 0; padding: 0; list-style: none; counter-reset: flow; }
.story-doc li { counter-increment: flow; display: grid; grid-template-columns: 20px 1fr; }
.story-doc li::before { content: counter(flow) "."; color: var(--muted); font-variant-numeric: tabular-nums; }
.story-flow { padding-top: 14px; border-top: 1px solid var(--line); }

/* 3. The website chat, as the widget draws it. */
.story-chat-head { flex: none; display: flex; align-items: center; gap: 8px; height: 52px; padding: 0 20px; background: var(--tile); border-bottom: 1px solid var(--line); font-size: 15px; font-weight: 500; }
.story-chat-mark { width: 18px; height: 18px; color: var(--mark); fill: currentColor; }
/* Under the business's name, as the real widget draws it: people are told up front that
   they are talking to an AI assistant (owner, 2026-09-23, D218). */
.story-chat-sub { display: block; font-size: 12.5px; font-weight: 400; line-height: 1.3; color: var(--ink-soft); }
.story-thread { flex: 1; display: flex; flex-direction: column; gap: 8px; padding: 16px 20px; }

.story-turn { display: grid; justify-items: start; align-items: start; }
.story-turn > * { grid-area: 1 / 1; }
.story-msg { max-width: 80%; padding: 8px 12px; border-radius: 12px 12px 12px 4px; background: var(--tile); }
.story-msg-customer { align-self: flex-end; border-radius: 12px 12px 4px 12px; background: var(--mark); color: var(--white); }
.story-dots { display: inline-flex; gap: 4px; padding: 14px 12px; border-radius: 12px 12px 12px 4px; background: var(--tile); }
.story-dots i { width: 6px; height: 6px; border-radius: 50%; background: var(--muted); animation: story-dot 1.2s ease-in-out infinite; }
.story-dots i:nth-child(2) { animation-delay: .15s; }
.story-dots i:nth-child(3) { animation-delay: .3s; }
@keyframes story-dot { 0%, 60%, 100% { opacity: .35; } 30% { opacity: 1; } }
.story:not(.is-animated) .story-dots { display: none; }
.story-composer { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 0 14px 14px; padding: 5px 5px 5px 16px; border: 1px solid var(--line); border-radius: 999px; box-shadow: 0 1px 1px rgba(0, 0, 0, .06), 0 2px 8px rgba(0, 0, 0, .06); color: var(--muted); font-size: 13.5px; }
.story-send { flex: none; width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; background: var(--mark); color: var(--white); opacity: .5; }
.story-send svg { width: 14px; height: 14px; }
/* The agent's lookup, drawn as the app draws a tool call (ChatToolCalls: a glyph and one
   line), with the fields shopify_lookup_order returns without the order's email: the
   status, the carrier and the carrier's expected date. Tracking needs the email. */
.story-tool { align-self: stretch; margin: 2px 0; padding: 10px 12px; border: 1px solid var(--line); border-radius: 12px; font-size: 13px; }
.story-tool-head { display: flex; align-items: center; gap: 8px; color: var(--ink-soft); font-weight: 500; }
.story-tool-head img { flex: none; width: 16px; height: 16px; }
.story-tool-name { display: grid; }
.story-tool-name > * { grid-area: 1 / 1; }
.story:not(.is-animated) .story-tool-busy { visibility: hidden; }
.story-tool-state { flex: none; display: grid; width: 16px; height: 16px; }
.story-tool-state > * { grid-area: 1 / 1; }
.story-spin { width: 14px; height: 14px; margin: 1px; border-radius: 50%; border: 2px solid rgba(var(--mark-rgb), .2); border-top-color: var(--mark); animation: story-spin .8s linear infinite; }
@keyframes story-spin { to { transform: rotate(360deg); } }
.story:not(.is-animated) .story-spin { display: none; }
.story.is-paused .story-spin { animation-play-state: paused; }
.story-check { width: 16px; height: 16px; color: var(--mark); }
.story-tool-result { display: flex; flex-wrap: wrap; gap: 4px 20px; margin: 8px 0 0 24px; }
.story-tool-result dt { font-size: 11.5px; color: var(--muted); }
.story-tool-result dd { margin: 0; color: var(--ink-soft); }

@media (max-width: 640px) {
  .story { gap: 12px; }
  /* A phone has room for one label, the step being played. The others keep their
     number, and their name for a screen reader; the bar spans the card, so it does
     not change width as the label does. */
  .story-bar { width: 100%; }
  .story-steps { flex: 1; }
  .story-step { padding: 0 6px; font-size: 12.5px; }
  .story-step[aria-selected="true"] { flex: 1; padding-right: 12px; }
  .story-step:not([aria-selected="true"]) .story-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .story-meter { left: 12px; right: 12px; }
  .story-prompt, .story-skill { padding: 18px; }
  .story-question { font-size: 16px; }
  .story-title { font-size: 18px; }
  .story-chat-head { padding: 0 16px; }
  .story-thread { padding: 14px 16px; }
  .story-composer { margin: 0 10px 10px; }
}
@media (prefers-reduced-motion: reduce) {
  .story-toggle, .story-step, .story-num, .story-scene, .story-scene.is-active { transition: none; }
}

/* ---------- sections ---------- */
.section { padding: 64px 0; }
.section-head { display: flex; align-items: center; justify-content: space-between; gap: 32px; margin-bottom: 40px; }
.section-head .h2 { max-width: 760px; }
.section-intro { max-width: 60ch; margin-top: 12px; color: var(--muted); font-size: 15px; line-height: 1.5; }

/* Several kinds of customer work, with specific supported examples. */
.examples { display: grid; grid-template-columns: repeat(3, 1fr); gap: 48px 40px; }
.example { padding-top: 24px; border-top: 1px solid var(--line); }
.example .example-app { display: flex; align-items: center; gap: 8px; margin: 0 0 12px; font-size: 13px; font-weight: 500; color: var(--muted); }
.example-app img { flex: none; width: 20px; height: 20px; object-fit: contain; border-radius: 5px; }
.example-mark { flex: none; width: 20px; height: 20px; padding: 3px; border-radius: 5px; background: rgba(var(--mark-rgb), .1); color: var(--mark); fill: currentColor; }
/* The six come in one after another, left to right and down, as the section does. */
@media (prefers-reduced-motion: no-preference) {
  #outcomes .example { opacity: 0; transform: translateY(12px); transition: opacity .6s var(--ease), transform .6s var(--ease); }
  #outcomes.in .example { opacity: 1; transform: none; }
  #outcomes.in .example:nth-child(2) { transition-delay: .08s; }
  #outcomes.in .example:nth-child(3) { transition-delay: .16s; }
  #outcomes.in .example:nth-child(4) { transition-delay: .24s; }
  #outcomes.in .example:nth-child(5) { transition-delay: .32s; }
  #outcomes.in .example:nth-child(6) { transition-delay: .4s; }
}
.example h3 { font-family: var(--font-text); font-size: 16px; font-weight: 500; letter-spacing: -0.01em; line-height: 1.4; }
.example p { margin-top: 10px; color: var(--muted); max-width: 42ch; }


/* the apps it works with, under the story (owner, 2026-09-21: "a section with carousel of
   logos show the connection we support", then "show all companies and have it 3 lines
   carousel so we can show volume"). Every app a customer can connect, each as its official
   logo and its name, in three rows: several of the vendors' icons are drawn on white, so the
   pill is white with a hairline rather than the grey tile, which would box them. Colour is the
   logo's own and the name stays ink. The rows stay inside the column and fade at both edges,
   so the loop never runs past the margin. Still (no script, or reduced motion), each row is
   its whole list, scrolled by hand. */
.apps .section-head { flex-direction: row; align-items: center; }
.apps-rows { display: grid; gap: 12px; }
.apps-row { padding: 2px 0; overflow-x: auto; }
.apps-list { display: flex; gap: 12px; width: max-content; }
.app { display: inline-flex; align-items: center; gap: 10px; height: 48px; padding: 0 20px 0 14px; border-radius: 999px; background: var(--white); box-shadow: 0 1px 2px rgba(0, 0, 0, .04), 0 0 0 1px rgba(0, 0, 0, .08); font-size: 15px; font-weight: 500; letter-spacing: -0.01em; white-space: nowrap; }
.app img { flex: none; width: 24px; height: 24px; object-fit: contain; border-radius: 6px; }
/* Moving: in each row the list and the copy script.js adds sit in one track that slides by
   exactly one of them, so the loop has no seam; the copy's own right padding is the gap
   between them. The middle row runs the other way. */
.apps.is-moving .apps-row { overflow: hidden; -webkit-mask-image: linear-gradient(90deg, transparent, #000 64px, #000 calc(100% - 64px), transparent); mask-image: linear-gradient(90deg, transparent, #000 64px, #000 calc(100% - 64px), transparent); }
.apps.is-moving .apps-track { display: flex; width: max-content; animation: apps-loop 240s linear infinite; }
.apps.is-moving .apps-row-back .apps-track { animation-direction: reverse; }
.apps.is-moving .apps-list { padding-right: 12px; }
.apps:not(.is-moving) .apps-list[aria-hidden] { display: none; }
/* Held by the toggle, and a row while a pointer rests on it to read a name. */
.apps.is-paused .apps-track, .apps-row:hover .apps-track { animation-play-state: paused; }
@keyframes apps-loop { to { transform: translateX(-50%); } }
/* The story's pause control, ringed here because it sits on the page, not in a white bar. */
.apps-toggle { flex: none; width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; color: var(--ink); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .12); transition: background-color .18s var(--ease); }
.apps-toggle:hover { background: var(--tile); }
.apps-toggle svg { width: 12px; height: 12px; fill: currentColor; }
.apps-play, .apps.is-paused .apps-pause { display: none; }
.apps.is-paused .apps-play { display: block; }

/* Phone calls: the copy, and a call on the hero's frosted silk */
.call-card { position: relative; z-index: 1; width: 100%; max-width: 420px; padding: 20px; border-radius: 16px; background: var(--white); box-shadow: 0 30px 70px -20px rgba(0, 0, 0, .35), 0 0 0 1px rgba(0, 0, 0, .03); font-size: 14px; line-height: 1.5; }
.call-head { display: flex; align-items: center; gap: 12px; padding-bottom: 16px; border-bottom: 1px solid var(--line); }
.call-avatar { flex: none; width: 40px; height: 40px; border-radius: 50%; display: grid; place-items: center; background: rgba(var(--mark-rgb), .1); color: var(--mark); }
.call-avatar svg { width: 20px; height: 20px; fill: currentColor; }
.call-name { font-size: 15px; font-weight: 500; }
.call-example { margin-left: 8px; font-size: 11px; font-weight: 400; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.call-live { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.call-wave { display: inline-flex; align-items: center; gap: 2px; height: 14px; }
.call-wave i { width: 3px; height: 100%; border-radius: 2px; background: var(--mark); transform: scaleY(.35); }
.call-lines { display: grid; gap: 12px; padding-top: 16px; }
.call-line b { display: block; font-size: 11.5px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
/* The agent's opening and the caller's question arrive as the call's first beat. */
.call-open { display: grid; gap: 12px; }
.call-tool { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border: 1px solid var(--line); border-radius: 12px; font-size: 13px; font-weight: 500; color: var(--ink-soft); }
.call-tool img { flex: none; width: 16px; height: 16px; }
.call-tool-state, .call-tool-name { display: grid; }
.call-tool-state > *, .call-tool-name > * { grid-area: 1 / 1; }
.call-tool-state { flex: none; width: 16px; height: 16px; }
.call-check { width: 16px; height: 16px; color: var(--mark); }
.call-spin { width: 14px; height: 14px; margin: 1px; border-radius: 50%; border: 2px solid rgba(var(--mark-rgb), .2); border-top-color: var(--mark); }
.call-spin, .call-tool-busy { visibility: hidden; }
/* The call plays once as the section comes in, and is still within five seconds, so it
   needs no pause control (WCAG 2.2.2): the agent's opening and the caller's question, the
   Shopify lookup turning from Checking to Checked, then the agent's answer, with the voice
   bars moving while it talks.
   Without motion it is the finished call, as the markup reads. */
@media (prefers-reduced-motion: no-preference) {
  #phone .call-line, #phone .call-tool { opacity: 0; transform: translateY(6px); transition: opacity .45s var(--ease), transform .45s var(--ease); }
  #phone.in .call-line, #phone.in .call-tool { opacity: 1; transform: none; }
  #phone.in .call-lines > :nth-child(1) { transition-delay: .5s; }
  #phone.in .call-lines > :nth-child(2) { transition-delay: 1.4s; }
  #phone.in .call-lines > :nth-child(3) { transition-delay: 3.2s; }
  #phone.in .call-spin { animation: story-spin .8s linear 1.4s 2, call-show 1.6s steps(1) 1.4s both; }
  #phone.in .call-tool-busy { animation: call-show 1.6s steps(1) 1.4s both; }
  #phone.in .call-check, #phone.in .call-tool-done { animation: call-hide 3s steps(1) both; }
  #phone.in .call-wave i { animation: call-wave .8s ease-in-out 3.2s 2; }
  #phone.in .call-wave i:nth-child(2) { animation-delay: 3.3s; }
  #phone.in .call-wave i:nth-child(3) { animation-delay: 3.4s; }
  #phone.in .call-wave i:nth-child(4) { animation-delay: 3.5s; }
  #phone.in .call-wave i:nth-child(5) { animation-delay: 3.6s; }
}
/* Shown only during its window, and hidden only until its moment. */
@keyframes call-show { 0% { visibility: visible; } 100% { visibility: hidden; } }
@keyframes call-hide { 0% { visibility: hidden; } 100% { visibility: visible; } }
@keyframes call-wave { 50% { transform: scaleY(1); } }

/* owner control: a plain list */
.control { display: grid; grid-template-columns: 1fr 1.4fr; gap: 48px; align-items: start; }
.control-list { border-top: 1px solid var(--line); }
.control-list li { padding: 18px 0; border-bottom: 1px solid var(--line); font-size: 16px; line-height: 1.5; color: var(--ink-soft); }

/* band */
/* The one coloured surface on the page: the brand colour, and WHITE on it.
   It carried ink while the brand was a pale yellow, where ink was about 14:1.
   The brand went blue on 2026-09-11 (#0073e6) and the same ink is 4.33:1 -- over
   1.4.3's 3:1 for the h2, which is large text, and under its 4.5:1 for anything
   smaller that lands here later. White is 4.57:1 and passes at every size, and
   it is what a saturated blue surface carries anywhere else in the industry, so
   the band does not depend on nothing small ever being added to it. */
.band { max-width: var(--container); margin: 40px auto 0; border-radius: var(--radius-card); background: var(--mark); color: var(--white); padding: 104px 24px; text-align: center; }
/* White on the brand blue, never ink: ink on #0073e6 is 4.33:1, under 1.4.3's
   4.5:1 for text this size. */
.band-lead { margin: 18px auto 0; max-width: 44ch; font-size: 16px; color: var(--white); opacity: .92; }
/* WHITE on the band, with the heading beneath it: the band's fill IS the brand
   colour, so a brand-coloured mark on it would be invisible. This is the same
   reason the sign-in screen's mark is white on the aurora. */
.band .brand-mark { width: 56px; height: 56px; margin: 0 auto 32px; color: var(--white); }
.band .h2 { font-size: clamp(31px, 3.06vw, 41px); }
.band .btn { margin-top: 36px; }

/* faq */
.faq-list { border-top: 1px solid var(--line); }
.faq { border-bottom: 1px solid var(--line); }
.faq summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 24px; padding: 24px 0; font-family: var(--font-text); font-size: 15px; font-weight: 500; letter-spacing: -0.01em; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary svg { width: 16px; height: 16px; flex: none; transition: transform .2s var(--ease); }
.faq[open] summary svg { transform: rotate(180deg); }
.faq .answer { padding: 0 0 24px; color: var(--muted); max-width: 90ch; }
.faq .answer a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }

/* footer */
.footer { padding: 72px 0 40px; }
.footer-bottom .brand { font-size: 16px; }
.footer-bottom .brand-logo { height: 30px; }
.footer-legal { margin-top: 28px; display: flex; flex-wrap: wrap; align-items: center; gap: 12px 20px; font-size: 14px; color: var(--ink-soft); }
.footer-legal .sep { width: 1px; height: 16px; background: var(--line); }
.footer-links { display: flex; flex-wrap: wrap; gap: 8px 20px; }
.footer-links a { padding: 4px 0; }
.footer-legal a:hover { text-decoration: underline; text-underline-offset: 3px; }
.footer-legal .note { color: var(--muted); }

/* ---------- inner pages: blog, posts, 404, legal ---------- */
.page-head { padding: 72px 0 40px; }
.page-head .h1 { font-size: clamp(32px, 4.14vw, 58px); line-height: 1.04; }
.page-head .lead { margin-top: 16px; color: var(--muted); max-width: 56ch; font-size: 16px; }
.post-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 40px; padding-bottom: 96px; }
.post-card { display: block; }
.post-card img { width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border-radius: var(--radius-tile); background: var(--tile); }
.post-card .meta { margin-top: 18px; font-size: 11.5px; letter-spacing: .12em; text-transform: uppercase; font-weight: 600; color: var(--muted); }
.post-card h2 { margin-top: 8px; font-family: var(--font-text); font-size: 20px; font-weight: 500; letter-spacing: -0.01em; line-height: 1.3; }
.post-card p { margin-top: 8px; color: var(--muted); }
.post-card .more { display: inline-flex; align-items: center; gap: 6px; margin-top: 12px; font-weight: 500; }
.post-card .more svg { width: 12px; height: 12px; }
.post { max-width: 720px; margin: 0 auto; padding: 64px 0 96px; }
.post .meta { font-size: 11.5px; letter-spacing: .12em; text-transform: uppercase; font-weight: 600; color: var(--muted); }
.post .h1 { margin-top: 12px; font-size: clamp(31px, 3.6vw, 47px); line-height: 1.06; }
.post .lead { margin-top: 18px; font-size: 17px; color: var(--muted); line-height: 1.5; }
.post .cover { margin: 36px 0; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; border-radius: var(--radius-card); background: var(--tile); }
.post .lead + .body { margin-top: 32px; }
.post .body { font-size: 16px; line-height: 1.65; color: var(--ink-soft); }
.post .body p { margin: 0 0 22px; }
.post .body h2 { margin: 40px 0 12px; font-family: var(--font-text); font-size: 22px; font-weight: 500; letter-spacing: -0.01em; color: var(--ink); }
.post .body ul, .post .body ol { margin: 0 0 22px; padding-left: 22px; list-style: disc; }
.post .body ol { list-style: decimal; }
.post .body li { margin-bottom: 8px; }
.post .body strong { color: var(--ink); }
.post .end { margin-top: 40px; padding-top: 28px; border-top: 1px solid var(--line); display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.legal .body h2 { font-size: 18px; }
.legal .body .fill { color: var(--muted); }
.notfound { min-height: calc(100svh - var(--nav-h) - 220px); display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; padding: 48px 0; }
.notfound .code { font-family: var(--font-display); font-weight: 300; font-size: clamp(99px, 16.2vw, 198px); line-height: .9; letter-spacing: -0.04em; background: url("/assets/step-2.jpg") center / cover; -webkit-background-clip: text; background-clip: text; color: transparent; }
.notfound .h1 { margin-top: 16px; font-size: clamp(25px, 2.7vw, 36px); }
.notfound p { margin-top: 12px; color: var(--muted); max-width: 46ch; }
.notfound .actions { margin-top: 28px; display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }
@media (max-width: 900px) { .post-grid { grid-template-columns: 1fr; gap: 32px; } .post { padding: 40px 0 72px; } }

/* login and signup: redirects, with a card for the moment before */
.auth { min-height: calc(100svh - var(--nav-h) - 160px); display: flex; align-items: center; justify-content: center; padding: 48px 0; }
.auth > div { width: 100%; max-width: 420px; }
.auth-card { display: block; background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-card); padding: 32px; box-shadow: 0 24px 60px -30px rgba(0, 0, 0, .2); }
.auth-card .brand-mark { width: 40px; height: 40px; }
.auth-card h1 { margin-top: 18px; font-size: 27px; }
.auth-card .btn { width: 100%; justify-content: center; margin-top: 22px; }

/* pricing */
.billing-toggle { margin-top: 24px; display: inline-flex; padding: 4px; border-radius: 999px; background: var(--tile); }
.billing-toggle button { height: 36px; padding: 0 16px; border-radius: 999px; font-size: 13px; font-weight: 500; color: var(--muted); display: inline-flex; align-items: center; gap: 8px; }
.billing-toggle button[aria-pressed="true"] { background: var(--white); color: var(--ink); box-shadow: 0 1px 2px rgba(0, 0, 0, .08); }
/* WHITE, NOT INK, and this pill is why the rule is worth stating: 11px
   uppercase is small text, 1.4.3 asks 4.5:1 of it, and ink on #0073e6 is
   4.33:1. White is 4.57:1. It was ink on pale yellow until 2026-09-11. */
.billing-toggle .save { font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; padding: 2px 8px; border-radius: 999px; background: var(--mark); color: var(--white); }
.plans { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin-top: 8px; }
.plan { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius-card); padding: 24px; display: flex; flex-direction: column; }
.plan .billed { margin-top: 6px; font-size: 12.5px; color: var(--muted); }
.plan.featured .billed { color: rgba(255, 255, 255, .7); }
.plan.featured { background: var(--ink); color: var(--white); border-color: var(--ink); }
.plan .name { font-size: 11.5px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; }
/* 34px four across: a yearly figure such as CA$124.17 and its "/ month" share one line in a
   card's 224px. Two across and on a phone there is room for 40px (the media queries below). */
.plan .price { margin-top: 14px; font-family: var(--font-display); font-weight: 300; font-size: 34px; letter-spacing: -0.02em; line-height: 1; }
.plan .price small { font-family: var(--font-text); font-size: 14px; letter-spacing: 0; color: var(--muted); margin-left: 8px; white-space: nowrap; }
.plan.featured .price small { color: rgba(255, 255, 255, .7); }
/* A card is the plan's name, price and who it is for, and nothing else (owner, 2026-09-26:
   the card's list repeated the comparison below it). The gap is the list's old one. */
.plan .for { margin: 12px 0 28px; color: var(--muted); font-size: 14px; }
.plan.featured .for { color: rgba(255, 255, 255, .75); }
.plan .btn { margin-top: auto; justify-content: center; }
/* The featured plan's call to action: a blue primary button, white label,
   darkening on hover. It was a yellow surface with an ink label lightening on
   hover, which is the right pair for a pale colour and the wrong one for a
   saturated one -- `.btn` is 14px, so 1.4.3 asks 4.5:1 and ink on #0073e6 gives
   4.33:1. White gives 4.57:1, and 5.9:1 on the hover. */
/* And so is the call to action on it. A blue fill on a black card is the same
   pairing as the ticks above; white carrying ink is what a primary button on a
   dark card is everywhere else, and it is 18.1:1 rather than 3.92:1. The white
   plans keep the blue button -- their ground is white, where blue belongs. */
.plan.featured .btn { background: var(--white); color: var(--ink); box-shadow: none; }
.plan.featured .btn:hover { background: var(--tile-deep); }
.pricing-note { margin-top: 20px; color: var(--muted); font-size: 14px; }
/* The one way past Growth: a line under the cards, not a fifth card. */
.pricing-contact { margin-top: 20px; text-align: center; font-size: 14px; color: var(--muted); }
.pricing-contact a { color: var(--ink); font-weight: 500; text-decoration: underline; text-underline-offset: 3px; }
/* Every row of the price book, under the cards that list only what a visitor chooses by. The
   table scrolls inside its own box at phone width, so the page itself never does. `relative`
   is what keeps that promise (2026-10-13): without it the table's `.sr-only` labels, which are
   absolutely positioned, escaped the box and widened the page to 530px on a 390px phone. */
.compare-section { margin-top: 40px; }
.compare-scroll { position: relative; overflow-x: auto; border: 1px solid var(--line); border-radius: var(--radius-card); background: var(--white); }
.compare { width: 100%; min-width: 640px; border-collapse: collapse; font-size: 14px; font-variant-numeric: tabular-nums; }
.compare th, .compare td { padding: 12px 16px; text-align: left; border-top: 1px solid var(--line); vertical-align: top; }
.compare thead th, .compare thead td { border-top: 0; font-size: 11.5px; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; }
.compare tbody th { font-weight: 500; color: var(--muted); white-space: nowrap; }
/* A thing a plan includes one of (its phone number) is a tick, in ink: colour lives on marks, and
   this one only says "included". */
.compare .tick { width: 16px; height: 16px; vertical-align: -3px; color: var(--ink); }
.faq .answer.fill { color: var(--muted); }
.legal .body h3 { margin: 22px 0 8px; font-family: var(--font-text); font-size: 15px; font-weight: 600; color: var(--ink); }
.legal .body a { text-decoration: underline; text-underline-offset: 3px; }
.post .end .muted { font-size: 13px; margin-right: auto; }
/* Four plans stay four across until a card is too narrow for its yearly price, then two by
   two, then one column. Four split evenly, so no plan sits alone on a row. */
@media (max-width: 1180px) { .plans { grid-template-columns: repeat(2, 1fr); } .plan .price { font-size: 40px; } }
@media (max-width: 640px) { .plans { grid-template-columns: 1fr; } }

/* reveal */
[data-reveal] { opacity: 0; transform: translateY(18px); transition: opacity .7s var(--ease), transform .7s var(--ease); }
[data-reveal].in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { [data-reveal] { opacity: 1; transform: none; transition: none; } }

/* Phone and SMS, on one line from the hero (owner, 2026-10-01). The line runs down the middle
   between each section's words and its card; each channel sits on it as a node, and the line
   fades in and out at its ends. Under 900px it runs down the left edge and everything stacks. */
.flow { position: relative; padding: 8px 0 24px; }
.flow::before { content: ""; position: absolute; left: 50%; top: 0; bottom: 20px; width: 2px; margin-left: -1px; background: linear-gradient(180deg, rgba(var(--mark-rgb), 0), rgba(var(--mark-rgb), .5) 56px, rgba(var(--mark-rgb), .5) calc(100% - 56px), rgba(var(--mark-rgb), 0)); }
.chan { position: relative; display: grid; grid-template-columns: 1fr 1fr; column-gap: 128px; align-items: center; padding: 72px 0; }
.chan-flip .chan-copy { order: 2; }
.chan-node { position: absolute; left: 50%; top: 50%; z-index: 1; width: 48px; height: 48px; margin: -24px 0 0 -24px; border-radius: 50%; display: grid; place-items: center; background: var(--mark); color: var(--white); box-shadow: 0 0 0 8px var(--white), 0 0 0 9px rgba(var(--mark-rgb), .25); }
.chan-node svg { width: 22px; height: 22px; }
.chan-eyebrow { font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase; font-weight: 600; color: var(--mark); }
.chan .h2 { margin-top: 10px; }
.chan-lead { margin: 18px 0 24px; max-width: 46ch; font-size: 16px; line-height: 1.55; color: var(--muted); }
.chan-try { margin-top: 20px; font-size: 15px; color: var(--ink-soft); }
.chan-try a { font-weight: 500; color: var(--mark); white-space: nowrap; }
.chan-try a:hover { text-decoration: underline; }
.chan-card { width: 100%; max-width: 440px; justify-self: center; }
.chan-card .call-card { max-width: none; }
.chan-skill { display: inline-flex; align-items: center; gap: 6px; margin-bottom: 12px; padding: 4px 10px; border-radius: 999px; background: rgba(var(--mark-rgb), .08); color: var(--mark); font-size: 12px; font-weight: 500; }
.chan-skill::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.sms-card { padding: 0; overflow: hidden; }
.sms-head { padding: 14px 20px; background: var(--tile); border-bottom: 1px solid var(--line); font-size: 12.5px; color: var(--muted); }
.sms-head b { display: block; font-size: 15px; font-weight: 500; color: var(--ink); }
.sms-thread { display: flex; flex-direction: column; gap: 8px; padding: 18px 20px 22px; }
.sms-msg { max-width: 82%; padding: 8px 12px; border-radius: 16px 16px 16px 4px; background: var(--tile); }
.sms-me { align-self: flex-end; border-radius: 16px 16px 4px 16px; background: var(--mark); color: var(--white); }
.sms-tool { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border: 1px solid var(--line); border-radius: 12px; font-size: 13px; font-weight: 500; color: var(--ink-soft); }
.sms-tool img, .sms-done { flex: none; width: 16px; height: 16px; }
.sms-done { color: var(--mark); }
.call-tool .call-wait { color: var(--muted); }
.sms-tool small { display: block; font-size: 12px; font-weight: 400; color: var(--muted); }
@media (prefers-reduced-motion: no-preference) {
  #sms .sms-thread > * { opacity: 0; transform: translateY(6px); transition: opacity .45s var(--ease), transform .45s var(--ease); }
  #sms.in .sms-thread > * { opacity: 1; transform: none; }
  #sms.in .sms-thread > :nth-child(2) { transition-delay: 1s; }
  #sms.in .sms-thread > :nth-child(3) { transition-delay: 2.2s; }
}
@media (max-width: 900px) {
  .flow::before { left: 24px; }
  .chan { grid-template-columns: 1fr; row-gap: 32px; padding: 56px 0 56px 72px; }
  .chan-flip .chan-copy { order: 0; }
  .chan-node { left: 24px; top: 56px; margin-top: 0; }
  .chan-card { justify-self: start; }
}
@media (max-width: 640px) {
  .flow::before { left: 16px; }
  .chan { padding-left: 44px; }
  .chan-node { left: 16px; width: 36px; height: 36px; margin-left: -18px; box-shadow: 0 0 0 6px var(--white), 0 0 0 7px rgba(var(--mark-rgb), .25); }
  .chan-node svg { width: 18px; height: 18px; }
}

/* ---------- responsive ---------- */
@media (max-width: 900px) {
  .hero { padding-top: 48px; }
  .hero-art { min-height: 0; margin-top: 48px; padding: 40px 16px; }
  .examples { grid-template-columns: 1fr; gap: 28px; }
  .control { grid-template-columns: 1fr; gap: 24px; }
  .section-head { flex-direction: column; align-items: flex-start; gap: 20px; }
  .band { padding: 80px 16px; }
}
@media (max-width: 640px) {
  body { font-size: 14px; }
  /* Pricing stays in the hero and the footer; the header keeps Log in and
     Start free, and there is no menu. */
  .header-actions { gap: 2px; }
  .header-actions .header-link { display: none; }
  .header-actions .login { padding: 8px 10px; }
  /* On a phone the size follows the width, so "Great conversations." keeps its line: it is
     nine of its own ems wide, and 40px would break it at 390. */
  .hero .h1 { font-size: min(40px, 9.1vw); }
  .hero-lead { font-size: 14px; }
  .hero-cta { width: 100%; flex-direction: column; }
  .hero-cta .btn { justify-content: center; }
  .section { padding: 48px 0; }
  .control-list li { font-size: 15px; }
  /* Smaller pills on a phone, so each row shows three apps rather than two and a half. */
  .apps-rows, .apps-list { gap: 8px; }
  .apps.is-moving .apps-list { padding-right: 8px; }
  .app { gap: 8px; height: 40px; padding: 0 14px 0 10px; font-size: 14px; }
  .app img { width: 20px; height: 20px; border-radius: 5px; }
  .apps.is-moving .apps-row { -webkit-mask-image: linear-gradient(90deg, transparent, #000 32px, #000 calc(100% - 32px), transparent); mask-image: linear-gradient(90deg, transparent, #000 32px, #000 calc(100% - 32px), transparent); }
}
