/* Axalus.ai — shared styles for every page
   Editorial, systems-led, premium B2B. White, near-black and one red,
   Onest throughout, thin-line node-and-connector diagrams, light
   heroes, a few red bands and an ink footer. Usage balance (brand guide,
   Colour): mostly white and light neutral, red on no more than a fifth of
   any page (About is the agreed exception), ink for text and the footer. */

:root {
  /* Red family (brand guide, Colour). Six named steps, each with one job.
     600 is Axalus Red: 5.8:1 with white, so it carries buttons, links, small
     text and display text alike. On ink it is only 3.3:1: fine for large
     text, dots, lines and focus rings, never small text (links on ink are
     white). 200 and 300 are decoration only, never text. */
  --red-50: #FFF0EF;         /* error field fill */
  --red-100: #FDE3E1;        /* Axalus's chat bubbles */
  --red-200: #FFBEB9;        /* light red lines and rings on white */
  --red-300: #F4A09C;        /* soft red in diagrams */
  --red-600: #CA171E;        /* Axalus Red */
  --red-700: #A81218;        /* hover, error text */

  /* Grey scale (brand guide, Colour). Warm greys, one step per job; never
     add a one-off grey, use the nearest step. The drawn phone's hardware
     greys are illustration and sit outside the scale. */
  --grey-0: #FFFFFF;
  --grey-25: #FAFAF9;        /* paper */
  --grey-50: #F6F6F4;        /* light neutral */
  --grey-100: #EDEDEA;       /* pressed, lit chips */
  --grey-150: #E8E8E6;       /* line, the customer's bubbles */
  --grey-200: #D5D5D2;       /* line, strong */
  --grey-300: #B5B5B1;       /* field hover, diagram dots */
  --grey-400: #A3A3A0;       /* diagram lines, text on ink */
  --grey-500: #8D8D8A;       /* quiet text on ink */
  --grey-600: #666666;       /* text, muted */
  --grey-700: #4A4A4A;       /* text, secondary */
  --grey-800: #2E2E2E;       /* lines on ink */
  --grey-900: #111111;       /* ink */

  /* Roles, named for what they do */
  --surface: var(--grey-0);
  --paper: var(--grey-25);   /* inset panels inside white cards */
  --tint: var(--grey-50);
  --line: var(--grey-150);
  --line-2: var(--grey-200);
  --ink: var(--grey-900);
  --ink-2: var(--grey-700);
  --ink-3: var(--grey-600);

  --accent: var(--red-600);
  --accent-2: var(--red-700); /* hover */
  --accent-line: var(--red-200);
  --bubble-in: var(--grey-150); /* the customer's messages */
  --bubble-out: var(--red-100); /* Axalus's messages */

  /* Colour roles across every diagram: red is Axalus responding (the system
     at work, the actions), black is a person taking over, white is the
     customer or the channel they use. Gaps, where things went quiet, are
     dashed and struck through; in the problem scenes they carry a light
     touch of red (red text and counts, the softest red fill) so the problem
     reads at a glance (user, 2026-10-17). */
  --gap: var(--red-600);
  --gap-soft: var(--red-50);

  --dark: var(--grey-900);
  --dark-2: var(--grey-900);
  --dark-line: var(--grey-800);
  --on-dark: var(--grey-50);
  --on-dark-2: var(--grey-400);
  --on-dark-3: var(--grey-500);

  --r-s: 8px;
  --r: 12px;
  --r-l: 16px;
  --r-xl: 20px;

  --shadow-1: 0 1px 2px rgba(17, 17, 17, .05), 0 1px 1px rgba(17, 17, 17, .02);
  --shadow-2: 0 1px 2px rgba(17, 17, 17, .04), 0 6px 16px -4px rgba(17, 17, 17, .08);
  --shadow-card: 0 0 0 1px rgba(17, 17, 17, .05), 0 1px 2px rgba(17, 17, 17, .06), 0 24px 48px -24px rgba(17, 17, 17, .22);   /* the content cards: problem, solution, stop, owns */
  --shadow-3: 0 2px 4px rgba(17, 17, 17, .03), 0 16px 36px -10px rgba(17, 17, 17, .12), 0 48px 96px -32px rgba(17, 17, 17, .16);

  --ease-out: cubic-bezier(.16, 1, .3, 1);
  /* iOS paging: quick off the mark, then a long settle the eye can follow.
     For a whole card sliding across the screen. */
  --ease-swipe: cubic-bezier(.32, .72, 0, 1);
  /* Type. One family, Onest (user, 2026-10-10; it replaced Mona Sans); a
     metric-matched Arial stands in while it
     loads, so lines don't reflow when it arrives. Four weights, each with
     one job: 400 text, 500 interface (buttons, links, nav, labels, chips),
     560 display (h1, h2 and every line set at 28px or more), 600 titles and
     emphasis. Display lines track in tighter than titles; text and interface
     are set as drawn. Every lead paragraph shares one size. */
  --font: "Onest", "Onest Fallback", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --w-ui: 500;
  --w-display: 560;
  --w-strong: 600;
  --track-display: -0.025em;
  --track-title: -0.015em;
  --fs-lead: clamp(1.0625rem, .95rem + .35vw, 1.25rem);
  --wrap: 1200px;
  --gutter: clamp(16px, 4vw, 32px);
  --nav-h: 90px;

  color-scheme: light;
}

/* ---------- Base ---------- */

/* Arial scaled to Onest's widths (measured on a long sentence: text 400
   against Arial 105.3%, display 560 against Arial Bold 100%), so lines
   don't reflow when Onest arrives. Onest's figures are plain (no slashed
   zero, no serifed 1), proportional by default, tabular on request. */
@font-face {
  font-family: "Onest Fallback";
  src: local("Arial"), local("ArialMT");
  font-weight: 400 500;
  size-adjust: 105.3%;
}
@font-face {
  font-family: "Onest Fallback";
  src: local("Arial Bold"), local("Arial-BoldMT");
  font-weight: 560 700;
  size-adjust: 100%;
}

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: calc(var(--nav-h) + 16px);
  scrollbar-color: var(--line-2) var(--surface);
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: 1.0625rem;
  line-height: 1.6;
  color: var(--ink);
  background: var(--surface);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  font-synthesis: none;
}

body.menu-open { overflow: hidden; }

::selection { background: var(--accent); color: #fff; }
.dark ::selection { background: var(--accent); color: #fff; }

::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--surface); }
::-webkit-scrollbar-thumb { background: var(--line-2); border: 3px solid var(--surface); border-radius: 99px; }
::-webkit-scrollbar-thumb:hover { background: var(--ink-3); }

h1, h2, h3 { margin: 0; font-weight: var(--w-display); letter-spacing: var(--track-display); line-height: 1.08; text-wrap: balance; }
p, ol, ul, dl, figure { margin: 0; }
b, strong { font-weight: var(--w-strong); }
a { color: inherit; }
img, svg { display: block; }
button { font: inherit; color: inherit; }

h2 { font-size: clamp(2rem, 1.2rem + 2.6vw, 3.25rem); line-height: 1.05; }

.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Filled icons (Phosphor, fill weight). */
.ic {
  width: 1em;
  height: 1em;
  flex: none;
  fill: currentColor;
}

.wrap {
  width: 100%;
  max-width: calc(var(--wrap) + var(--gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip {
  position: fixed;
  top: 12px; left: 12px;
  z-index: 100;
  padding: 10px 16px;
  border-radius: var(--r-s);
  background: var(--ink);
  color: #fff;
  font-size: .9375rem;
  text-decoration: none;
  transform: translateY(-160%);
  transition: transform .25s var(--ease-out);
}
.skip:focus { transform: none; }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 6px; }
.dark :focus-visible { outline-color: var(--accent); }

.nobr { white-space: nowrap; }

/* ---------- Brand ---------- */

.brand {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  border-radius: var(--r-s);
}
/* The Axalus logo (brand/ holds the masters and rules). Its knot and wordmark
   are never the same colour: red + ink on light, white + ink on red, red + white on dark. */
.axalus-logo {
  --logo-knot: var(--accent);
  --logo-word: var(--ink);
  display: block;
  height: 38.5px;
  width: auto;
  aspect-ratio: 465.22 / 121.99;
}
/* Phones: a slightly shorter header bar. */
@media (max-width: 760px) { :root { --nav-h: 80px; } }

/* ---------- Buttons & links ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5em;
  --btn-h: 44px;
  height: var(--btn-h);
  padding: 0 19px;
  border: 0;
  border-radius: 10px;
  font-size: .9375rem;
  font-weight: var(--w-ui);
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  position: relative;
  isolation: isolate;
  overflow: hidden;
  /* Hover-out: the fill colour lets go at once; the label switches back
     as the sinking fill uncovers it (about .48s in). */
  transition: color .12s linear .43s, background-color .33s linear;
}

/* Hover: the WhatsApp fill rise (user, 2026-10-09). Nothing scales, so the
   label never blurs or shifts. A wide oval of the fill colour waits just
   below the button; on hover it rises and swells (1s, slow in and out)
   until it covers the button. The label takes its on-fill colour in a
   quick .12s just as the fill crosses it (about .5s in; the curve starts slow),
   so it is never the same colour as what is behind it for long (user,
   2026-10-09); the button's own background follows at .5s, so no edge of
   the old colour shows. On leaving, the oval sinks back. The oval is sized
   from the button's height (WhatsApp's 167px oval on its 52px button), so
   every button, 44px or 52px tall, fills on exactly the same timing. Mouse only, so a
   tap never leaves a button filled. Each style sets its fill and the label
   colour on that fill (--btn-fill, --btn-on-fill). */
.btn::after {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  z-index: -1;
  width: 100%;
  min-width: calc(var(--btn-h) * 3.212);
  height: calc(var(--btn-h) * 3.212);
  border-radius: 50%;
  background: var(--btn-fill);
  transform: translate(-50%, calc(var(--btn-h) * 1.288)) scale(1);
  transition: transform 1s cubic-bezier(.66, 0, .34, 1);
  pointer-events: none;
}
@media (hover: hover) {
  .btn:hover:not(:disabled) {
    color: var(--btn-on-fill);
    background-color: var(--btn-fill);
    transition: color .12s linear .45s, background-color .33s linear .5s;
  }
  .btn:hover:not(:disabled)::after { transform: translate(-50%, 0) scale(1.47); }
}

.btn-primary {
  background: var(--accent);
  color: #fff;
  --btn-fill: var(--ink);
  --btn-on-fill: #fff;
}

/* No button has a border. The primary is the main action (Request a
   Discovery Call, one per view); the secondary is the background it sits
   on, one tone deeper. On light: red primary, ink-at-7% secondary (reads
   as Grey 100 on white, Grey 150 on light neutral). On ink: red primary,
   Grey 800 secondary. On red bands: both ink (user, 2026-10-09).
   Hover fills in ink, or in white where the button is ink or on ink. */
.btn-ghost {
  background: rgba(17, 17, 17, .07);
  color: var(--ink);
  --btn-fill: var(--ink);
  --btn-on-fill: #fff;
}
.dark .btn-primary { --btn-fill: #fff; --btn-on-fill: var(--ink); }
.dark .btn-ghost { background: var(--grey-800); color: var(--on-dark); --btn-fill: #fff; --btn-on-fill: var(--ink); }
.band-red .btn-primary { background: var(--ink); color: #fff; --btn-fill: #fff; --btn-on-fill: var(--ink); }
.band-red .btn-ghost { background: var(--ink); color: #fff; --btn-fill: #fff; --btn-on-fill: var(--ink); }

.btn-lg { --btn-h: 52px; padding: 0 25px; font-size: 1rem; border-radius: 12px; }


.link {
  display: inline-flex;
  align-items: center;
  gap: .4em;
  color: var(--accent);
  font-weight: var(--w-ui);
  text-decoration: none;
  text-underline-offset: 4px;
}
.link .ic { transition: transform .3s var(--ease-out); }
@media (hover: hover) {
  .link:hover { text-decoration: underline; text-decoration-thickness: 1px; }
  .link:hover .ic { transform: translateX(3px); }
}
.dark .link { color: #fff; }
/* Touch screens: a taller tap area than the line of text, without moving
   anything around it. */
@media (pointer: coarse) {
  .link { position: relative; }
  .link::before { content: ""; position: absolute; inset: -9px -6px; }
}

.actions { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 36px; }

/* ---------- Nav ---------- */

.nav {
  position: fixed;
  inset: 0 0 auto;
  z-index: 50;
  background: rgba(255, 255, 255, 0);
  border-bottom: 1px solid transparent;
  transition: border-color .3s, background-color .3s, -webkit-backdrop-filter .3s, backdrop-filter .3s;
}
/* main.js moves the nav with the page: scrolling down carries it off with
   the hero, as if part of it, and scrolling back up mid-page slides it in
   (.is-sliding). Without script it stays at the top. */
.nav.is-sliding { transition: transform .4s var(--ease-out), border-color .3s, background-color .3s, -webkit-backdrop-filter .3s, backdrop-filter .3s; }
@media (prefers-reduced-motion: reduce) { .nav.is-sliding { transition: none; } }
.nav.is-scrolled, body.menu-open .nav {
  background: rgba(255, 255, 255, .82);
  -webkit-backdrop-filter: saturate(1.6) blur(14px);
  backdrop-filter: saturate(1.6) blur(14px);
  border-bottom-color: var(--line);
}

/* The open menu is a solid light sheet, even over the dark hero. */
body.menu-open .nav { background: var(--surface); }

/* Over the red band the frosted white would tint pink, so it turns solid. */
.nav.is-solid.is-scrolled { background: var(--surface); }

/* Over a dark band (the hero, the closing CTA) the nav turns light-on-dark.
   main.js sets .is-dark from whatever band sits under the nav. */
.nav.is-dark.is-scrolled {
  background: rgba(17, 17, 17, .74);
  border-bottom-color: rgba(255, 255, 255, .08);
}
.nav.is-dark .axalus-logo { --logo-knot: var(--accent); --logo-word: #FFFFFF; }
.nav.is-dark .nav-links a { color: var(--on-dark-2); }
@media (hover: hover) { .nav.is-dark .nav-links a:hover { color: var(--on-dark); background: rgba(255, 255, 255, .07); } }
.nav.is-dark .nav-links a[aria-current="page"] { color: var(--on-dark); }
.nav.is-dark .nav-toggle { border-color: var(--dark-line); background: var(--dark-2); color: var(--on-dark); }
.nav.is-dark :focus-visible { outline-color: var(--accent); }


.nav-inner { display: flex; align-items: center; gap: 24px; height: var(--nav-h); padding-top: 6px; }

/* At the top of the page the bar sits 24px down (as on morclave.com) and
   scrolls off with the hero; slid back in mid-page (.is-scrolled), it sits
   at the edge with the frosted background. Desktop only. */
@media (min-width: 961px) {
  .nav-inner { transition: transform .2s cubic-bezier(.4, 0, .2, 1); }
  .js .nav:not(.is-scrolled) .nav-inner { transform: translateY(24px); }
}
@media (min-width: 961px) and (prefers-reduced-motion: reduce) {
  .nav-inner { transition: none; }
}

/* Right-aligned; the last link's text lines up with the page edge. */
.nav-links { display: flex; gap: 2px; margin-left: auto; margin-right: -12px; }
.nav-links a {
  padding: 8px 12px;
  white-space: nowrap;
  border-radius: var(--r-s);
  color: var(--ink-2);
  font-size: .9375rem;
  font-weight: var(--w-ui);
  text-decoration: none;
  transition: color .2s, background-color .2s;
}
@media (hover: hover) { .nav-links a:hover { color: var(--ink); background: var(--tint); } }
.nav-links a[aria-current="page"] { color: var(--accent); }

/* Holds the menu button, shown only where the links move into the menu. */
.nav-end { display: none; align-items: center; gap: 8px; }

.nav-toggle {
  display: none;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
}
.nav-toggle .ic { font-size: 20px; }
.nav-toggle { -webkit-tap-highlight-color: transparent; transition: transform .2s var(--ease-out); }
@media (hover: hover) { .nav-toggle:hover { transform: scale(1.04); } }
.nav-toggle:active { transform: scale(.95); transition-duration: .1s; }

.menu {
  position: absolute;
  inset: var(--nav-h) 0 auto;
  height: calc(100dvh - var(--nav-h));
  background: var(--surface);
  border-top: 1px solid var(--line);
  overflow-y: auto;
}
/* Opening settles in; closing is instant, so the page comes straight back. */
.menu:not([hidden]) { animation: menu-in .2s var(--ease-out); }
@keyframes menu-in { from { opacity: 0; transform: translateY(-6px); } }
.menu nav { display: flex; flex-direction: column; padding-block: 12px 32px; }
.menu nav a {
  padding: 16px 0;
  border-bottom: 1px solid var(--line);
  font-size: 1.25rem;
  font-weight: var(--w-ui);
  letter-spacing: var(--track-title);
  text-decoration: none;
}
.menu nav a[aria-current="page"] { color: var(--accent); }

/* ---------- Hero ---------- */

/* Every page opens on a hero that runs up behind the transparent nav (its
   height plus its 1px bottom border). Every hero is light grey, so the nav
   above it keeps the red knot and black wordmark. */
.hero {
  position: relative;
  overflow-x: clip;
  padding-top: calc(var(--nav-h) + 1px);
}

/* --H is the hero's height on desktop, nav included. */
.hero-top {
  --H: clamp(660px, 100svh, 900px);
  --copy: 600px;
  position: relative;
  display: flex;
  align-items: center;
  min-height: calc(var(--H) - var(--nav-h));
  padding-block: 24px 64px;
}

.hero-copy { position: relative; z-index: 1; }

.hero h1 {
  max-width: min(var(--copy), 10em);
  font-size: clamp(2.125rem, 1.3rem + 2.6vw, 3.875rem);
  font-weight: var(--w-display);
  line-height: 1.06;
  letter-spacing: var(--track-display);
  text-wrap: pretty;
}

/* The grey hero (--tint, the palette's light grey) with a hairline where it
   meets the page. Headline in ink, subline in the grey that keeps AA on
   it; the buttons are the standard red primary and tonal secondary. */
.hero-grey { background: var(--tint); border-bottom: 1px solid var(--line); }
.hero-grey .hero-sub { color: var(--ink-2); }

.hero-sub {
  /* Wide enough that the top line is the longer one (fitted for Mona Sans
     at 31.5em for "…systems that make customer"; still holds in Onest). */
  max-width: 32em;
  margin-top: clamp(20px, 2vw, 28px);
  color: var(--on-dark-2);
  font-size: var(--fs-lead);
  line-height: 1.65;
  text-wrap: pretty;
}

@media (max-width: 1180px) {
  .hero-top { --copy: 560px; }
}

/* Side by side, every hero's headline sits the same distance below the nav
   (140px; a little less on short screens), with whatever sits beside it
   top-aligned to it. The hero's content starts level with the logo's foot. */
@media (min-width: 1024px) {
  .hero-top { --hero-gap: clamp(120px, 17.5svh, 140px); align-items: flex-start; padding-top: var(--hero-gap); }
  .hero-top .sol-hero-grid { align-items: start; }
}

@media (max-width: 1023px) {
  .hero-top { flex-direction: column; align-items: stretch; min-height: 0; padding-block: clamp(32px, 7vw, 56px) 8px; }
  /* Phones and tablets: heroes run flush to the bottom of the band. */
  .hero-grey .hero-top { padding-bottom: 0; }
}

/* ---------- Home hero: the phone ----------
   Copy on the left; on the right a customer's phone, drawn in CSS, rising from the foot of the band with one text conversation on it
   (main.js picks one of ten and plays it once). Side by side, the phone
   hangs from the headline's cap height and the band's foot cuts it (see
   the min-width: 1024px block below). Stacked, it stands on the band's
   foot and runs past it by --hph-crop. */
/* Clipped, so the phone ends at the band's foot. */
.home-hero { overflow: clip; }
/* "can respond." is kept whole, so the lines step down. */
.home-hero.sol-hero h1 { max-width: 10.4em; }
.home-hero .hero-top { align-items: stretch; }
.hph-col {
  --hph-w: clamp(300px, calc((var(--H) - 150px) * .4615), 350px);
  --hph-crop: max(40px, calc(var(--hph-w) * 2.1667 - var(--H) / 2 - 204px));
  align-self: end;
  justify-self: center;
  margin: 0 0 calc(-1 * var(--hph-crop));
}

.hph {
  position: relative;
  width: var(--hph-w);
  aspect-ratio: 9 / 19.5;
  padding: calc(var(--hph-w) * .034);
  border-radius: calc(var(--hph-w) * .17);
  background: #151515;
  box-shadow:
    inset 0 0 0 1.5px #474747,
    inset 0 0 0 4px #0a0a0a,
    0 2px 6px rgba(17, 17, 17, .14),
    0 50px 90px -30px rgba(17, 17, 17, .38);
}
.hph-btn { position: absolute; width: 3px; background: #2a2a2a; }
.hph-btn-action, .hph-btn-up, .hph-btn-down { left: -3px; border-radius: 2px 0 0 2px; }
.hph-btn-power { right: -3px; top: 26%; height: 11.5%; border-radius: 0 2px 2px 0; }
.hph-btn-action { top: 16.5%; height: 4.4%; }
.hph-btn-up { top: 24%; height: 7.6%; }
.hph-btn-down { top: 33.5%; height: 7.6%; }

.hph-screen {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
  border-radius: calc(var(--hph-w) * .137);
  background: #fff;
  color: var(--ink);
}
.hph-island {
  position: absolute;
  left: 50%;
  top: calc(var(--hph-w) * .03);
  z-index: 2;
  width: calc(var(--hph-w) * .31);
  height: calc(var(--hph-w) * .09);
  border-radius: 999px;
  background: #000;
  transform: translateX(-50%);
}
.hph-status {
  display: flex;
  justify-content: space-between;
  align-items: center;
  height: calc(var(--hph-w) * .15);
  padding: 0 calc(var(--hph-w) * .085) 0 calc(var(--hph-w) * .1);
  font-size: 15px;
  font-weight: var(--w-strong);
  letter-spacing: -.01em;
  /* The clock ticks as messages arrive: fixed-width figures, as on a phone. */
  font-variant-numeric: tabular-nums;
}
.hph-sys { display: flex; align-items: center; gap: 6px; }
.hph-sys svg { fill: currentColor; }

.hph-head {
  position: relative;
  display: grid;
  justify-items: center;
  gap: 5px;
  padding: 2px 16px 10px;
  border-bottom: 1px solid var(--line);
  background: var(--paper);
}
.hph-back { position: absolute; left: 16px; top: 13px; color: var(--accent); }
.hph-avatar {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: linear-gradient(var(--grey-300), var(--grey-500));
  color: #fff;
  font-size: 17px;
  font-weight: var(--w-strong);
  letter-spacing: .02em;
}
.hph-name { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: var(--w-ui); line-height: 1.2; }
.hph-name svg { color: var(--ink-3); }

/* The customer's messages on the right in the customer grey, the
   business's on the left in the light red, as in every chat on the site. */
.hph-msgs {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0;
  padding: 10px 12px 12px;
  list-style: none;
  font-size: 15px;
  line-height: 1.35;
}
.hph-day { margin: 2px 0 6px; color: var(--ink-3); font-size: 11px; line-height: 1.3; text-align: center; }
.hph-msg, .hph-typing { max-width: 78%; padding: 8px 13px; border-radius: 18px; }
.hph-me { align-self: flex-end; border-bottom-right-radius: 5px; background: var(--bubble-in); }
.hph-biz { align-self: flex-start; border-bottom-left-radius: 5px; background: var(--bubble-out); }
/* A change of speaker gets a little more room. It is marked in the markup
   (and by main.js), not with sibling selectors: the typing bubble sits in
   the list too and would shift the spacing as it comes and goes. Every
   reply follows a customer message, so the typing bubble always gets it. */
.hph-turn, .hph-typing { margin-top: 6px; }
/* Each message's time sits at the end of its last line. */
.hph-at { float: right; margin: 5px -3px -2px 10px; color: var(--ink-3); font-size: 11px; line-height: 1.2; white-space: nowrap; }

.hph-typing { display: none; gap: 4px; align-items: center; padding: 13px 14px; }
.hph-typing.is-on { display: flex; animation: hph-in .3s var(--ease-out) both; }
.hph-typing i { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); opacity: .35; animation: hph-dot 1s ease-in-out infinite; }
.hph-typing i:nth-child(2) { animation-delay: .15s; }
.hph-typing i:nth-child(3) { animation-delay: .3s; }
@keyframes hph-dot { 30% { opacity: 1; transform: translateY(-2px); } 60% { opacity: .35; transform: none; } }

/* While playing, a message shows once it has arrived. */
.hph-msgs.is-playing .hph-msg:not(.is-in) { display: none; }
.hph-me { transform-origin: 100% 100%; }
.hph-biz { transform-origin: 0 100%; }
.hph-msg.is-in { animation: hph-in .42s cubic-bezier(.34, 1.3, .64, 1) both; }
@keyframes hph-in { from { opacity: 0; transform: translateY(6px) scale(.9); } }

.hph-bar { display: flex; align-items: center; gap: 8px; margin-top: auto; padding: 8px 12px 30px; }
.hph-plus { display: grid; place-items: center; flex: none; width: 32px; height: 32px; border-radius: 50%; background: var(--tint); color: var(--ink-3); font-size: 20px; line-height: 1; }
.hph-field { flex: 1; padding: 7px 14px; border: 1px solid var(--line-2); border-radius: 18px; color: var(--ink-3); font-size: 15px; line-height: 1.2; }
.hph-home { position: absolute; left: 50%; bottom: 8px; width: 36%; height: 5px; border-radius: 3px; background: var(--ink); transform: translateX(-50%); }

/* Short laptop screens: a touch smaller, so the longest chats keep some
   room under their last message. */
@media (min-width: 960px) and (max-height: 760px) {
  .hph-msgs { gap: 5px; font-size: 14px; }
  .hph-head { padding-bottom: 8px; }
}
/* Side by side, the copy is top-aligned under the nav, and the phone's top
   edge lines up with the headline's cap height (Onest's caps start .157em
   into the 1.06 line). It runs on past the band's foot, which clips it;
   the large negative bottom margin keeps it from making the hero taller. */
@media (min-width: 1024px) {
  .hph-col { align-self: start; margin: calc(.157 * clamp(2rem, 1.3rem + 2.6vw, 3.875rem)) 0 -1000px; }
  /* At least ~535px of phone shows, so the longest chats keep about 30px
     under their last message; short screens make the band a little taller. */
  .home-hero .hero-top { min-height: max(calc(var(--H) - var(--nav-h)), calc(var(--hero-gap) + 545px)); }
}
@media (max-width: 959px) {
  /* Stacked: the phone follows the buttons, and the band's foot cuts it
     just below the conversation: about 550px of phone shows at any width
     (narrower phones wrap more, so they show more of the phone). */
  .hero.home-hero.sol-hero .hero-top { padding-bottom: 0; }
  .hph-col { --hph-w: min(320px, 86vw); --hph-crop: max(0px, calc(var(--hph-w) * 2.1667 - 550px)); margin-top: 48px; }
}
@media (max-width: 380px) {
  .hph-msgs { font-size: 14px; }
}
/* Mobile hero: larger headline, each headline sentence on its own line,
   and the phone hidden. Desktop keeps the inline sentences and the phone. */
@media (max-width: 760px) {
  .home-hero.sol-hero h1 { font-size: 40px; line-height: 1.04; max-width: none; margin-top: 1.25rem; }
  .home-hero h1 .h1-sentence { display: block; text-wrap: balance; }
  .home-hero.sol-hero .hero-sub { margin-top: 1.5rem; }
  .hero.home-hero.sol-hero .hero-top { padding-bottom: 3.5rem; }
  .home-hero h1 .h1-sentence + .h1-sentence { margin-top: .4em; }
  .home-hero .hph-col { display: none; }
}
/* Every page's hero headline is the same size on phones. */
@media (max-width: 760px) {
  .hero.hero-grey h1 { font-size: 40px; margin-top: 1.25rem; }
  /* The home page's headline is larger. */
  .hero.hero-grey.home-hero h1 { font-size: 46px; }
  /* The contact page's hero starts 8px lower, so its headline needs 8px less. */
  .hero.hero-grey.dc-hero h1 { margin-top: calc(1.25rem - 8px); }
}

/* First load: the copy settles in line by line (Home and Solutions) and
   Home's phone rises from the band's foot (the hero clips it). Once only,
   never on scroll; main.js starts the conversation when the phone has
   landed. What sits beside the copy follows it in each page's own block
   (Solutions' stops, How We Work's phase index, Technology's mix;
   Industries' questions and About's card rows arrive on their own). */
@media (prefers-reduced-motion: no-preference) {
  .js :is(.home-hero, .solutions-hero, .hww-hero, .tech-hero, .ind-hero, .about-hero) .sol-hero-text > * { animation: hero-in .7s var(--ease-out) both; }
  .js :is(.home-hero, .solutions-hero, .hww-hero, .tech-hero, .ind-hero, .about-hero) .sol-hero-text > :nth-child(2) { animation-delay: 60ms; }
  .js :is(.home-hero, .solutions-hero, .hww-hero, .tech-hero, .ind-hero, .about-hero) .sol-hero-text > :nth-child(3) { animation-delay: 120ms; }
  .js :is(.home-hero, .solutions-hero, .hww-hero, .tech-hero, .ind-hero, .about-hero) .sol-hero-text > :nth-child(4) { animation-delay: 180ms; }
  .js .home-hero .hph { animation: hph-rise .9s var(--ease-out) .1s both; }
}
@keyframes hero-in { from { opacity: 0; transform: translateY(10px); } }
@keyframes hph-rise { from { opacity: 0; transform: translateY(56px); } }

/* ---------- Chat primitives ----------
   Shared by the worked example's phone and the diagrams' step lists. */

.wires {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.phone-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid var(--line);
}
.phone-who strong { display: block; font-size: .875rem; font-weight: var(--w-strong); line-height: 1.3; }
.phone-who span { display: block; color: var(--ink-3); font-size: .75rem; line-height: 1.3; }
/* The chat reads like WhatsApp: header with avatar and call buttons, a
   patterned wallpaper, bubbles with a tail on the first of each run, the
   time (and ticks on sent messages) tucked into the bubble, centred system
   notices, and the message bar. */
.phone-msgs {
  display: flex;
  flex: 1;
  min-height: 0;
  flex-direction: column;
  justify-content: flex-end;
  gap: 6px;
  padding: 14px 16px;
  list-style: none;
  overflow: hidden;
  background: var(--grey-50) radial-gradient(circle at 1px 1px, rgba(17, 17, 17, .07) 1px, transparent 0) 0 0 / 14px 14px;
}

.msg {
  position: relative;
  flex: none;
  max-width: 84%;
  padding: 6px 9px 7px;
  border-radius: 8px;
  box-shadow: 0 1px .5px rgba(17, 17, 17, .13);
  font-size: .8125rem;
  line-height: 1.45;
  text-wrap: pretty;
}
/* Same colours as the cards: the customer in light grey, Axalus in light red. */
.msg-in { align-self: flex-start; background: var(--bubble-in); color: var(--ink); }
.msg-out { align-self: flex-end; background: var(--bubble-out); color: var(--ink); }
.msg-in:not(.msg-in + .msg-in) { margin-top: 4px; border-top-left-radius: 0; }
.msg-out:not(.msg-out + .msg-out) { margin-top: 4px; border-top-right-radius: 0; }
.msg-in:not(.msg-in + .msg-in)::before,
.msg-out:not(.msg-out + .msg-out)::before {
  content: "";
  position: absolute;
  top: 0;
  width: 8px;
  height: 12px;
  background: inherit;
}
.msg-in:not(.msg-in + .msg-in)::before { left: -7px; clip-path: polygon(0 0, 100% 0, 100% 100%); }
.msg-out:not(.msg-out + .msg-out)::before { right: -7px; clip-path: polygon(0 0, 100% 0, 0 100%); }
.msg-time {
  float: right;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  margin: 7px -2px -3px 12px;
  color: var(--ink-3);
  font-size: .6875rem;
  line-height: 1;
  white-space: nowrap;
}
.msg-time .ic { color: var(--accent); font-size: 15px; }
.msg-quote {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 0 -3px 6px;
  padding: 6px 8px;
  border-left: 3px solid var(--accent);
  border-radius: 5px;
  background: rgba(17, 17, 17, .05);
  color: var(--ink-2);
  font-size: .75rem;
}
.msg-quote .ic { flex: none; color: var(--ink-3); font-size: 14px; }
.msg-day {
  align-self: center;
  margin-bottom: 4px;
  padding: 4px 10px;
  border-radius: 7px;
  background: var(--surface);
  color: var(--ink-3);
  font-size: .6875rem;
  font-weight: var(--w-ui);
  letter-spacing: .04em;
  text-transform: uppercase;
}
.msg-sys {
  align-self: center;
  max-width: 88%;
  padding: 5px 11px;
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink-2);
  text-align: center;
  font-size: .75rem;
  font-weight: var(--w-ui);
}
.msg-sys .ic { display: inline-block; margin-right: 6px; color: var(--accent); font-size: 14px; vertical-align: -2px; }
.is-new { animation: rise .45s var(--ease-out) both; }
.msg-in.is-new { transform-origin: 0 100%; }
.msg-out.is-new { transform-origin: 100% 100%; }
@keyframes rise { from { opacity: 0; transform: translateY(8px) scale(.96); } }


/* ---------- Sections ---------- */

.section { padding-block: clamp(96px, 11vw, 152px); }

.section-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 32px; margin-bottom: clamp(40px, 5vw, 64px); }
.section-head h2 { max-width: 21ch; }

.lead { margin-top: 20px; color: var(--ink-2); font-size: var(--fs-lead); line-height: 1.55; text-wrap: pretty; }

/* ---------- Problem ---------- */

.problem-grid {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(40px, 6vw, 96px);
  align-items: start;
}
.problem-head { position: sticky; top: calc(var(--nav-h) + 48px); }
/* A longer statement than the other section headings: sized to its column so
   it always breaks into the same four phrases. */
.problem-head { container-type: inline-size; }
.problem-head h2 { max-width: none; font-size: clamp(2rem, 1.25rem + 2.1vw, 2.875rem); font-size: clamp(2rem, 9.6cqi, 2.875rem); }

.incidents { display: grid; gap: 16px; container-type: inline-size; }
/* Bigger screens: more room between the stories (phones set their own gap below). */
@media (min-width: 761px) { .incidents { gap: 64px; } }
.problem-pin { display: contents; }

/* Phones (main.js adds .is-stack): the three stories are a sticky stack. Each
   card pins in the vertical centre of the screen (equal room above and below)
   and the next one slides up over it and covers it completely. All cards share
   the tallest card's height (--card-h). Without script (or with reduced motion) they are a
   plain list. */
@media (max-width: 760px) {
  .problem-grid.is-stack { display: block; }
  .is-stack .problem-head { margin-bottom: 32px; }
  /* The space between cards is a flex gap, not a margin: a sticky card has to keep
     its margin box inside the stack, so a margin would send it away early, before
     the last card has covered it. */
  .is-stack .incidents { display: flex; flex-direction: column; gap: 300px; container-type: normal; }
  .is-stack .incident {
    position: sticky;
    top: max(calc(var(--nav-h) + 12px), calc((100svh - var(--card-h, 0px)) / 2));
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 20px;
    height: var(--card-h, auto);
  }
  /* A card stacking onto the one before it has no shadow, so the stacked
     cards' shadows don't add up (main.js adds .is-stacked). */
  .is-stack .incident { transition: box-shadow .25s var(--ease-out); }
  .is-stack .incident.is-stacked { box-shadow: none; }
  /* The story sits at the top, its illustration under it, and a summary strip
     at the foot. */
  .is-stack .incident-copy { flex: none; }
  .is-stack .frag { flex: 1; min-height: 0; }
  .is-stack .frag-sum { margin-top: auto; }
  /* Order update: the four steps share whatever room the card has. */
  .is-stack .loop { flex: 1; grid-auto-rows: minmax(52px, 1fr); }
  .is-stack .loop li { height: auto; }
  .is-stack .sheet-row { min-height: 30px; padding-block: 3px; }
}

.incident {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.12fr);
  gap: clamp(20px, 3vw, 36px);
  align-items: center;
  padding: clamp(20px, 2.4vw, 28px);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}
/* The story starts at the top of the card, level with its illustration. */
.incident-copy { order: -1; display: grid; gap: 6px; align-self: start; }
.incident-copy p { font-size: 1.125rem; line-height: 1.5; text-wrap: pretty; }
.incident-copy p + p { color: var(--ink-2); }
/* In a narrow column (about 1000–1250px wide screens) the story sits above
   its illustration, so the chat, loop and table keep their full width. */
@container (max-width: 639px) {
  .incident { grid-template-columns: minmax(0, 1fr); }
}

.frag {
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--paper);
  font-size: .8125rem;
  line-height: 1.4;
}

.frag-timeline { display: flex; flex-direction: column; gap: 14px; padding: 0; border: 0; border-radius: 0; background: none; }
.tl-chat { display: flex; flex-direction: column; gap: 10px; padding: 14px; border: 1px solid var(--line); border-radius: 14px; background: var(--paper); }
.is-stack .tl-chat { flex: 1; }
.tl-msg { display: grid; justify-items: start; gap: 5px; max-width: 84%; }
.tl-msg.is-out { align-self: flex-end; justify-items: end; }
.tl-meta { display: inline-flex; align-items: center; gap: 10px; padding-inline: 4px; color: var(--ink-3); font-size: .75rem; }
.bubble {
  display: inline-flex;
  align-items: flex-start;
  gap: 7px;
  max-width: 100%;
  padding: 7px 11px;
  border-radius: 12px;
}
.bubble .ic { margin-top: 1px; color: var(--ink-3); font-size: 15px; }
/* The customer writes in light grey, Axalus answers in light red; a person
   on the business side, before Axalus, answers in plain white. */
.bubble-in { background: var(--bubble-in); color: var(--ink); border-bottom-left-radius: 4px; }
.bubble-out { border: 1px solid var(--line-2); background: var(--surface); color: var(--ink); border-bottom-right-radius: 4px; }
.bubble-late { color: var(--ink-2); }
.tl-status { display: inline-flex; align-items: center; gap: 6px; color: var(--gap); font-size: .75rem; font-weight: var(--w-ui); }
.tl-status::before { content: ""; width: 7px; height: 7px; border: 1.5px solid var(--gap); border-radius: 50%; }
.tl-gap {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-block: 4px;
  color: var(--gap);
  font-size: .75rem;
  font-weight: var(--w-ui);
}
.tl-gap::before, .tl-gap::after { content: ""; flex: 1; border-top: 1.5px dashed var(--gap); }

/* Order update and renewal sit straight on the card, without the inset
   panel: the steps (or the sheet) on top, a summary strip underneath. */
.frag-loop,
.frag-sheet { display: flex; flex-direction: column; gap: 14px; padding: 0; border: 0; border-radius: 0; background: none; }

/* The four steps, joined by a dashed line from icon to icon, and a bracket
   that carries the last step back round to the first. */
.loop { position: relative; display: grid; gap: 10px; padding: 0 30px 0 0; list-style: none; }
.loop li {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  height: 52px;
  padding: 0 14px 0 8px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  color: var(--ink);
  font-size: .875rem;
  white-space: nowrap;
}
/* Drawn from the previous step's icon to this one; the icons sit on top. */
.loop li + li::before {
  content: "";
  position: absolute;
  top: calc(-50% - 10px);
  left: 25px;
  height: calc(100% + 10px);
  border-left: 1.5px dashed var(--line-2);
}
.loop-ic { position: relative; z-index: 1; display: grid; flex: none; place-items: center; width: 36px; height: 36px; border-radius: 50%; background: var(--tint); }
.loop-ic .ic { color: var(--ink-3); font-size: 16px; }
/* From the middle of the first step to the middle of the last (four equal
   rows, three 10px gaps). */
.loop::after {
  content: "";
  position: absolute;
  top: calc((100% - 30px) / 8);
  bottom: calc((100% - 30px) / 8);
  right: 8px;
  width: 14px;
  border: 1.5px solid var(--line-2);
  border-left: 0;
  border-radius: 0 12px 12px 0;
}

/* The summary strip: an icon, the count, and what it counts. */
.frag-sum {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px 8px 8px;
  border-radius: 12px;
  background: var(--gap-soft);
  color: var(--ink-3);
  font-size: .8125rem;
  line-height: 1.3;
}
.sum-ic { display: grid; flex: none; place-items: center; width: 38px; height: 38px; border-radius: 50%; background: var(--red-100); }
.sum-ic .ic { color: var(--gap); font-size: 18px; }
.sum-n { flex: none; color: var(--gap); font-size: 1.875rem; font-weight: var(--w-strong); letter-spacing: var(--track-title); line-height: 1; white-space: nowrap; }
.sum-note { display: grid; gap: 1px; min-width: 0; }
.sum-note b { color: var(--gap); font-size: 1rem; line-height: 1.25; }
/* The renewals strip leads with what it counts; the count sits at the end. */
.sum-note + .sum-n { margin-left: auto; padding-right: 6px; }

/* One set of columns for every row (subgrid): the last three sized to their
   longest entry, the customer name takes the rest, and every gap is equal. */
.sheet {
  display: grid;
  grid-template-columns: minmax(0, 1fr) repeat(3, auto);
  column-gap: 7px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface);
  overflow: hidden;
  font-variant-numeric: tabular-nums;
}
.sheet-row {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  align-items: center;
  min-height: 34px;
  padding: 5px 9px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.sheet-row:last-child { border-bottom: 0; }
.sheet-row span { overflow: hidden; text-overflow: ellipsis; }
.sheet-headrow { background: var(--tint); color: var(--ink-3); font-size: .75rem; font-weight: var(--w-ui); }
.sheet-miss { background: var(--grey-100); color: var(--ink-2); }
.sheet-miss s { color: var(--gap); text-decoration-thickness: 1.5px; }
.miss-tag { justify-self: start; padding: 2px 6px; border-radius: 99px; background: var(--red-100); color: var(--red-700); font-size: .75rem; font-weight: var(--w-strong); }
/* An empty cell: no reminder set. */
.sheet-nil::before { content: ""; display: inline-block; width: 10px; border-top: 1.5px solid var(--line-2); vertical-align: middle; }
/* The narrowest phones drop the Plan column, so no name is cut off. */
@media (max-width: 359px) {
  .sheet { grid-template-columns: minmax(0, 1fr) repeat(2, auto); }
  .sheet-row > :nth-child(2) { display: none; }
}

/* Phones: each story's outcome plays once, the first time its card is the
   one in the centre (main.js adds .is-played). The setup is always there, so
   no card ever arrives (or peeks in at the edge) empty: the first message,
   the four steps, the sheet. What plays is what goes wrong: the eleven hours
   open up and the replies come too late, the loop closes back round and
   the count lands, the missed renewals turn red one by one. Without
   .is-stack (no script, reduced motion, wider screens) nothing waits. */
@media (max-width: 760px) {
  .is-stack .incident:not(.is-played) .tl-chat > .tl-msg:nth-child(n + 3) { opacity: 0; transform: translateY(6px) scale(.96); }
  .is-stack .incident:not(.is-played) .frag-sum { opacity: 0; transform: translateY(8px); }
  .is-stack .incident:not(.is-played) .tl-gap { opacity: 0; }
  .is-stack .incident:not(.is-played) .tl-gap::before { clip-path: inset(0 0 0 100%); }
  .is-stack .incident:not(.is-played) .tl-gap::after { clip-path: inset(0 100% 0 0); }
  .is-stack .incident:not(.is-played) .loop::after { clip-path: inset(100% 0 0 0); }
  .is-stack .incident:not(.is-played) .sheet-miss { background-color: transparent; }
  .is-stack .incident:not(.is-played) .sheet-miss s { color: inherit; text-decoration-color: transparent; }
  .is-stack .incident:not(.is-played) .miss-tag { opacity: 0; transform: scale(.85); }

  .is-stack .incident.is-played :is(.tl-msg, .tl-gap, .frag-sum, .miss-tag) {
    transition: opacity .3s var(--ease-out) var(--d, 0s), transform .45s var(--ease-out) var(--d, 0s);
  }
  /* The gap's dashes draw outward from "11 hours"; the bracket draws up,
     from the last step back round to the first. (An explicit inset(0):
     clip-path can't animate to none.) */
  .is-stack .incident.is-played .tl-gap::before,
  .is-stack .incident.is-played .tl-gap::after { clip-path: inset(0); transition: clip-path .45s var(--ease-out) var(--d, 0s); }
  .is-stack .incident.is-played .loop::after { clip-path: inset(0); transition: clip-path .5s cubic-bezier(.77, 0, .175, 1) var(--d, 0s); }
  .is-stack .incident.is-played .sheet-miss { transition: background-color .35s var(--ease-out) var(--d, 0s); }
  .is-stack .incident.is-played .sheet-miss s { transition: color .35s var(--ease-out) var(--d, 0s), text-decoration-color .35s var(--ease-out) var(--d, 0s); }

  /* Each reply grows from its speaker's corner; the tag from its left. */
  .frag-timeline .tl-msg { transform-origin: 0 100%; }
  .frag-timeline .tl-msg.is-out { transform-origin: 100% 100%; }
  .miss-tag { transform-origin: 0 50%; }

  /* The beats: quick, so the outcome lands as the card does. */
  .tl-chat > .tl-gap { --d: .1s; }
  .tl-chat > :nth-child(3) { --d: .4s; }
  .tl-chat > :nth-child(4) { --d: .65s; }
  .frag-timeline .frag-sum { --d: .95s; }
  .loop { --d: .1s; }
  .frag-loop .frag-sum { --d: .5s; }
  .sheet-miss:nth-child(1 of .sheet-miss) { --d: .1s; }
  .sheet-miss:nth-child(2 of .sheet-miss) { --d: .17s; }
  .sheet-miss:nth-child(3 of .sheet-miss) { --d: .24s; }
  .sheet-miss:nth-child(4 of .sheet-miss) { --d: .31s; }
  .sheet-miss:nth-child(5 of .sheet-miss) { --d: .38s; }
  .frag-sheet .frag-sum { --d: .55s; }
}

/* Gaps → the three moments, handled */

.gaps { margin-top: clamp(80px, 10vw, 136px); }
.gaps-stage { text-align: center; }
.gaps-lead {
  max-width: 20.4em;
  margin-inline: auto;
  font-size: clamp(1.25rem, 1rem + 1.1vw, 1.875rem);
  font-weight: var(--w-ui);
  line-height: 1.3;
  letter-spacing: var(--track-title);
  text-wrap: pretty;
}

/* The turn of the page: the gaps above are grey and quiet, the answer is
   the brand red. */
.gaps-close {
  margin-top: clamp(16px, 2vw, 24px);
  color: var(--accent);
  font-size: clamp(3rem, 2.4rem + 5.2vw, 5rem);
  font-weight: var(--w-display);
  line-height: 1.02;
  letter-spacing: var(--track-display);
  text-wrap: balance;
}

/* The three moments above, handled: the same message, answered in the same
   minute, and what came of it. Every card reads the same way, top to bottom:
   the name of the moment, the exchange, the result. */
.fixes {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  margin-top: clamp(40px, 5vw, 64px);
}
.fix {
  display: grid;
  grid-row: span 3;
  grid-template-rows: subgrid;
  row-gap: 14px;
  padding: 20px 20px 22px;
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  background: var(--surface);
  box-shadow: var(--shadow-card);
}
.fix h3 { font-size: 1rem; font-weight: var(--w-strong); letter-spacing: var(--track-title); line-height: 1.3; }

.fix-thread {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px;
  border: 1px solid var(--line);
  border-radius: 14px;
  background: var(--paper);
  font-size: .8125rem;
  line-height: 1.4;
  list-style: none;
}
.fix-thread li { display: grid; justify-items: start; gap: 5px; max-width: 90%; }
.fix-thread .is-sys { align-self: flex-end; justify-items: end; }
.bubble-sys { background: var(--bubble-out); color: var(--ink); border-bottom-right-radius: 4px; }
.fix-meta { padding-inline: 4px; color: var(--ink-3); font-size: .75rem; }
.fix-meta b { color: var(--accent-2); }

.fix-result {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: 10px;
  align-content: start;
  padding-inline: 2px;
}
.fix-result .ic { grid-row: span 2; margin-top: 1px; color: var(--accent); font-size: 20px; }
.fix-result strong { font-size: .9375rem; line-height: 1.4; text-wrap: pretty; }
.fix-result span { color: var(--ink-3); font-size: .8125rem; line-height: 1.45; }

/* The gaps sequence. Without script, or with reduced motion, it is static:
   the two lines, then the cards. main.js turns it into one pinned run
   (.is-seq): the gaps line grows on a blank screen, fades into "We close
   these gaps.", which rises to the top and stays while the three moments
   come up from below one by one. Where the three cards fit on one screen
   (.is-full) they rise into the pinned screen; on phones they follow in the
   page and pass under the pinned line (.gaps-band keeps it clear). */
.gaps.is-seq { margin-top: clamp(24px, 4vw, 48px); overflow-x: clip; }
/* Sized to the small viewport (a phone's toolbars showing), as main.js lays
   the run out on it, so nothing shifts as the toolbars slide in and out. */
.gaps.is-seq .gaps-stage { position: sticky; top: 0; z-index: 2; height: 100vh; height: 100svh; pointer-events: none; }
.gaps.is-seq .gaps-stage > .wrap { position: relative; height: 100%; }
.gaps.is-seq .gaps-lead,
.gaps.is-seq .gaps-close {
  position: absolute;
  inset: 0;
  height: fit-content;
  margin: auto;
}
/* A comfortable measure for the line on its blank screen. */
.gaps.is-seq .gaps-lead { max-width: min(20.4em, 68%); }
.gaps.is-seq .gaps-close { opacity: 0; }
.gaps-band { display: none; }
/* A line break used on phones only. */
.m-br { display: none; }
/* Phones: the two lines share one style, and "We close these gaps." is a
   step bigger. With the scroll sequence on (.is-phone) the two lines take the
   same place, the second replacing the first (main.js). No growth here. */
@media (max-width: 760px) {
  .gaps-lead,
  .gaps.is-seq .gaps-lead { max-width: 100%; padding-inline: 16px; }
  .gaps-lead-a,
  .gaps-lead-b {
    display: block;
    font-size: 2rem;
    font-weight: var(--w-display);
    line-height: 1.15;
    letter-spacing: var(--track-display);
    text-wrap: balance;
  }
  .gaps-lead-b { margin-top: 12px; }
  .gaps.is-seq.is-phone .gaps-lead { display: grid; align-items: center; }
  .gaps.is-seq.is-phone .gaps-lead-a,
  .gaps.is-seq.is-phone .gaps-lead-b { grid-area: 1 / 1; margin-top: 0; }
  .gaps-close { font-size: 3.25rem; }
  .m-br { display: inline; }
}
.gaps.is-seq:not(.is-full) .gaps-band {
  display: block;
  position: absolute;
  inset: 0 0 auto;
  height: var(--band-h, 0);
  background: var(--surface);
}
/* Cards fade out as they pass under the line instead of being cut. */
.gaps.is-seq:not(.is-full) .gaps-band::after {
  content: "";
  position: absolute;
  inset: 100% 0 auto;
  height: 40px;
  background: linear-gradient(var(--surface), rgba(255, 255, 255, 0));
}

.gaps.is-seq .gaps-cards { position: relative; z-index: 1; margin-top: var(--text-dist, 0); }
.gaps.is-full .gaps-cards {
  position: sticky;
  top: 0;
  z-index: 3;
  height: 100vh;
  height: 100svh;
  margin-top: -100vh;
  margin-top: -100svh;
  overflow: clip;
  pointer-events: none;
}
.gaps.is-full .fixes { margin-top: 0; padding-top: var(--cards-top, 0); }
/* The pinned screen already leaves room under the cards. */
.problem:has(.gaps.is-full) { padding-bottom: clamp(24px, 3vw, 48px); }
.gaps.is-full .fix { pointer-events: auto; opacity: 0; }

/* Phones: the three moments are one row that slides in from the right. */
@media (max-width: 760px) {
  .gaps.is-phone .fixes { display: flex; width: max-content; max-width: none; margin-inline: 0; }
  .gaps.is-phone .fixes { transform-origin: 0 var(--cards-top, 0); transition: transform .5s var(--ease-swipe); }
  .gaps.is-phone .fix { flex: none; grid-row: auto; grid-template-rows: auto; width: min(80vw, 320px); opacity: 1; transition: opacity .5s var(--ease-swipe); }
  .gaps.is-phone .fix:not(.is-current) { opacity: .35; }
  .gaps.is-phone.no-anim .fixes,
  .gaps.is-phone.no-anim .fix { transition: none; }
}

/* Phones: each card rises in as it scrolls into view. */
.gaps.is-seq:not(.is-full) .fix { transition: opacity .7s var(--ease-out), transform .9s var(--ease-out); }
.gaps.is-seq:not(.is-full) .fix.is-pending { opacity: 0; transform: translateY(40px); transition: opacity .3s var(--ease-out), transform .4s var(--ease-out); }

/* Phones: each handled moment's answer plays once, as its card arrives in
   the centre (main.js adds .is-played). The first message is always there,
   so no card arrives empty; the answer follows a beat later (like the hero
   phone's bubbles, from its speaker's side), then the result with its tick. */
@media (max-width: 760px) {
  .gaps.is-phone .fix:not(.is-played) .fix-thread li:nth-child(2) { opacity: 0; transform: translateY(6px) scale(.92); }
  .gaps.is-phone .fix:not(.is-played) .fix-result { opacity: 0; transform: translateY(8px); }
  .gaps.is-phone .fix:not(.is-played) .fix-result .ic { transform: scale(.6); }

  .gaps.is-phone .fix.is-played .fix-thread li:nth-child(2) { transition: opacity .25s var(--ease-out) var(--d, 0s), transform .42s cubic-bezier(.34, 1.3, .64, 1) var(--d, 0s); }
  .gaps.is-phone .fix.is-played .fix-result { transition: opacity .3s var(--ease-out) var(--d, 0s), transform .45s var(--ease-out) var(--d, 0s); }
  .gaps.is-phone .fix.is-played .fix-result .ic { transition: transform .45s cubic-bezier(.34, 1.56, .64, 1) calc(var(--d, 0s) + .08s); }

  .fix-thread li { transform-origin: 0 100%; }
  .fix-thread li.is-sys { transform-origin: 100% 100%; }
  .fix-thread li:nth-child(2) { --d: .15s; }
  .fix-result { --d: .45s; }
}

/* ---------- Bands ----------
   Only the footer is dark. The red bands are Acquire · Serve · Grow and
   The workflow comes first. */

.dark { background: var(--dark); color: var(--on-dark); }

/* Acquire · Serve · Grow and The workflow comes first: the red bands. The
   working red keeps white text at 5:1 at every size.
   Without script, or with reduced motion, it is an ordinary section: the
   headline, then the three areas in a row. With script on a screen that has
   the room, main.js pins the band under the nav (.is-pinned): the headline
   stays at the top, and scrolling brings the areas in from the right, one
   after another, into the row at the foot of the screen. */

.band-red { background: var(--accent); color: #fff; }
.band-red ::selection { background: #fff; color: var(--accent-2); }
.band-red :focus-visible { outline-color: #fff; }

.outcomes { position: relative; overflow-x: clip; }
.areas-stage { padding-block: clamp(96px, 11vw, 152px); }
.areas-inner { display: flex; flex-direction: column; gap: clamp(56px, 8vw, 112px); }
/* Breaks as "Three places where our / solutions create / business value.",
   top line longest (10.27em / 7.08em / 6.74em). */
.outcomes h2 { max-width: 10.7em; text-wrap: wrap; }

.modules { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(24px, 3.4vw, 56px); }
.module { padding-bottom: clamp(24px, 3vw, 36px); }
/* A thin rule between the areas: down the gaps of the row here, across them
   once they stack on phones. */
.modules { column-gap: 0; }
.module:not(:last-child) { padding-right: clamp(24px, 3.4vw, 56px); }
.module + .module { padding-left: clamp(24px, 3.4vw, 56px); border-left: 1px solid rgba(255, 255, 255, .3); }
.module-num { display: block; margin-bottom: 12px; color: rgba(255, 255, 255, .62); font-size: .9375rem; font-weight: var(--w-ui); font-variant-numeric: tabular-nums; letter-spacing: .02em; }
.module-name { font-size: clamp(1.75rem, 1.25rem + 1.25vw, 2.625rem); line-height: 1.1; }
.module-tag { margin-top: 12px; color: rgba(255, 255, 255, .86); font-size: clamp(1.0625rem, .95rem + .4vw, 1.3125rem); font-weight: 400; line-height: 1.4; letter-spacing: var(--track-title); }
.band-red .link { margin-top: 22px; color: #fff; }
.band-red .lead { color: #fff; }

.outcomes.is-pinned .areas-stage {
  position: sticky;
  top: 0;
  display: flex;
  height: 100vh;
  padding-top: calc(var(--nav-h) + clamp(32px, 6vh, 64px));
  padding-bottom: clamp(40px, 9vh, 96px);
}
.outcomes.is-pinned .areas-inner { flex: 1; justify-content: space-between; }
.outcomes.is-pinned .module { will-change: transform, opacity; }

/* Where the row doesn't fit, the areas stack and each slides in from the
   right as it scrolls into view. */
.outcomes:not(.is-pinned) .module { transition: opacity .8s var(--ease-out), transform 1.1s var(--ease-out); }
.outcomes:not(.is-pinned) .module.is-pending { opacity: 0; transform: translateX(96px); transition: opacity .3s var(--ease-out), transform .4s var(--ease-out); }

/* ---------- What We Build ---------- */

.build-head { max-width: 780px; }
.build-head h2 { max-width: 18ch; }
.build .build-head { max-width: 900px; }
/* Breaks after "first." (the first sentence is 11.4em wide). */
.build .build-head h2 { max-width: 12em; text-wrap: wrap; }
.build .build-head .lead { max-width: 26em; text-wrap: pretty; }

.ic-flip { transform: scaleX(-1); }

/* Layers */

.layers {
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
  gap: clamp(40px, 6vw, 80px);
  align-items: center;
  margin-top: clamp(48px, 6vw, 80px);
}
.statement {
  font-size: clamp(1.75rem, 1.15rem + 1.9vw, 2.625rem);
  font-weight: var(--w-display);
  line-height: 1.08;
  letter-spacing: var(--track-display);
  text-wrap: balance;
}
.layers-sub { max-width: 30em; margin-top: 24px; font-size: 1.125rem; line-height: 1.55; text-wrap: pretty; }
.layers-copy .btn { margin-top: 32px; }

/* The board reads top to bottom: the step in the workflow, the channel it
   reaches the customer through, and the systems that power it. main.js draws the wires between the tiers
   and lights one step's routes at a time, starting with the first. */
.layers-board {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: clamp(16px, 2vw, 28px);
  align-items: center;
  padding: clamp(24px, 3vw, 40px);
  border-radius: var(--r-xl);
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 1px 2px rgba(70, 0, 0, .14), 0 32px 64px -32px rgba(70, 0, 0, .55);
}
/* A white card on a red band (this board, How We Work's story cards):
   selection goes back to the light-surface red. */
.band-red :is(.layers-board, .story-step) ::selection { background: var(--accent); color: #fff; }
.layers-board .wires { z-index: 2; }
.tier-label { grid-column: 1; font-size: .8125rem; font-weight: var(--w-strong); }
.tier { position: relative; grid-column: 2; padding: 0; list-style: none; }
.tier-label ~ .tier-label, .tier-label ~ .tier-label + .tier { margin-top: clamp(56px, 6vw, 88px); }

.tier-process { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px; }
.tier-process li {
  display: grid;
  align-content: start;
  gap: 10px;
  padding: 16px 14px;
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--shadow-1);
  font-size: .8125rem;
  font-weight: var(--w-ui);
  line-height: 1.3;
  cursor: default;
  -webkit-tap-highlight-color: transparent;
  transition: border-color .25s, background-color .25s, color .25s, box-shadow .25s;
}
.tier-process .ic { font-size: 20px; transition: color .25s; }
.tier-process li:focus-visible { outline-color: var(--accent); outline-offset: 2px; }
.tier-process .uses { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Voice sits under the first three steps, Messaging under the last two. */
.tier-channels { height: 52px; }
.tier-channels li {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 22%;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 0 8px;
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--shadow-1);
  font-size: .8125rem;
  font-weight: var(--w-ui);
  line-height: 1.15;
  text-align: center;
  transition: border-color .25s, background-color .25s, color .25s, box-shadow .25s;
}
.tier-channels .ic { font-size: 18px; transition: color .25s; }
.tier-channels [data-node="voice"] { left: 19%; }
.tier-channels [data-node="msg"] { left: 69%; }

.tier-systems { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.tier-systems li {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 16px 4px;
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--shadow-1);
  color: var(--ink);
  font-size: .8125rem;
  font-weight: var(--w-ui);
  transition: border-color .25s, background-color .25s, color .25s, box-shadow .25s;
}
.tier-systems .ic { font-size: 20px; transition: color .25s; }

.tier-wire { fill: none; stroke: var(--line-2); stroke-width: 1.25; opacity: .8; }
.tier-wire-lit { fill: none; stroke: var(--accent); stroke-width: 1.75; opacity: 0; transition: opacity .25s; }
.tier-wire-lit.is-hot { opacity: 1; }
.tier-dot { fill: var(--line-2); stroke: var(--surface); stroke-width: 1.5; transition: fill .25s; }
.tier-dot.is-hot { fill: var(--accent); }

@media (min-width: 761px) {
  .layers-board li.is-hot { border-color: var(--ink-3); background: var(--grey-100); box-shadow: var(--shadow-2); }
}

.layers-hint {
  grid-column: 1 / -1;
  justify-self: center;
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: clamp(32px, 3.4vw, 48px);
  padding: 8px 16px;
  border-radius: 99px;
  background: var(--tint);
  color: var(--ink-3);
  font-size: .8125rem;
  line-height: 1.35;
}
.layers-hint .ic { font-size: 15px; color: var(--ink-2); }
.hint-tap { display: none; }
@media (hover: none) { .hint-hover { display: none; } .hint-tap { display: inline; } }

/* ---------- Worked example ---------- */

.example-head h2 { max-width: 16ch; }

/* The scroller is tall; the pin stays on screen while it passes, and each
   step owns an equal stretch of that scroll, so none can be skipped.
   The pin fills the whole screen and centres its content, so the space
   above and below is equal (user, 2026-10-10): the nav is tucked away
   while scrolling down. Content stays within the screen less two nav
   heights, so the nav never covers it when it comes back. */
.example-scroll {
  --seg: 300px;
  position: relative;
  height: calc(100vh + var(--steps) * var(--seg));
  height: calc(100svh + var(--steps) * var(--seg));
  margin-top: clamp(8px, 2vw, 24px);
}
/* Phones: a shorter stretch per step; a flick of the thumb moves on one. */
@media (max-width: 760px) { .example-scroll { --seg: 200px; } }
.example-pin {
  position: sticky;
  top: 0;
  display: flex;
  align-items: center;
  height: 100vh;
  height: 100svh;
}
.example-grid {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: clamp(40px, 7vw, 112px);
  align-items: center;
}

.phone {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 400px;
  height: min(600px, calc(100svh - 2 * var(--nav-h) - 16px));
  min-height: 360px;
  margin-inline: auto;
  border: 1px solid var(--line);
  border-radius: 28px;
  background: var(--surface);
  box-shadow: var(--shadow-3);
  overflow: hidden;
}
.phone-head { gap: 10px; padding: 12px 14px; }
.phone-back { color: var(--ink-2); font-size: 18px; }
.chat-avatar { display: grid; flex: none; place-items: center; width: 36px; height: 36px; border-radius: 50%; background: var(--ink); color: #fff; }
.chat-avatar .ic { font-size: 17px; }
.phone-who { flex: 1; min-width: 0; }
.phone-acts { display: flex; gap: 18px; color: var(--ink-2); }
.phone-acts .ic { font-size: 19px; }
.phone-bar { display: flex; align-items: center; gap: 8px; padding: 8px 10px 10px; background: var(--grey-50); }
.phone-input { display: flex; flex: 1; align-items: center; height: 40px; padding: 0 16px; border-radius: 99px; background: var(--surface); box-shadow: 0 1px .5px rgba(17, 17, 17, .1); color: var(--ink-3); font-size: .875rem; }
.phone-mic { display: grid; flex: none; place-items: center; width: 40px; height: 40px; border-radius: 50%; background: var(--accent); color: #fff; }
.phone-mic .ic { font-size: 18px; }
.phone-msgs .msg { font-size: .875rem; }
.phone-msgs .msg-sys { font-size: .78rem; }
.phone-msgs .is-hidden { display: none; }

.example-title { font-size: 1.5rem; font-weight: var(--w-strong); letter-spacing: var(--track-title); }
.example-intro { margin-top: 8px; color: var(--ink-2); font-size: 1.125rem; text-wrap: pretty; }
.example-sys { margin-top: 20px; font-weight: var(--w-strong); }

.steps { display: grid; gap: 2px; margin-top: 12px; padding: 0; list-style: none; counter-reset: step; }
.steps li { counter-increment: step; }
.step {
  position: relative;
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  align-items: center;
  width: 100%;
  /* Rows tighten on short screens so the list fits the same space as the phone. */
  min-height: clamp(40px, calc((100svh - 2 * var(--nav-h) - 138px) / 8), 52px);
  padding: 8px 16px 8px 10px;
  border: 1px solid transparent;
  border-radius: var(--r-l);
  background: none;
  color: var(--ink-2);
  font-size: 1rem;
  line-height: 1.45;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: background-color .35s, color .35s, border-color .35s, box-shadow .35s, transform .16s var(--ease-out);
}
.step::before {
  content: counter(step);
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border: 1px solid var(--line-2);
  border-radius: 50%;
  background: var(--surface);
  color: var(--ink-3);
  font-size: .8125rem;
  font-weight: var(--w-ui);
  transition: background-color .35s, border-color .35s, color .35s;
}
@media (hover: hover) {
  .step:hover { background: var(--tint); color: var(--ink); }
  .step:hover::before { border-color: var(--ink-3); }
  }
.step:active { transform: scale(.985); }
.step:focus-visible { outline-offset: 0; border-radius: var(--r-l); }
.js .steps .step { color: var(--ink-3); }
.js .steps .step:hover { color: var(--ink); }
.js .steps li.is-past .step { color: var(--ink-2); }
.js .steps li.is-past .step::before { border-color: var(--accent-line); color: var(--accent); }
.js .steps li.is-active .step { border-color: var(--line); background: var(--surface); color: var(--ink); box-shadow: var(--shadow-2); cursor: default; }
.js .steps li.is-active .step::before { border-color: var(--accent); background: var(--accent); color: #fff; }

.step-now { display: none; }

.example-after {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
  gap: clamp(40px, 7vw, 112px);
  margin-top: clamp(24px, 3vw, 40px);
}
.handoff { grid-column: 2; padding-top: 28px; border-top: 1px solid var(--line-2); }
.handoff-line { max-width: 19em; font-size: clamp(1.25rem, 1.05rem + .6vw, 1.5rem); font-weight: var(--w-ui); line-height: 1.3; letter-spacing: var(--track-title); }
.handoff .btn { margin-top: 24px; }

/* ---------- How We Work ----------
   One route from mess to system. The diagram shares the steps' four columns
   (each node sits on a column line) and runs past the wrap to both screen
   edges. main.js plays the transformation as the section scrolls: grey
   tangle → Map → Design → Build → Improve, then one pulse. The markup is
   the finished state, which is what shows without script or with reduced
   motion. */

.process { overflow-x: clip; }
.process .section-head h2 { max-width: 13em; }

/* The headline scrolls away on its own; the stage below pins, centred under
   the nav, while the route plays (main.js adds .is-pinned where it fits). */
.route.is-pinned .route-pin {
  position: sticky;
  top: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  height: 100vh;
  padding-top: var(--nav-h);
}
/* The pinned stage already leaves room under the button. */
.process:has(.route.is-pinned) { padding-bottom: clamp(24px, 3vw, 48px); }

.route-art { position: relative; aspect-ratio: 1200 / 300; }
.route-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }

.r-strand { fill: none; stroke: url(#route-grad); stroke-width: 1.15; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.r-dot { fill: var(--grey-300); }
.r-dot.is-warm { fill: var(--red-300); }
.r-guide { fill: none; stroke: var(--accent); stroke-width: 1; stroke-dasharray: 2 6; stroke-linecap: round; vector-effect: non-scaling-stroke; opacity: .5; }
.r-gdot { fill: var(--accent); opacity: .55; }
.r-trunk { fill: none; stroke: var(--accent); stroke-width: 2.25; stroke-linecap: round; vector-effect: non-scaling-stroke; }
.r-trunk-glow { fill: none; stroke: var(--accent); stroke-width: 10; opacity: .14; }

.r-tile-bg { fill: #fff; stroke: var(--grey-100); stroke-width: 1; vector-effect: non-scaling-stroke; }
.r-station use { fill: var(--grey-600); }
.r-flow-grey { fill: none; stroke: var(--grey-400); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.r-flow-red { fill: none; stroke: var(--accent); stroke-width: 1.8; stroke-linejoin: round; }
.r-face { fill: #fff; stroke: var(--grey-150); stroke-width: 1; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.r-skirt { fill: var(--grey-100); stroke: var(--grey-150); stroke-width: 1; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.r-face-red { fill: url(#route-red); stroke: var(--accent); stroke-width: 1; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.r-skirt-red { fill: var(--red-700); stroke: var(--red-700); stroke-width: 1; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.r-stack-glow { fill: var(--accent); opacity: .22; }
.r-shadow { fill: var(--ink); opacity: .09; }
.r-inset { fill: var(--paper); stroke: var(--grey-100); stroke-width: 1; vector-effect: non-scaling-stroke; }
.r-bar { fill: var(--grey-200); }
.r-bar-warm { fill: var(--red-300); }
.r-bar-red { fill: var(--accent); }
.r-chart { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; stroke-dasharray: 1; stroke-dashoffset: 0; }
.r-chart-end { fill: var(--accent); }
.r-chart-end-halo { fill: var(--accent); opacity: .16; }
.r-donut-track { fill: none; stroke: var(--grey-100); stroke-width: 4; }
.r-donut { fill: none; stroke: var(--accent); stroke-width: 4; stroke-linecap: round; stroke-dasharray: 70 100; }

/* Nodes wake from a soft grey ring to a crisp red one, just after the route
   reaches them. */
.r-halo { fill: var(--accent); opacity: 0; transition: opacity .4s var(--ease-out) .2s; }
.r-ring { fill: #fff; stroke: var(--grey-200); stroke-width: 1; vector-effect: non-scaling-stroke; transition: stroke .35s ease .2s, stroke-width .35s ease .2s; }
.r-core { fill: var(--grey-200); transition: fill .35s ease .2s; }
.r-node-in { transform: scale(.9); transform-box: fill-box; transform-origin: center; transition: transform .45s var(--ease-out) .2s; }
.r-node.is-on .r-node-in { transform: none; }
.r-node.is-on .r-ring { stroke: var(--accent-line); stroke-width: 1.5; }
.r-node.is-on .r-core { fill: var(--accent); }
.r-node.is-on .r-halo { opacity: .09; }

.r-pulse { opacity: 0; pointer-events: none; }
.r-pulse-core { fill: var(--accent); }
.r-pulse-halo { fill: var(--accent); opacity: .22; }


.route-steps { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin-top: clamp(20px, 3vw, 40px); padding: 0; list-style: none; }
.route-steps li {
  padding: 6px clamp(16px, 2.4vw, 32px) 4px;
  border-left: 1px solid var(--line);
  transition: opacity .5s var(--ease-out) .2s, transform .6s var(--ease-out) .2s;
}
.route-steps li:first-child { padding-left: 0; border-left: 0; }
.route-num { display: block; color: var(--ink-3); font-size: .875rem; font-weight: var(--w-ui); }
.route-steps h3 { margin-top: 6px; font-size: clamp(1.5rem, 1.15rem + .9vw, 2rem); line-height: 1.1; }
.route-steps p { margin-top: 10px; color: var(--ink-2); font-size: 1rem; line-height: 1.6; text-wrap: pretty; }
.route.is-live .route-steps li:not(.is-on) { opacity: 0; transform: translateY(10px); transition-delay: 0s; }

.route-cta { display: flex; justify-content: flex-end; margin-top: clamp(48px, 8vh, 88px); transition: opacity .5s var(--ease-out) .2s, transform .6s var(--ease-out) .2s; }
.route.is-live .route-cta:not(.is-on) { opacity: 0; transform: translateY(10px); transition-delay: 0s; }

/* ---------- Final CTA ---------- */

.final { position: relative; overflow: hidden; padding-block: clamp(112px, 13vw, 184px); text-align: center; }
.final-lines {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(46% 60% at 50% 100%, rgba(202, 23, 30, .13), transparent 70%),
    radial-gradient(circle at 1px 1px, rgba(255, 255, 255, .08) 1px, transparent 0) 0 0 / 24px 24px;
  -webkit-mask-image: radial-gradient(70% 80% at 50% 60%, #000 20%, transparent 80%);
  mask-image: radial-gradient(70% 80% at 50% 60%, #000 20%, transparent 80%);
  pointer-events: none;
}
.final-inner { position: relative; }
.final h2 { max-width: 11em; margin-inline: auto; text-wrap: wrap; }
.final p { max-width: 38ch; margin: 24px auto 0; color: var(--on-dark-2); font-size: var(--fs-lead); line-height: 1.55; text-wrap: pretty; }
.final .btn { margin-top: 40px; }
/* Home's question breaks at its phrases, each line shorter than the one
   above: "Where is customer communication" (16em) / "costing you time,
   leads," / "or repeat business?" (kept whole). */
.home-final h2 { max-width: 16.5em; }
/* Below 380px the kept phrase would leave "leads," on a line of its own. */
@media (max-width: 379px) { .home-final .nobr { white-space: normal; } }
/* Phones: a taller band, a larger question that wraps where it falls
   ("… costing you time, / leads, or repeat / business?"), a wider button,
   and the dot grid evenly across the whole band. */
@media (max-width: 760px) {
  .home-final { padding-block: 128px 144px; }
  .home-final h2 { font-size: 2.25rem; }
  .home-final .nobr { white-space: normal; }
  .home-final p { max-width: 18.5em; margin-top: 28px; }
  .home-final .btn { padding-inline: 36px; font-size: 1.0625rem; }
  .home-final .final-lines { -webkit-mask-image: none; mask-image: none; }
}

/* ---------- Footer ---------- */

.footer { padding: 72px 0 32px; border-top: 1px solid var(--dark-line); }
.footer-top { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); gap: 48px; }
.footer .axalus-logo { --logo-knot: var(--accent); --logo-word: #FFFFFF; height: 43px; }
.footer-brand p { max-width: 40ch; margin-top: 18px; color: var(--on-dark-2); font-size: .9375rem; line-height: 1.6; }
.footer-brand .btn { margin-top: 26px; }
.footer-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 24px; }
/* Phones: each column as wide as its links. */
@media (max-width: 560px) { .footer-cols { grid-template-columns: repeat(2, auto); justify-content: start; column-gap: clamp(32px, 14vw, 64px); } }
@media (max-width: 359px) { .footer-cols { grid-template-columns: auto; row-gap: 36px; } }
.footer-h { margin-bottom: 14px; color: var(--on-dark-3); font-size: .8125rem; font-weight: var(--w-ui); }
.footer ul { display: grid; gap: 10px; padding: 0; list-style: none; }
.footer ul a { color: var(--on-dark); font-size: .9375rem; text-decoration: none; text-underline-offset: 4px; }
@media (hover: hover) { .footer ul a:hover { text-decoration: underline; } }
/* Phones: each link a full 44px row to tap. */
@media (max-width: 760px) {
  .footer-h { margin-bottom: 4px; }
  .footer ul { gap: 0; }
  .footer ul a { display: inline-flex; align-items: center; min-height: 44px; }
}
.footer-line {
  max-width: 13.1em;
  color: var(--on-dark);
  /* On narrow phones the size follows the width, so "It's part of the
     infrastructure." (12.93em in Onest) still fits on one line. */
  font-size: min(clamp(1.875rem, 1rem + 3.3vw, 3.75rem), (100vw - 2 * var(--gutter)) / 13.2);
  font-weight: var(--w-display);
  line-height: 1.04;
  letter-spacing: var(--track-display);
}
/* One sentence per line. */
.footer-line > span { display: block; text-wrap: balance; }
/* full-bleed wire behind the line; the wire itself is the divider above the copyright.
   The robot is 200px tall. The wire sits 14.5/300 up the image, so the box drops 10px to put it on the edge. */
.footer-stage { position: relative; margin-top: clamp(72px, 9vw, 112px); }
.footer-stage::before,
.footer-stage::after {
  content: "";
  position: absolute; bottom: -10px;
  height: 200px;
  pointer-events: none;
}
.footer-stage::before {
  left: 0;
  right: 0;
  background: url("footer.png") right bottom / auto 200px no-repeat;
  /* WebP (18KB) where supported; the PNG (128KB) stays for the rest. */
  background-image: image-set(url("footer.webp") type("image/webp"), url("footer.png") type("image/png"));
}
/* On wide screens footer.png (1115px at 200px tall) stops short; footer-wire.png, a plain slice of the
   wire, tiles across just the left gap so the wire still runs edge to edge. */
.footer-stage::after { left: 0; right: 1114px; background: url("footer-wire.png") left bottom / auto 200px repeat-x; }
.footer-stage .wrap { position: relative; padding-bottom: 32px; }
/* Phones and tablets: the robot drops under the tagline (130px tall) instead of sitting behind it. */
@media (max-width: 960px) {
  .footer-stage::before, .footer-stage::after { bottom: -6px; height: 130px; }
  .footer-stage::before { background-size: auto 130px; }
  .footer-stage::after { right: 724px; background-size: auto 130px; }
  .footer-stage .wrap { padding-bottom: 144px; }
}
.footer-base { margin-top: 0; padding-top: 35px; color: var(--on-dark-3); font-size: .8125rem; }

/* ---------- Solutions page ---------- */

/* Hero: the copy, and Acquire → Serve → Grow as three linked stops that jump
   to their sections. */
.sol-hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 440px);
  gap: clamp(40px, 6vw, 96px);
  align-items: center;
}
/* Wide enough for "Stop losing customers" (10.1em) on the first line. */
.sol-hero h1 { max-width: 10.6em; font-size: clamp(2rem, 1.3rem + 2.6vw, 3.875rem); }
/* The top line runs to "faster," (32.8em); "actually happens." is kept whole. */
.sol-hero .hero-sub { max-width: 33em; text-wrap: wrap; }
.solutions-hero .hero-sub { max-width: 33.8em; } /* top line ends "faster," (33.6em in Onest) */
.sol-map { display: grid; }
@media (max-width: 1180px) { .sol-hero-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 380px); } }
.sol-stop {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  column-gap: 24px;
  row-gap: 4px;
  align-items: center;
  padding: 18px 24px 18px 30px;
  border-radius: var(--r-xl);
  background: var(--surface);
  color: var(--ink);
  text-decoration: none;
  box-shadow: var(--shadow-card);
  -webkit-tap-highlight-color: transparent;
  /* Touch: a press springs back at once. */
  transition: transform .2s var(--ease-out);
}
/* Mouse: the spring-up, a slow ease back, and the arrow points the way. */
@media (hover: hover) {
  .sol-stop { transition: transform .9s cubic-bezier(.22, 1, .36, 1); }
  .sol-stop:hover { transform: scale(1.06); transition: transform .45s cubic-bezier(.34, 1.45, .64, 1); }
  .sol-stop:hover .sol-stop-go { transform: rotate(90deg) translateX(3px); }
}
/* Press: a quick, plain ease-out, as on the buttons. */
.sol-stop:active { transform: scale(.97); transition: transform .12s var(--ease-out); }
.sol-stop:focus-visible { outline-offset: 3px; border-radius: var(--r-xl); }
/* Each stop leads into the next: a grey line with an arrowhead, under the
   icon's centre (30px in, 42px box). It hangs off a wrapper, not the card,
   so it stays still while the card scales. */
.sol-step { position: relative; }
.sol-step + .sol-step { margin-top: 40px; }
.sol-step + .sol-step::before,
.sol-step + .sol-step::after { content: ""; position: absolute; left: 50px; }
.sol-step + .sol-step::before { top: -40px; height: 38px; border-left: 1.5px solid var(--ink-3); }
.sol-step + .sol-step::after {
  top: -10px;
  width: 8px;
  height: 8px;
  margin-left: -3.25px;
  border-right: 1.5px solid var(--ink-3);
  border-bottom: 1.5px solid var(--ink-3);
  transform: rotate(45deg);
}
.sol-stop-ic {
  grid-row: span 2;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  color: var(--accent);
}
.sol-stop-ic .ic { font-size: 34px; }
.sol-stop strong { font-size: 1.375rem; font-weight: var(--w-strong); letter-spacing: var(--track-title); line-height: 1.2; }
.sol-stop-line { grid-column: 2; color: var(--ink-2); font-size: .9375rem; line-height: 1.45; text-wrap: pretty; }
.ic-down { transform: rotate(90deg); }
.sol-stop-go { grid-column: 3; grid-row: 1 / span 2; color: var(--ink-3); font-size: 18px; transition: transform .3s var(--ease-out); }
/* First load: the stops arrive in order after the copy, each with the
   link into it, so the page opens on the sequence it is about. */
@media (prefers-reduced-motion: no-preference) {
  .js .sol-step { animation: hero-in .7s var(--ease-out) both; }
  .js .sol-step:nth-child(1) { animation-delay: 160ms; }
  .js .sol-step:nth-child(2) { animation-delay: 240ms; }
  .js .sol-step:nth-child(3) { animation-delay: 320ms; }
}

/* Acquire / Serve / Grow: the copy with its five capabilities, and the
   worked example beside it. */
.area-grid {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(40px, 6vw, 96px);
  align-items: center;
}
/* All three are white, divided by a line at the content width. The nav
   slides away on the way down, so a jump from the hero lands the section's
   top edge at the top of the screen, not a nav's height below it. */
.area { scroll-margin-top: calc(-1 * (var(--nav-h) + 16px)); }
.area + .area { background: linear-gradient(var(--line-2), var(--line-2)) top center / min(var(--wrap), 100% - var(--gutter) * 2) 1px no-repeat; }
.area h2 { font-size: clamp(2.5rem, 1.6rem + 3vw, 4rem); }
.area-sub {
  max-width: 13.4em;
  margin-top: 16px;
  font-size: clamp(1.375rem, 1.1rem + .8vw, 1.75rem);
  font-weight: var(--w-ui);
  line-height: 1.25;
  letter-spacing: var(--track-title);
  text-wrap: balance;
}
.area-intro { max-width: 32em; margin-top: 20px; color: var(--ink-2); font-size: 1.0625rem; line-height: 1.6; text-wrap: pretty; }
.caps { margin-top: clamp(28px, 3vw, 40px); padding: 0; list-style: none; border-top: 1px solid var(--line); }
.caps li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 14px;
  align-items: start;
  padding: 16px 0;
  border-bottom: 1px solid var(--line);
}
.caps :is(h3, h4) { font-size: 1.0625rem; font-weight: var(--w-strong); letter-spacing: 0; line-height: 1.35; }
.caps p { margin-top: 3px; color: var(--ink-2); font-size: .9375rem; line-height: 1.55; text-wrap: pretty; }
/* The icon alone, in red, centred on the heading's first line. */
.cap-ic {
  display: grid;
  place-items: center;
  flex: none;
  width: 22px;
  height: 23px;
  color: var(--accent);
}
.cap-ic .ic { font-size: 20px; }

/* The worked example: what comes in, the numbered steps, and where it ends,
   on one rail. A tag names the part of the business a step touches. No
   frame: it reads as a walkthrough, not a screen. It stays in view while the
   capabilities beside it are read. */
.walk {
  position: sticky;
  top: calc(var(--nav-h) + 56px);
  align-self: start;
  justify-self: end;
  width: 100%;
  max-width: 580px;
  margin: 0;
}
/* Shared with How We Work's output cards. */
.walk-label, .output-label {
  display: inline-block;
  padding: 2px 10px;
  border: 1px solid var(--accent);
  border-radius: 99px;
  background: var(--surface);
  color: var(--accent);
  font-size: .75rem;
  font-weight: var(--w-ui);
}
.walk-steps { margin: 0; padding: 0; list-style: none; }
.walk-row {
  position: relative;
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr) auto;
  align-items: start;
  column-gap: 16px;
  margin: 0;
  padding-bottom: 18px;
  font-size: 1.0625rem;
  line-height: 1.4;
}
.walk-start { margin-top: 22px; }
.walk-end { padding-bottom: 0; }
.walk-start, .walk-end { font-weight: var(--w-ui); }
.walk-text { padding-top: 6px; text-wrap: pretty; }
/* The rail runs from each node's centre to the next: grey underneath, red on
   top, which fills as the example plays. */
.walk-row:not(.walk-end)::before,
.walk-row:not(.walk-end)::after {
  content: "";
  position: absolute;
  top: 18px;
  bottom: -18px;
  left: 17.25px;
  border-left: 1.5px solid var(--line-2);
}
.walk-row:not(.walk-end)::after { border-left-color: var(--accent); transform-origin: 50% 0; transition: transform .4s linear; }
.walk.is-cond .walk-steps .walk-row:last-child::before,
.walk.is-cond .walk-steps .walk-row:last-child::after { border-left-style: dashed; }
.walk-node {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 1.5px solid var(--line-2);
  border-radius: 50%;
  background: var(--surface);
  color: var(--ink-2);
  font-size: .875rem;
  font-weight: var(--w-strong);
  line-height: 1;
  transition: transform .5s cubic-bezier(.34, 1.3, .64, 1);
}
.walk-node .ic { font-size: 18px; }
.walk-start .walk-node { border-color: var(--ink); color: var(--ink); }
/* Every example ends the same way: a red node. Serve's "only if there's an
   exception" shows in the dashed link above it. */
.walk-end .walk-node { border-color: var(--accent); background: var(--accent); color: #fff; }
.walk-tag {
  margin-top: 6px;
  padding: 2px 10px;
  border: 1px solid var(--line);
  border-radius: 99px;
  background: var(--surface);
  color: var(--ink-3);
  font-size: .75rem;
  font-weight: var(--w-ui);
  line-height: 1.5;
  white-space: nowrap;
}
.walk-result {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin-top: 26px;
  padding-top: 20px;
  border-top: 1px solid var(--line-2);
  font-size: 1rem;
  font-weight: var(--w-ui);
  line-height: 1.5;
  text-wrap: pretty;
}
.walk-result .ic { flex: none; margin-top: 1px; color: var(--accent); font-size: 20px; }

/* Played once when it scrolls into view (main.js): the rows wait greyed,
   then light in order while the rail fills down to each. */
.walk-row, .walk-result { transition: opacity .4s var(--ease-out); }
.walk[data-state="pending"] .walk-row:not(.is-on),
.walk[data-state="pending"] .walk-result { opacity: .3; }
.walk[data-state="pending"] .walk-row:not(.is-on)::after { transform: scaleY(0); }
.walk[data-state="pending"] .walk-row:not(.is-on) .walk-node { transform: scale(.86); }

/* One relationship: a short bridge. The heading and three lines sit beside
   the board: the customer's stages on top, the teams inside the business
   below, one communication layer between them. Hovering a stage lights the
   teams it involves. */
.journey.is-bridge { padding-block: clamp(72px, 8vw, 112px); }
.journey-grid { margin-top: 0; }
/* "Customers do not" is 8.2em; the lines step down from it. */
.journey-copy h2 { max-width: 8.4em; font-size: clamp(2rem, 1.3rem + 1.6vw, 2.75rem); text-wrap: wrap; }
/* Two sizes only: the heading and the body. */
.journey-copy p { max-width: 24em; margin-top: 20px; font-size: 1.125rem; line-height: 1.55; text-wrap: pretty; }
/* Breaks after "relationship." (16.6em), then steps down. */
.journey-copy p:last-child { max-width: 17em; text-wrap: wrap; }
.journey-board .tier-process, .journey-areas { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.journey-board .tier-systems { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.journey-board .tier-systems li { padding-inline: 6px; line-height: 1.25; text-align: center; }
.journey-board .tier-channels [data-node="layer"] { left: 18%; width: 64%; gap: 10px; }
/* Which stages belong to Acquire, Serve and Grow. */
.journey-areas { display: grid; gap: 8px; margin-bottom: 14px; }
.journey-areas span { color: var(--accent); font-size: .75rem; font-weight: var(--w-strong); text-align: center; }
.journey-areas span::after {
  content: "";
  display: block;
  height: 8px;
  margin-top: 6px;
  border: 1.5px solid var(--accent-line);
  border-bottom: 0;
  border-radius: 6px 6px 0 0;
}
.ja-acquire { grid-column: span 3; }
.ja-serve { grid-column: span 1; }
.ja-grow { grid-column: span 2; }

/* No two businesses: the eight questions, all alike. */
.q-grid {
  display: grid;
  grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
  gap: clamp(40px, 6vw, 96px);
  align-items: start;
}
/* Sized to its column, like the problem heading beside its stories. */
.q-head { position: sticky; top: calc(var(--nav-h) + 48px); container-type: inline-size; }
.q-head h2 { font-size: clamp(2rem, 1.25rem + 2.1vw, 2.875rem); font-size: clamp(2rem, 9.6cqi, 2.875rem); }
.q-list { margin: 0; border-top: 1px solid var(--line); }
.q-row {
  display: grid;
  grid-template-columns: minmax(140px, 12em) minmax(0, 1fr);
  gap: 8px 24px;
  align-items: center;
  padding: 20px 0;
  border-bottom: 1px solid var(--line);
}
.q-row dt { display: flex; align-items: center; gap: 12px; font-size: 1rem; font-weight: var(--w-strong); }
.q-row dd { margin: 0; font-size: 1.125rem; line-height: 1.5; text-wrap: pretty; }

/* Closing band: one button. */
.final-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 40px; }
.final .final-actions .btn { margin-top: 0; }
/* "Where is communication" is 11.4em; "of growth?" is kept together. */
.sol-final h2 { max-width: 11.6em; }
/* Two lines, one sentence each: the first is 32.25em in Onest. */
.sol-final p { max-width: 32.6em; text-wrap: wrap; }


/* ---------- How We Work page ---------- */

/* Hero: the copy, and beside it the four phases as an index of what each
   one hands over: type on the grey, no cards. One caption says what the
   second line of each row is; grey rules part the rows (number, phase,
   deliverable), and each row jumps to its phase. The index runs the full
   height of the copy, so it starts level with the headline and its last
   rule sits level with the buttons. The phase names stay a step below the
   headline, so the headline leads. */
/* "Start with the workflow." is 10.9em in Onest, so it gets its own line: the
   headline shrinks a little whenever its column is narrower than 11.1em
   (about 4% at 1024px), and is the shared hero size everywhere else. */
.hww-hero .sol-hero-text { container-type: inline-size; }
.hww-hero h1 { max-width: 11.1em; font-size: min(clamp(2rem, 1.3rem + 2.6vw, 3.875rem), 100cqi / 11.1); text-wrap: wrap; }
/* Around 1024px the narrow column would leave "belong." on its own. */
.hww-hero .hero-sub { text-wrap: pretty; }
.phase-index { align-self: stretch; display: flex; flex-direction: column; }
.pi-title { margin-bottom: 14px; font-size: .9375rem; font-weight: var(--w-ui); line-height: 1.35; }
.phase-index ol {
  flex: 1;
  display: grid;
  grid-template-rows: repeat(4, 1fr);
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--line-2);
}
.phase-index li { display: flex; border-bottom: 1px solid var(--line-2); }
.phase-index a {
  flex: 1;
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr) auto;
  column-gap: 12px;
  row-gap: 4px;
  align-content: center;
  align-items: baseline;
  padding: 16px 12px;
  color: var(--ink);
  text-decoration: none;
  transition: background-color .25s;
}
.phase-index a:focus-visible { outline-offset: -2px; }
/* No grey tap flash: a press darkens the row instead (below the hover). */
.phase-index a { -webkit-tap-highlight-color: transparent; }
/* First load: the caption, then 01 to 04 in order, after the copy. */
@media (prefers-reduced-motion: no-preference) {
  .js .pi-title, .js .phase-index li { animation: hero-in .7s var(--ease-out) both; }
  .js .pi-title { animation-delay: 160ms; }
  .js .phase-index li:nth-child(1) { animation-delay: 220ms; }
  .js .phase-index li:nth-child(2) { animation-delay: 280ms; }
  .js .phase-index li:nth-child(3) { animation-delay: 340ms; }
  .js .phase-index li:nth-child(4) { animation-delay: 400ms; }
}
.pi-num { margin: 0 16px 0 24px; color: var(--accent); font-size: 1.875rem; font-weight: var(--w-strong); line-height: 1; }
.pi-name { font-size: clamp(1.5rem, 1.1rem + 1.1vw, 2.125rem); font-weight: var(--w-display); letter-spacing: var(--track-display); line-height: 1.05; }
.pi-out { grid-column: 2; color: var(--ink-2); font-size: .9375rem; line-height: 1.35; }
.pi-go { grid-column: 3; grid-row: 1 / span 2; align-self: center; color: var(--ink-3); font-size: 20px; transition: transform .3s var(--ease-out); }
@media (hover: hover) {
  .phase-index a:hover { background: rgba(17, 17, 17, .04); }
  .phase-index a:hover .pi-go { transform: rotate(90deg) translateX(4px); }
}
/* Press: the row darkens at once (a list row, so tone rather than scale);
   after the hover, so it still shows over it. */
.phase-index a:active { background: rgba(17, 17, 17, .07); transition-duration: .08s; }

/* The four phases. A rail of 01–04 stays beside them and fills red as the
   page moves through (main.js); each phase is its heading, what we do, and
   the deliverable it ends with. */
.phases-grid { display: grid; grid-template-columns: 168px minmax(0, 1fr); gap: clamp(40px, 5vw, 80px); }
.phase-rail {
  position: sticky;
  top: calc(var(--nav-h) + 40px);
  align-self: start;
  /* Margins, not padding: the rail sticks by its own box, and the bottom
     margin keeps it out of the last phase's bottom padding, so it stops
     where the last output card stops. */
  margin-block: clamp(80px, 9vw, 128px);
}
.phase-rail ol { position: relative; display: grid; gap: 28px; padding: 0; list-style: none; }
.phase-rail ol::before,
.phase-rail ol::after { content: ""; position: absolute; top: 18px; left: 17.25px; border-left: 1.5px solid var(--line-2); }
.phase-rail ol::before, .phase-rail ol::after { bottom: 18px; }
/* Scaled, not resized, so following the scroll costs no layout. */
.phase-rail ol::after { border-left-color: var(--accent); transform: scaleY(var(--fill, 0)); transform-origin: 50% 0; }
.phase-rail a {
  display: flex;
  align-items: center;
  gap: 14px;
  color: var(--ink-3);
  font-size: 1rem;
  font-weight: var(--w-ui);
  text-decoration: none;
  transition: color .25s;
}
.phase-rail a { -webkit-tap-highlight-color: transparent; }
.phase-rail a.is-current { color: var(--ink); }
@media (hover: hover) { .phase-rail a:hover { color: var(--ink); } }
.rail-node {
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  flex: none;
  width: 36px;
  height: 36px;
  border: 1.5px solid var(--line-2);
  border-radius: 50%;
  background: var(--surface);
  color: var(--ink-3);
  font-size: .8125rem;
  font-weight: var(--w-strong);
  transition: border-color .25s, background-color .25s, color .25s, transform .12s var(--ease-out);
}
.phase-rail a:active .rail-node { transform: scale(.9); }
.phase-rail a.is-past .rail-node { border-color: var(--accent); color: var(--accent); }
.phase-rail a.is-current .rail-node { border-color: var(--accent); background: var(--accent); color: #fff; }

.phase { padding-block: clamp(80px, 9vw, 128px); scroll-margin-top: calc(-1 * (var(--nav-h) + 16px)); }
.phase + .phase { border-top: 1px solid var(--line-2); }
.phase-head h2 { font-size: clamp(2.5rem, 1.6rem + 3vw, 4rem); }
.phase-num { display: block; margin-bottom: 12px; color: var(--accent); font-size: 1rem; font-weight: var(--w-strong); letter-spacing: 0; line-height: 1; }
.phase-sub {
  max-width: 22em;
  margin-top: 16px;
  font-size: clamp(1.375rem, 1.1rem + .8vw, 1.75rem);
  font-weight: var(--w-ui);
  line-height: 1.25;
  letter-spacing: var(--track-title);
}
.phase-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 320px);
  gap: clamp(32px, 4vw, 64px);
  align-items: start;
  margin-top: clamp(28px, 3vw, 40px);
}
.phase-intro, .phase-text { max-width: 34em; color: var(--ink-2); font-size: 1.0625rem; line-height: 1.6; text-wrap: pretty; }
.phase-text { margin-top: 14px; }
.phase-lead { margin-top: 24px; font-size: 1rem; font-weight: var(--w-strong); }
.checks { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 32px; margin-top: 14px; padding: 0; list-style: none; }
.checks li { display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 10px; font-size: 1rem; line-height: 1.5; text-wrap: pretty; }
.checks .ic { margin-top: 3px; color: var(--accent); font-size: 18px; }
.phase-main .caps { margin-top: 16px; }
.caps h4 { margin: 0; }

/* The deliverable: a document card, not a screen. It stays in view beside
   the phase's list. */
.output {
  position: sticky;
  top: calc(var(--nav-h) + 40px);
  padding: 22px 24px 24px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-l);
  background: var(--surface);
  box-shadow: var(--shadow-2);
}
.output-top { display: flex; align-items: center; justify-content: space-between; }
.output-top .ic { color: var(--ink-3); font-size: 20px; }
.output-title { margin-top: 16px; font-size: 1.25rem; font-weight: var(--w-strong); letter-spacing: var(--track-title); line-height: 1.25; text-wrap: balance; }
.output-text { margin-top: 8px; color: var(--ink-2); font-size: .9375rem; line-height: 1.6; text-wrap: pretty; }

/* Improve: Observe → Measure → Learn → Adjust, round a ring, clockwise. */
/* Improve's loop, centred in the text column (user, 2026-10-10: bigger,
   centred). The ring, dots and arrows scale with the box. */
.cycle { position: relative; width: min(100%, 460px); aspect-ratio: 320 / 220; margin: 48px auto 0; }
.cycle-ring { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; color: var(--accent); }
.cycle-arcs path { fill: none; stroke: var(--accent); stroke-width: 1.5; marker-end: url(#cycle-head); }
.cycle-dots circle { fill: var(--accent); }
.cycle-steps { padding: 0; list-style: none; font-size: 1.125rem; font-weight: var(--w-ui); line-height: 1.2; }
.cycle-steps li { position: absolute; white-space: nowrap; }
.cycle-steps .c-1 { left: 50%; top: calc(40 / 220 * 100% - 18px); transform: translate(-50%, -100%); }
.cycle-steps .c-2 { left: calc(230 / 320 * 100% + 18px); top: 50%; transform: translateY(-50%); }
.cycle-steps .c-3 { left: 50%; top: calc(180 / 220 * 100% + 18px); transform: translateX(-50%); }
.cycle-steps .c-4 { left: calc(90 / 320 * 100% - 18px); top: 50%; transform: translate(-100%, -50%); }

/* The worked example: four white cards on red, joined by arrows. They
   light in order once, when the band scrolls in (main.js). */
.hww-story .story-head { max-width: 860px; }
.hww-story h2 { max-width: 15em; }
.story {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 40px;
  margin-top: clamp(40px, 5vw, 64px);
  padding: 0;
  list-style: none;
}
.story-step {
  position: relative;
  padding: 24px 24px 26px;
  border-radius: var(--r-xl);
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 1px 2px rgba(70, 0, 0, .14), 0 24px 48px -24px rgba(70, 0, 0, .5);
}
.story-step + .story-step::before,
.story-step + .story-step::after { content: ""; position: absolute; top: 50%; }
.story-step + .story-step::before { left: -40px; width: 38px; border-top: 1.5px solid rgba(255, 255, 255, .8); }
.story-step + .story-step::after {
  left: -10px;
  width: 8px;
  height: 8px;
  margin-top: -3.25px;
  border-top: 1.5px solid rgba(255, 255, 255, .8);
  border-right: 1.5px solid rgba(255, 255, 255, .8);
  transform: rotate(45deg);
}
.story-phase { display: flex; align-items: baseline; gap: 10px; color: var(--accent); font-size: 1.125rem; font-weight: var(--w-strong); line-height: 1.2; }
.story-phase span { color: var(--ink-3); font-size: .8125rem; }
.story-step p + p { margin-top: 12px; color: var(--ink-2); font-size: .9375rem; line-height: 1.6; text-wrap: pretty; }
.story-result { display: flex; align-items: flex-start; gap: 12px; margin-top: 40px; color: #fff; font-size: var(--fs-lead); font-weight: var(--w-ui); line-height: 1.45; }
.story-result .ic { flex: none; margin-top: 2px; font-size: 22px; }
[data-seq-item] { transition: opacity .5s var(--ease-out), transform .6s var(--ease-out); }
.is-seq-pending [data-seq-item]:not(.is-on) { opacity: .35; transform: translateY(10px); }

/* Principles: six short rules under one heading. */
.principles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 40px clamp(24px, 3vw, 48px);
  margin-top: clamp(40px, 5vw, 64px);
  padding: 0;
  list-style: none;
}
.principles li { padding-top: 20px; border-top: 1px solid var(--line-2); }
.principles h3 { font-size: 1.25rem; font-weight: var(--w-strong); letter-spacing: var(--track-title); line-height: 1.3; }
.principles p { margin-top: 8px; color: var(--ink-2); font-size: 1.0625rem; line-height: 1.55; text-wrap: pretty; }

/* Working with us: the heading beside four words, two by two. */
.hww-feel { background: linear-gradient(var(--line-2), var(--line-2)) top center / min(var(--wrap), 100% - var(--gutter) * 2) 1px no-repeat; }
.feel-grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: clamp(40px, 6vw, 96px); align-items: start; }
.feel-grid h2 { max-width: 9em; }
.feel { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 40px clamp(24px, 3vw, 48px); margin: 0; }
.feel dt { font-size: clamp(1.5rem, 1.2rem + .9vw, 2rem); font-weight: var(--w-display); letter-spacing: var(--track-display); line-height: 1.1; }
.feel dd { margin: 10px 0 0; color: var(--ink-2); font-size: 1.0625rem; line-height: 1.55; text-wrap: pretty; }

/* Breaks after "breaks down," (30.2em), so the phrase stays whole. */
.hww-final p { max-width: 30.6em; }

@media (max-width: 1180px) {
  .phase-body { grid-template-columns: minmax(0, 1fr); }
  .output { position: static; max-width: 520px; }
  .story { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
  .story-step + .story-step::before, .story-step + .story-step::after { display: none; }
}
@media (max-width: 959px) {
  .phases-grid { grid-template-columns: minmax(0, 1fr); }
  .phase-rail { display: none; }
  .principles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .feel-grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 560px) {
  .checks { grid-template-columns: minmax(0, 1fr); }
  .story { grid-template-columns: minmax(0, 1fr); }
  .principles, .feel { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- Technology page ---------- */

/* Hero: the copy, and beside it the mix: the same categories for every
   business, a different set lit for each. Four example businesses take
   turns (main.js); hovering holds one, picking one keeps it. Type and thin
   outlines on the grey; the lit ones turn white. */
/* Each sentence starts its own line, balanced within the column. */
.tech-hero h1 { max-width: none; text-wrap: wrap; }
.tech-hero h1 > span { display: block; text-wrap: balance; }
/* Breaks after "already" (27.4em), so the top line is the longer one. */
.tech-hero .hero-sub { max-width: 34em; text-wrap: wrap; }

.mix { margin: 0; }
/* First load: the caption, the tabs and the grid follow the copy. */
@media (prefers-reduced-motion: no-preference) {
  .js .mix > * { animation: hero-in .7s var(--ease-out) both; }
  .js .mix > :nth-child(1) { animation-delay: 160ms; }
  .js .mix > :nth-child(2) { animation-delay: 220ms; }
  .js .mix > :nth-child(3) { animation-delay: 280ms; }
}
.mix-cap { font-size: .9375rem; font-weight: var(--w-ui); line-height: 1.4; text-wrap: pretty; }
/* The four names spread across one line. */
.mix-tabs { position: relative; display: grid; grid-template-columns: repeat(4, auto); justify-content: space-between; gap: 12px; margin-top: 10px; border-bottom: 1px solid var(--line-2); }
.mix-tabs button {
  position: relative;
  padding: 10px 0 12px;
  border: 0;
  background: none;
  color: var(--ink-2);
  font-size: .9375rem;
  font-weight: var(--w-ui);
  line-height: 1.3;
  white-space: nowrap;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color .2s, transform .12s var(--ease-out);
}
@media (hover: hover) { .mix-tabs button:hover { color: var(--ink); } }
.mix-tabs button:active { transform: scale(.97); }
.mix-tabs button::after {
  content: "";
  position: absolute;
  right: 0;
  bottom: -1.5px;
  left: 0;
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transition: transform .35s var(--ease-out);
}
.mix-tabs button[aria-pressed="true"] { color: var(--ink); }
.mix-tabs button[aria-pressed="true"]::after { transform: none; }
.mix-tabs button:focus-visible { outline-offset: 2px; }
/* With script, one underline travels from the last example to the next
   (main.js sets where and how wide), instead of one shrinking while
   another grows. Scaled from a 1px bar, so it only ever moves by transform. */
.mix-tabs.has-slide button::after { display: none; }
.mix-tabs.has-slide::after {
  content: "";
  position: absolute;
  /* Centred on the 1px grey line: half a pixel over it on each side. */
  bottom: -1.5px;
  left: 0;
  width: 1px;
  height: 2px;
  background: var(--accent);
  transform: translateX(var(--tab-x, 0)) scaleX(var(--tab-w, 0));
  transform-origin: 0 0;
  transition: transform .35s cubic-bezier(.77, 0, .175, 1);
}
.mix-tabs.is-still::after { transition: none; }
.mix-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 8px; margin-top: 20px; padding: 0; list-style: none; }
.mix-grid li {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 52px;
  padding: 10px 14px;
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  color: var(--ink-3);
  font-size: .9375rem;
  font-weight: var(--w-ui);
  line-height: 1.25;
  transition: background-color .4s, color .4s, border-color .4s, box-shadow .4s;
  /* A change sweeps across the grid in reading order (main.js numbers the
     chips), so the new mix reads as one change, not eleven at once. */
  transition-delay: calc(var(--i, 0) * 25ms);
}
.mix-grid .ic { flex: none; font-size: 16px; opacity: 0; transform: scale(.6); transition: opacity .3s, transform .35s var(--ease-out); transition-delay: calc(var(--i, 0) * 25ms); }
/* Eleven categories fill three columns: the last one takes two cells. */
.mix-grid li:last-child { grid-column: span 2; }
.mix-grid li.is-on { border-color: transparent; background: var(--surface); color: var(--ink); box-shadow: 0 0 0 1px rgba(17, 17, 17, .05), 0 1px 2px rgba(17, 17, 17, .06), 0 8px 18px -10px rgba(17, 17, 17, .25); }
.mix-grid li.is-on .ic { color: var(--accent); }
.mix-grid li.is-on .ic { opacity: 1; transform: none; }

/* Two white sections in a row are parted by a line at the content width. */
.tech-ai, .tech-build { background: linear-gradient(var(--line-2), var(--line-2)) top center / min(var(--wrap), 100% - var(--gutter) * 2) 1px no-repeat; }
.tech-layers-head, .tech-ai-head { display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); gap: clamp(32px, 5vw, 80px); align-items: end; }
.tech-layers-head h2 { max-width: 12em; }
.tech-ai-head h2 { max-width: 12em; }
.tech-ai-head h2 > span { display: block; } /* one sentence per line */
.tech-layers-lead p, .tech-ai-head .lead { color: var(--ink-2); font-size: var(--fs-lead); line-height: 1.55; text-wrap: pretty; }
.tech-ai-head .lead { margin-top: 0; }
.tech-layers-lead p + p { margin-top: 10px; }

/* Behind the conversation: a cross-section. One message at the top, the
   four layers beneath it as bands, and one red thread down through them to
   the reply the customer sees. It reads in order of weight: the path first
   (four numbered stops, what happens at each, and the tools it uses in solid
   red), then the layer names, then the other tools and each layer's role,
   quieter. It plays once, top to bottom. */
.xsec { position: relative; margin-top: clamp(48px, 6vw, 80px); padding-left: 64px; counter-reset: stop; }
.xsec::before { content: ""; position: absolute; top: 50px; bottom: 26px; left: 19px; border-left: 2px solid var(--accent); }
.xsec-end { display: grid; justify-items: start; gap: 8px; }
.xsec-who { color: var(--ink-3); font-size: .8125rem; font-weight: var(--w-ui); line-height: 1.2; }
.xsec-bubble {
  position: relative;
  max-width: 26em;
  padding: 12px 18px;
  border-radius: 18px 18px 18px 4px;
  background: var(--bubble-in);
  font-size: 1.25rem;
  font-weight: var(--w-ui);
  line-height: 1.4;
}
.xsec-bubble.is-out { border-radius: 18px 18px 4px 18px; background: var(--bubble-out); }
.xsec-bubble::before {
  content: "";
  position: absolute;
  top: 50%;
  left: -52px;
  width: 16px;
  height: 16px;
  margin-top: -8px;
  border-radius: 50%;
  background: var(--accent);
}
.xsec-layers { margin: 32px 0; padding: 0; list-style: none; border-top: 1px solid var(--line-2); }
.xsec-band {
  counter-increment: stop;
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 4fr) minmax(0, 7fr);
  gap: 18px clamp(24px, 4vw, 64px);
  padding: 32px 0;
  border-bottom: 1px solid var(--line-2);
}
.xsec-band::before {
  content: counter(stop);
  position: absolute;
  top: 33px;
  left: -58px;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-size: .8125rem;
  font-weight: var(--w-strong);
  line-height: 1;
}
.xsec-name { display: flex; align-items: flex-start; gap: 14px; }
.xsec-ic { flex: none; margin-top: 4px; color: var(--accent); }
.xsec-ic .ic { font-size: 24px; }
.xsec-name h3 { font-size: clamp(1.375rem, 1.1rem + .7vw, 1.75rem); font-weight: var(--w-display); letter-spacing: var(--track-title); line-height: 1.2; }
.xsec-name p { margin-top: 8px; color: var(--ink-3); font-size: .9375rem; line-height: 1.55; text-wrap: pretty; }
.xsec-here { padding-top: 2px; font-size: var(--fs-lead); font-weight: var(--w-ui); line-height: 1.45; text-wrap: pretty; }
.xsec-tools { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 16px; padding: 0; list-style: none; }
.xsec-tools li { padding: 4px 12px; border: 1px solid var(--line); border-radius: 99px; color: var(--ink-3); font-size: .8125rem; font-weight: var(--w-ui); line-height: 1.35; }
.xsec-tools li.is-hit { border-color: var(--accent); background: var(--accent); color: #fff; }

/* AI and people: three roles on the AI side, a dashed red boundary, and
   the one role that hands over to a person on the other side. */
/* Four equal columns: the AI side spans three and uses the same gap inside,
   so all four roles are the same width. The boundary is drawn in the middle
   of the gap before the fourth. */
.ai-split { --g: clamp(28px, 3.4vw, 52px); display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: var(--g); margin-top: clamp(40px, 5vw, 64px); }
.is-ai { grid-column: span 3; }
.zone-label { display: flex; align-items: center; gap: 8px; padding-bottom: 18px; font-size: .9375rem; font-weight: var(--w-strong); }
.zone-label .ic { font-size: 20px; }
.is-ai .zone-label { color: var(--accent); }
.ai-roles { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--g); padding: 0; list-style: none; }
.is-people .ai-roles { grid-template-columns: minmax(0, 1fr); }
.ai-roles li { padding-top: 20px; border-top: 2px solid var(--accent); }
.is-people .ai-roles li { border-top-color: var(--ink); }
.ai-roles h3 { font-size: 1.25rem; font-weight: var(--w-strong); letter-spacing: var(--track-title); line-height: 1.3; }
.ai-roles p { margin-top: 8px; color: var(--ink-2); font-size: 1rem; line-height: 1.55; text-wrap: pretty; }
.is-people { position: relative; }
.is-people::before { content: ""; position: absolute; top: 0; bottom: 0; left: calc(var(--g) / -2); border-left: 1.5px dashed var(--accent); }
/* The section's conclusion, set large, with the boundary's dashed red rule
   running its full height. */
.ai-end {
  grid-column: 1 / -1;
  display: flex;
  gap: clamp(16px, 2vw, 24px);
  /* Breaks after "know" (17.8em of text, plus the rule and gap). */
  max-width: 19.5em;
  margin-top: clamp(48px, 6vw, 72px);
  font-size: clamp(1.625rem, 1.1rem + 1.5vw, 2.5rem);
  font-weight: var(--w-display);
  letter-spacing: var(--track-display);
  line-height: 1.12;
  text-wrap: wrap;
}
.ai-end::before { content: ""; flex: none; border-left: 2px dashed var(--accent); }

/* Build on what already works: the four decisions as marks, then the same
   marks on an example setup. */
.tech-build-grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: clamp(40px, 6vw, 96px); align-items: start; }
.tech-build-lead { max-width: 30em; margin-top: 20px; color: var(--ink-2); font-size: var(--fs-lead); line-height: 1.55; text-wrap: pretty; }
.tech-build-start { margin-top: 12px; font-size: var(--fs-lead); font-weight: var(--w-strong); }
.verbs { display: grid; gap: 14px; margin: 28px 0 0; }
.verbs div { display: grid; grid-template-columns: 88px minmax(0, 1fr); align-items: baseline; gap: 12px; }
.verbs dd { margin: 0; color: var(--ink-2); font-size: 1rem; line-height: 1.5; text-wrap: pretty; }
.verb { display: inline-block; padding: 2px 12px; border: 1px solid var(--line-2); border-radius: 99px; font-size: .8125rem; font-weight: var(--w-ui); line-height: 1.5; }
.verb.is-keep { border-color: var(--ink); color: var(--ink); }
.verb.is-connect { border-color: var(--accent); color: var(--accent); }
.verb.is-replace { border-style: dashed; border-color: var(--ink-3); color: var(--ink-3); }
.verb.is-add { border-color: var(--accent); background: var(--accent); color: #fff; }
.audit { margin: 0; border: 1px solid var(--line-2); border-radius: var(--r-l); background: var(--surface); box-shadow: var(--shadow-2); overflow: hidden; }
.audit figcaption { display: flex; align-items: center; gap: 12px; padding: 18px 22px; font-size: .9375rem; font-weight: var(--w-ui); text-wrap: pretty; }
.audit table { width: 100%; border-collapse: collapse; }
.audit th { padding: 10px 22px; border-block: 1px solid var(--line); background: var(--paper); color: var(--ink-3); font-size: .8125rem; font-weight: var(--w-ui); text-align: left; }
.audit td { padding: 16px 22px; border-bottom: 1px solid var(--line); font-size: 1rem; line-height: 1.45; vertical-align: middle; }
.audit tr:last-child td { border-bottom: 0; }
.audit td:last-child { width: 1%; white-space: nowrap; }
.audit .verb + .verb { margin-left: 6px; }

/* What every system we build must be: four principles, in white on the red band. */
.tech-principles h2 { max-width: 12em; }
.pp { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(24px, 3vw, 48px); margin-top: clamp(40px, 5vw, 64px); padding: 0; list-style: none; }
.pp li { padding-top: 22px; border-top: 1px solid rgba(255, 255, 255, .5); }
.pp .ic { font-size: 26px; }
.pp h3 { margin-top: 18px; font-size: 1.375rem; font-weight: var(--w-strong); letter-spacing: var(--track-title); line-height: 1.25; }
.pp p { margin-top: 8px; font-size: 1rem; line-height: 1.55; text-wrap: pretty; }

/* How we decide what to use: what we look at, then the answer, set so AI
   is one answer among several. */
.job-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(40px, 6vw, 96px); align-items: center; }
.job-grid h2 { max-width: 11em; }
.job-lead { margin-top: 20px; color: var(--ink-2); font-size: var(--fs-lead); line-height: 1.55; }
.factors { margin-top: 20px; padding: 0; list-style: none; counter-reset: factor; border-top: 1px solid var(--line-2); }
.factors li { counter-increment: factor; display: grid; grid-template-columns: 40px minmax(0, 1fr); padding: 12px 0; border-bottom: 1px solid var(--line); font-size: 1.0625rem; line-height: 1.45; text-wrap: pretty; }
.factors li::before { content: counter(factor, decimal-leading-zero); color: var(--accent); font-size: .8125rem; font-weight: var(--w-strong); line-height: 1.85; }
.job-answer { padding-left: clamp(24px, 3vw, 40px); border-left: 2px solid var(--accent); }
.job-answer p + p { margin-top: 32px; }
.ans-lead { display: block; margin-bottom: 6px; color: var(--ink-3); font-size: 1rem; font-weight: var(--w-ui); }
.ans { display: block; font-size: clamp(1.625rem, 1.1rem + 1.3vw, 2.25rem); font-weight: var(--w-display); letter-spacing: var(--track-display); line-height: 1.15; text-wrap: balance; }

/* One sentence per line. */
.tech-final h2 { max-width: 14.8em; }
.tech-final h2 > span { display: block; }
.tech-final p { max-width: 30em; }

@media (max-width: 1100px) {
  .tech-layers-head, .tech-ai-head { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .ai-split { --g: 24px; }
  .ai-roles p { font-size: .9375rem; }
}
@media (max-width: 959px) {
  .ai-split { grid-template-columns: minmax(0, 1fr); }
  .is-ai { grid-column: auto; }
  .is-people { margin-top: 36px; padding-top: 28px; }
  .is-people::before { right: 0; bottom: auto; left: 0; border-top: 1.5px dashed var(--accent); border-left: 0; }
  .tech-build-grid, .job-grid { grid-template-columns: minmax(0, 1fr); }
  .pp { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .xsec-band { grid-template-columns: minmax(0, 1fr); }
  .ai-roles { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 560px) {
  .ai-end, .tech-final h2 > span { text-wrap: balance; }
  .mix-tabs button { font-size: .8125rem; }
  .mix-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .xsec { padding-left: 48px; }
  .xsec-bubble::before { left: -36px; }
  .xsec-band::before { left: -42px; }
  .xsec-bubble { font-size: 1.0625rem; }
  .pp { grid-template-columns: minmax(0, 1fr); }
  .audit th, .audit td { padding-inline: 16px; }
  .verbs div { grid-template-columns: 80px minmax(0, 1fr); }
}

/* ---------- Industries page ---------- */

/* Hero: the copy, and beside it five customers asking five different
   questions, one per industry, arriving one after another. Each question
   jumps to its industry. */
/* "Customer communication" (12.1em) fits the column on one line; the
   lines step down from it, "every industry." kept whole. */
.ind-hero h1 { max-width: 12.3em; font-size: clamp(2rem, .85rem + 2.6vw, 3.375rem); text-wrap: wrap; }
/* One sentence per line where it fits: the first is 30.7em, and "We" no
   longer ends it (32.4em). */
.ind-hero .hero-sub { max-width: 31.4em; }
.ind-asks ul { display: grid; gap: 14px; padding: 0; list-style: none; }
.ind-asks li { display: flex; animation: ask-in .6s var(--ease-out) both; animation-delay: calc(var(--i) * 140ms + 150ms); }
.ind-asks li:nth-child(even) { justify-content: flex-end; }
@keyframes ask-in { from { opacity: 0; transform: translateY(10px); } }
.ind-asks a { display: grid; justify-items: start; gap: 6px; max-width: 82%; color: var(--ink); text-decoration: none; }
.ind-asks li:nth-child(even) a { justify-items: end; }
.ask-tag { color: var(--accent); font-size: .8125rem; font-weight: var(--w-strong); line-height: 1.2; }
.ask-bubble {
  padding: 11px 16px;
  border-radius: 18px 18px 18px 4px;
  background: var(--surface);
  box-shadow: 0 0 0 1px rgba(17, 17, 17, .05), 0 1px 2px rgba(17, 17, 17, .06), 0 14px 28px -16px rgba(17, 17, 17, .25);
  font-size: 1rem;
  font-weight: var(--w-ui);
  line-height: 1.4;
  transform-origin: top left;
  /* Touch: a press springs back at once. */
  transition: transform .2s var(--ease-out), box-shadow .3s;
}
.ind-asks a { -webkit-tap-highlight-color: transparent; }
.ind-asks li:nth-child(even) .ask-bubble { border-radius: 18px 18px 4px 18px; transform-origin: top right; }
/* Hover: the bubble grows from its top edge, down and outward, so it never
   reaches the industry name above it. Same spring as the Solutions cards. */
@media (hover: hover) {
  .ask-bubble { transition: transform .9s cubic-bezier(.22, 1, .36, 1), box-shadow .3s; }
  .ind-asks a:hover .ask-bubble {
    transform: scale(1.06);
    box-shadow: 0 0 0 1px rgba(17, 17, 17, .05), 0 1px 2px rgba(17, 17, 17, .06), 0 20px 36px -16px rgba(17, 17, 17, .3);
    transition: transform .45s cubic-bezier(.34, 1.45, .64, 1), box-shadow .3s;
  }
}
/* Press: a quick, plain ease-out, as on the buttons. */
.ind-asks a:active .ask-bubble { transform: scale(.97); transition: transform .12s var(--ease-out), box-shadow .3s; }
.ind-asks a:focus-visible { outline-offset: 4px; border-radius: 18px; }

/* The journey changes: the heading and its three lines, then the five
   industries side by side, parted by thin rules; each jumps to its
   chapter. */
.ind-head { display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); gap: clamp(32px, 5vw, 80px); align-items: end; }
.ind-head h2 { max-width: 11em; }
.ind-head-copy p { color: var(--ink-2); font-size: 1.0625rem; line-height: 1.6; text-wrap: pretty; }
.ind-head-copy p + p { margin-top: 10px; }
.ind-head-copy .ind-head-lead { color: var(--ink); font-size: var(--fs-lead); font-weight: var(--w-ui); line-height: 1.45; }
.ind-index { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); margin-top: clamp(48px, 6vw, 80px); padding: 0; list-style: none; border-block: 1px solid var(--line-2); }
.ind-index li + li { border-left: 1px solid var(--line); }
.ind-index a {
  display: grid;
  grid-template-rows: auto auto 1fr auto;
  gap: 10px;
  height: 100%;
  padding: 28px clamp(16px, 1.8vw, 24px);
  color: var(--ink);
  text-decoration: none;
  transition: background-color .25s;
}
.ind-index a > .ic:first-child { color: var(--accent); font-size: 28px; }
.ind-index h3 { margin-top: 6px; font-size: 1.1875rem; font-weight: var(--w-strong); letter-spacing: var(--track-title); line-height: 1.25; }
.ind-index p { color: var(--ink-2); font-size: .9375rem; line-height: 1.55; text-wrap: pretty; }
.ind-go { color: var(--ink-3); font-size: 18px; transition: transform .3s var(--ease-out), color .25s; }
@media (hover: hover) {
  .ind-index a:hover { background: var(--tint); }
  .ind-index a:hover .ind-go { color: var(--accent); transform: rotate(90deg) translateX(3px); }
}
.ind-index a { -webkit-tap-highlight-color: transparent; }
/* Press: the card darkens at once (tone, not scale, inside its rules). */
.ind-index a:active { background: var(--grey-100); transition-duration: .08s; }

/* The five chapters: the industry's copy on one side, its example on the
   other, swapping sides each time; a line at the content width between
   them. A jump from the hero lands the chapter's top at the top of the
   screen (the nav slides away on the way down). */
.ind { scroll-margin-top: calc(-1 * (var(--nav-h) + 16px)); }
.ind + .ind { background: linear-gradient(var(--line-2), var(--line-2)) top center / min(var(--wrap), 100% - var(--gutter) * 2) 1px no-repeat; }
.ind-grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: clamp(40px, 6vw, 96px); align-items: center; }
.ind.is-flip .ind-grid { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); }
.ind.is-flip .ind-copy { order: 2; }
.ind-ic { display: block; color: var(--accent); }
.ind-ic .ic { font-size: 32px; }
.ind-copy h2 { margin-top: 18px; font-size: clamp(2.25rem, 1.5rem + 2.4vw, 3.5rem); }
.ind-sub {
  max-width: 17em;
  margin-top: 14px;
  font-size: clamp(1.25rem, 1.05rem + .6vw, 1.5rem);
  font-weight: var(--w-ui);
  line-height: 1.3;
  letter-spacing: var(--track-title);
  text-wrap: balance;
}
.ind-body { max-width: 34em; margin-top: 16px; color: var(--ink-2); font-size: 1.0625rem; line-height: 1.6; text-wrap: pretty; }
.ind-sub + .ind-body { margin-top: 22px; }
.ind-note { max-width: 32em; margin-top: 24px; padding-left: 18px; border-left: 2px solid var(--accent); font-size: 1.0625rem; font-weight: var(--w-ui); line-height: 1.55; text-wrap: pretty; }

/* The example: the conversation from the customer's side, with what the
   system did behind the reply as a margin note. No phone, no window: the
   bubbles sit on the page. The messages arrive once, in order (main.js). */
.convo { margin: 0; }
.convo-head { display: flex; align-items: center; gap: 12px; color: var(--ink-3); font-size: .875rem; font-weight: var(--w-ui); }
.convo-msgs { display: grid; gap: 14px; margin-top: 22px; padding: 0; list-style: none; }
.c-in, .c-out { max-width: 82%; padding: 12px 18px; font-size: 1.0625rem; line-height: 1.45; text-wrap: pretty; }
.c-in { justify-self: start; border-radius: 18px 18px 18px 4px; background: var(--bubble-in); }
.c-out { justify-self: end; border-radius: 18px 18px 4px 18px; background: var(--bubble-out); }
.c-notes { justify-self: end; width: min(82%, 420px); padding: 2px 0 2px 16px; border-left: 2px solid var(--accent); }
.c-notes p { color: var(--accent); font-size: .75rem; font-weight: var(--w-strong); line-height: 1.4; }
.c-notes ul { display: grid; gap: 4px; margin-top: 6px; padding: 0; list-style: none; }
.c-notes li { color: var(--ink-2); font-size: .9375rem; line-height: 1.45; text-wrap: pretty; }
/* While the conversation waits to play, each bubble sits a little small at
   its speaker's corner, so it arrives from that side. */
.c-in { transform-origin: 0 100%; }
.c-out { transform-origin: 100% 100%; }
.is-seq-pending :is(.c-in, .c-out):not(.is-on) { transform: translateY(10px) scale(.96); }
.c-if { justify-self: end; width: min(82%, 420px); padding: 2px 0 2px 16px; border-left: 2px dashed var(--line-2); color: var(--ink-3); font-size: .9375rem; line-height: 1.45; text-wrap: pretty; }

/* Two lines: "What does customer communication" (17em), then the rest. */
.ind-final h2 { max-width: 17.4em; }
/* Breaks after "repeats work," (32.25em), so the phrase stays whole. */
.ind-final p { max-width: 32.6em; }

@media (max-width: 1100px) {
  /* Three across, then two wider ones: no empty cell. */
  .ind-index { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .ind-index li { grid-column: span 2; }
  .ind-index li:nth-child(n + 4) { grid-column: span 3; }
  .ind-index li:nth-child(4) { border-left: 0; }
  .ind-index li:nth-child(n + 4) { border-top: 1px solid var(--line); }
}
@media (max-width: 959px) {
  .ind-head { grid-template-columns: minmax(0, 1fr); gap: 20px; }
  .ind-grid, .ind.is-flip .ind-grid { grid-template-columns: minmax(0, 1fr); }
  .ind.is-flip .ind-copy { order: 0; }
}
@media (max-width: 760px) {
  .ind-index { grid-template-columns: minmax(0, 1fr); }
  .ind-index li, .ind-index li:nth-child(n + 4) { grid-column: auto; }
  .ind-index li + li { border-top: 1px solid var(--line); border-left: 0; }
  .ind-index a { grid-template-columns: 28px minmax(0, 1fr) auto; grid-template-rows: auto auto; column-gap: 14px; row-gap: 4px; padding: 18px 4px; }
  .ind-index a > .ic:first-child { grid-row: span 2; font-size: 24px; }
  .ind-index h3 { margin-top: 0; }
  .ind-index p { grid-column: 2; }
  .ind-go { grid-column: 3; grid-row: 1 / span 2; align-self: center; }
}
@media (max-width: 560px) {
  .ind-asks a { max-width: 92%; }
  .c-in, .c-out, .c-notes, .c-if { max-width: 92%; width: auto; }
}

/* ---------- About page ---------- */

/* Hero: the copy, and beside it why Axalus exists: every part of a business
   is looked after by a team, apart from the conversation that runs through
   all of them. That gap is grey and dashed (the diagram colour roles), and
   the answer is red. The rows arrive one after another, the gap last. */
/* Three lines, breaking after "build the" and "customer" (12em). Phones are
   too narrow for "systems behind customer", so there it breaks after
   "build" and "behind" instead. */
.about-hero h1 { max-width: 12em; font-size: clamp(2rem, .85rem + 2.6vw, 3.375rem); text-wrap: wrap; }
@media (max-width: 440px) { .about-hero h1 { max-width: 10.6em; } }
.owns {
  margin: 0;
  padding: 22px 28px 24px;
  border-radius: var(--r-xl);
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-card);
}
/* First load: the card settles in with the copy; its rows then arrive in it. */
@media (prefers-reduced-motion: no-preference) {
  .js .owns { animation: hero-in .7s var(--ease-out) 100ms both; }
}
.owns-cap { color: var(--ink-3); font-size: .875rem; font-weight: var(--w-ui); line-height: 1.4; }
.owns-list { margin: 12px 0 0; }
.owns-list > div, .owns-foot { animation: ask-in .6s var(--ease-out) both; animation-delay: calc(var(--i) * 110ms + 200ms); }
.owns-list > div { display: flex; align-items: center; justify-content: space-between; gap: 20px; padding: 11px 0; border-top: 1px solid var(--line); }
.owns-list dt { font-size: 1rem; line-height: 1.4; }
.owns-list dd { flex: none; margin: 0; padding: 3px 12px; border: 1px solid var(--line-2); border-radius: 999px; color: var(--ink-2); font-size: .8125rem; font-weight: var(--w-ui); line-height: 1.5; }
.owns-list .is-gap { padding-block: 16px; animation-delay: 1s; }
.owns-list .is-gap dt { max-width: 15em; font-weight: var(--w-strong); text-wrap: pretty; }
.owns-list .is-gap dd { border: 1.5px dashed var(--ink-3); color: var(--ink-3); }
.owns-foot {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  color: var(--accent);
  font-size: 1.125rem;
  font-weight: var(--w-strong);
  letter-spacing: var(--track-title);
  line-height: 1.3;
  animation-delay: 1.4s;
}
.owns-foot::before { content: ""; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); }

/* What we are, and what we aren't: three kinds of company we're mistaken
   for, each struck through in red as it scrolls in, and what we are
   instead beneath it.
   Each label stays on one line: the size tracks the column, so the
   longest, "A software company" (9.4em), always fits; below 960px they
   stack. */
/* One line where it fits; "What we are," never ends a line on its own. */
.nots-head h2 { max-width: 15.4em; }
.nots-head .lead { max-width: 30em; }
.nots { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: clamp(32px, 4vw, 64px); margin-top: clamp(48px, 6vw, 80px); padding: 0; list-style: none; }
.not { padding-bottom: 22px; border-bottom: 1px solid var(--line-2); color: var(--ink-3); font-size: clamp(1.625rem, 2.95vw - 2px, 2.125rem); font-weight: var(--w-display); letter-spacing: var(--track-display); line-height: 1.15; }
.not s {
  text-decoration: none;
  background: linear-gradient(var(--accent), var(--accent)) no-repeat 0 57% / 100% 3px;
  transition: background-size .8s var(--ease-out) .3s;
}
.is-seq-pending .nots li:not(.is-on) s { background-size: 0 3px; transition: none; }
.nots h3 { margin-top: 24px; font-size: 1.375rem; font-weight: var(--w-strong); letter-spacing: var(--track-title); line-height: 1.25; }
.nots h3 + p { max-width: 24em; margin-top: 10px; color: var(--ink-2); font-size: 1.0625rem; line-height: 1.6; text-wrap: pretty; }

/* What we won't do: four lines on the red, each a sentence in display type
   with what it means beneath it, between white rules. */
.wont-grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: clamp(40px, 6vw, 96px); align-items: start; }
.wont-head h2 { max-width: 9em; }
.wont-head .lead { max-width: 18em; }
.wont { padding: 0; list-style: none; border-top: 1px solid rgba(255, 255, 255, .45); }
.wont li { padding: 28px 0 30px; border-bottom: 1px solid rgba(255, 255, 255, .45); }
.wont h3 { font-size: clamp(1.5rem, 1.15rem + 1vw, 2rem); font-weight: var(--w-display); letter-spacing: var(--track-display); line-height: 1.15; }
.wont p { max-width: 34em; margin-top: 10px; color: #fff; font-size: 1.0625rem; line-height: 1.6; text-wrap: pretty; }

/* Who we work with: who we're for and who we aren't, beside a short
   self-check. Ticking a line updates the count beneath (main.js); without
   script the boxes still tick and the count stays hidden. */
.fit-grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: clamp(40px, 6vw, 96px); align-items: start; }
.fit-copy h2 { max-width: 10em; }
.fit-copy .lead { max-width: 24em; }
.fit-not { margin-top: 40px; padding-top: 26px; border-top: 1px solid var(--line-2); }
.fit-not-title { font-size: 1.0625rem; font-weight: var(--w-strong); line-height: 1.5; }
.fit-not ul { display: grid; gap: 10px; margin-top: 14px; padding: 0; list-style: none; }
.fit-not li { position: relative; padding-left: 26px; color: var(--ink-2); font-size: 1.0625rem; line-height: 1.55; text-wrap: pretty; }
.fit-not li::before { content: ""; position: absolute; top: 12px; left: 2px; width: 12px; height: 2px; background: var(--line-2); }
.fit-not-end { margin-top: 18px; font-size: 1.0625rem; font-weight: var(--w-ui); line-height: 1.5; }

.fit-check { min-width: 0; margin: 0; padding: 0 32px 26px; border: 1px solid var(--line-2); border-radius: var(--r-xl); background: var(--surface); box-shadow: var(--shadow-2); }
.fit-check legend { float: left; width: 100%; padding: 26px 0 14px; font-size: 1.375rem; font-weight: var(--w-strong); letter-spacing: var(--track-title); line-height: 1.25; }
.fit-sign {
  position: relative;
  clear: both;
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr);
  gap: 16px;
  align-items: start;
  padding: 16px 0;
  border-top: 1px solid var(--line);
  font-size: 1.0625rem;
  line-height: 1.5;
  text-wrap: pretty;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.fit-sign input { position: absolute; top: 18px; left: 0; width: 22px; height: 22px; margin: 0; opacity: 0; }
.fit-box { position: relative; width: 22px; height: 22px; margin-top: 2px; border: 1.5px solid var(--line-2); border-radius: 6px; background: var(--surface); transition: background-color .2s, border-color .2s, transform .12s var(--ease-out); }
/* Press: the box gives a little under the finger or the click. */
.fit-sign:active .fit-box { transform: scale(.9); }
.fit-box::after {
  content: "";
  position: absolute;
  top: 2px;
  left: 6px;
  width: 6px;
  height: 11px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  /* The tick grows from half size as it fades in, never from nothing. */
  opacity: 0;
  transform: rotate(45deg) scale(.5);
  transition: transform .25s var(--ease-out), opacity .15s;
}
.fit-sign input:checked + .fit-box { border-color: var(--accent); background: var(--accent); }
.fit-sign input:checked + .fit-box::after { opacity: 1; transform: rotate(45deg) scale(1); }
.fit-sign input:focus-visible + .fit-box { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (hover: hover) { .fit-sign:hover input:not(:checked) + .fit-box { border-color: var(--ink-3); } }
.fit-count { display: none; padding-top: 18px; border-top: 1px solid var(--line); color: var(--ink-3); font-size: 1rem; font-weight: var(--w-ui); line-height: 1.5; transition: color .2s; }
.js .fit-count { display: block; }
.fit-count.is-on { color: var(--accent); }

/* One sentence per line, as on Technology: "Now tell us about your
   customers." is 15.3em. */
.about-final h2 { max-width: 15.6em; }
.about-final h2 > span { display: block; text-wrap: balance; }
/* Breaks after "reach you today," (28.1em), so the phrase stays whole. */
.about-final p { max-width: 28.5em; }

@media (max-width: 959px) {
  .wont-grid, .fit-grid, .nots { grid-template-columns: minmax(0, 1fr); }
  .nots { gap: 48px; }
  .owns { max-width: 520px; }
}
@media (max-width: 560px) {
  .owns { padding-inline: 20px; }
  .fit-check { padding-inline: 20px; }
}

/* ---------- Discovery Call page ---------- */

/* Hero: what the call is for (what you bring, what you leave with) beside
   the request form, in a white card that runs past the foot of the grey band
   into the questions below. */
.dc-hero, .dc-faq { --dc-overlap: clamp(72px, 9vw, 136px); }
.dc-hero .hero-top { align-items: flex-start; min-height: 0; padding-block: clamp(40px, 6vw, 80px) 0; }
@media (min-width: 1024px) { .dc-hero .hero-top { padding-top: var(--hero-gap); } }
.dc-grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); gap: clamp(40px, 6vw, 96px); align-items: start; }
.dc-copy { padding-bottom: clamp(56px, 7vw, 96px); }
.dc-hero h1 { text-wrap: wrap; }
/* Breaks after "where things" (23.2em), so the top line is the longer one. */
.dc-hero .hero-sub { max-width: 24em; text-wrap: wrap; }
.dc-swap { display: grid; gap: 28px; margin-top: clamp(40px, 5vw, 56px); padding-top: 32px; border-top: 1px solid var(--line-2); }
.dc-side + .dc-side { padding-top: 28px; border-top: 1px solid var(--line); }
.dc-side-title { font-size: 1.0625rem; font-weight: var(--w-strong); letter-spacing: 0; line-height: 1.4; }
.dc-side ul { display: grid; gap: 8px; margin-top: 12px; padding: 0; list-style: none; }
.dc-side li { position: relative; padding-left: 20px; font-size: 1.0625rem; line-height: 1.5; text-wrap: pretty; }
/* First load: the copy settles in line by line, as on every page, and the
   form card arrives with it. Quick, so the form is ready to use at once. */
@media (prefers-reduced-motion: no-preference) {
  .js .dc-copy > * { animation: hero-in .7s var(--ease-out) both; }
  .js .dc-copy > :nth-child(2) { animation-delay: 60ms; }
  .js .dc-copy > :nth-child(3) { animation-delay: 120ms; }
  .js .dc-card { animation: hero-in .7s var(--ease-out) 100ms both; }
}
.dc-side li::before { content: ""; position: absolute; top: .62em; left: 2px; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }

.dc-card {
  position: relative;
  z-index: 2;
  margin-bottom: calc(-1 * var(--dc-overlap));
  padding: clamp(24px, 3vw, 40px);
  border-radius: var(--r-xl);
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 0 0 1px rgba(17, 17, 17, .05), 0 1px 2px rgba(17, 17, 17, .06), 0 32px 64px -32px rgba(17, 17, 17, .28), 0 12px 40px -12px rgba(17, 17, 17, .1);
  scroll-margin-top: calc(var(--nav-h) + 16px);
}
.dc-form { display: grid; gap: 20px; }
.dc-form-title { font-size: 1.375rem; font-weight: var(--w-strong); letter-spacing: var(--track-title); line-height: 1.25; }
.dc-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px 16px; }
.field { display: grid; align-content: start; gap: 8px; min-width: 0; margin: 0; padding: 0; border: 0; }
.field label, .field legend { font-size: .9375rem; font-weight: var(--w-ui); line-height: 1.4; text-wrap: pretty; }
/* "Optional" sits a gap after the question; where it wraps, it starts the
   next line flush instead of indented. */
.field > label, .field > legend { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 10px; }
.field legend { margin-bottom: 10px; padding: 0; }
fieldset.field { display: block; }
.opt { color: var(--ink-3); font-size: .8125rem; font-weight: 400; }
.field input, .field textarea {
  width: 100%;
  min-height: 48px;
  padding: 12px 14px;
  border: 1px solid var(--line-2);
  border-radius: 10px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 1rem;
  line-height: 1.4;
  transition: border-color .2s, box-shadow .2s;
}
.field textarea { min-height: 120px; resize: vertical; }
.field input::placeholder, .field textarea::placeholder { color: var(--ink-3); opacity: 1; }
@media (hover: hover) { .field input:hover, .field textarea:hover { border-color: var(--grey-300); } }
.field input:focus, .field textarea:focus { border-color: var(--accent); outline: none; box-shadow: 0 0 0 3px rgba(202, 23, 30, .16); }
/* An error has its own look, so it never reads as focus or as Axalus
   speaking: Red 50 fill and red border on the field (hover keeps them),
   a warning icon and the message in Red 700 (7.6:1). Focus stays the red
   border and glow, so a focused field with an error shows both. */
.field [aria-invalid="true"],
.field [aria-invalid="true"]:hover { border-color: var(--accent); background: var(--red-50); }
.field-err { color: var(--red-700); font-size: .875rem; font-weight: var(--w-ui); line-height: 1.4; }
.field-err:empty { display: none; }
.field-err:not(:empty) { display: flex; gap: 6px; align-items: flex-start; animation: err-in .2s var(--ease-out); }
.field-err:not(:empty)::before {
  content: "";
  flex: none;
  width: 16px;
  height: 16px;
  margin-top: 2px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0ZM7.1 4.5a.9.9 0 0 1 1.8 0v3.8a.9.9 0 0 1-1.8 0ZM8 10.55a1.05 1.05 0 1 0 0 2.1a1.05 1.05 0 0 0 0-2.1Z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0ZM7.1 4.5a.9.9 0 0 1 1.8 0v3.8a.9.9 0 0 1-1.8 0ZM8 10.55a1.05 1.05 0 1 0 0 2.1a1.05 1.05 0 0 0 0-2.1Z'/%3E%3C/svg%3E") center / contain no-repeat;
}
@keyframes err-in { from { opacity: 0; transform: translateY(-4px); } }
/* Sending with fields missing: each one gives a short shake, once. */
.field .is-shake { animation: field-shake .32s cubic-bezier(.36, .07, .19, .97); }
@keyframes field-shake { 20% { transform: translateX(-3px); } 40% { transform: translateX(3px); } 60% { transform: translateX(-2px); } 80% { transform: translateX(2px); } }

/* Team size and channels: optional, picked as chips. */
.chip-set { display: flex; flex-wrap: wrap; gap: 8px; }
.chip { position: relative; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.chip input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.chip span {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 40px;
  padding: 8px 14px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
  font-size: .9375rem;
  font-weight: var(--w-ui);
  line-height: 1.2;
  transition: border-color .2s, background-color .2s, color .2s, transform .12s var(--ease-out);
}
.chip:active span { transform: scale(.96); }
.chip .ic { color: var(--accent); font-size: 16px; transition: color .2s; }
@media (hover: hover) { .chip:hover input:not(:checked) + span { border-color: var(--ink-3); } }
.chip input:checked + span { border-color: var(--accent); background: var(--accent); color: #fff; }
.chip input:checked + span .ic { color: #fff; }
.chip input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }

.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
/* On the white card the button is the usual red one. */
.dc-hero .dc-card .btn-primary { background: var(--accent); }
.dc-submit { margin-top: 4px; }
.dc-send { width: 100%; }
.dc-send:disabled { opacity: .7; cursor: progress; }
.dc-status { margin-top: 12px; color: var(--ink-2); font-size: .9375rem; line-height: 1.5; text-align: center; }
.dc-status:empty { margin-top: 0; }

/* Sent: the form gives way to a short thank-you. */
.dc-done { display: grid; justify-items: start; gap: 14px; padding-block: 16px 8px; }
.dc-form[hidden], .dc-done[hidden] { display: none; }
.dc-done-ic { color: var(--accent); font-size: 40px; line-height: 0; }
/* Rare and earned: the thank-you settles in, its tick with a little spring. */
.dc-done:not([hidden]) { animation: hero-in .5s var(--ease-out) both; }
.dc-done:not([hidden]) .dc-done-ic { animation: done-pop .5s cubic-bezier(.34, 1.45, .64, 1) 80ms both; }
@keyframes done-pop { from { opacity: 0; transform: scale(.6); } }
.dc-done h2 { max-width: 14em; font-size: clamp(1.625rem, 1.2rem + 1vw, 2rem); }
.dc-done h2:focus { outline: none; }
.dc-done p { color: var(--ink-2); font-size: 1.0625rem; line-height: 1.6; }
.dc-done strong { color: var(--ink); font-weight: var(--w-strong); }
.dc-hero .dc-done .link { margin-top: 6px; color: var(--accent); }

/* Questions before the call: an accordion beside the heading, clear of the
   form card above it. */
.dc-faq { padding-top: calc(var(--dc-overlap) + clamp(64px, 8vw, 112px)); }
.faq-grid { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: clamp(40px, 6vw, 96px); align-items: start; }
/* "Questions before" (7.8em), then "the call." */
.faq-grid h2 { max-width: 8em; text-wrap: wrap; }
.faq { border-top: 1px solid var(--line-2); interpolate-size: allow-keywords; }
/* Opening eases the answer down; closing is quicker. Browsers without
   ::details-content simply open and close at once. */
.faq details::details-content { block-size: 0; overflow: clip; transition: block-size .2s var(--ease-out), content-visibility .2s allow-discrete; }
.faq details[open]::details-content { block-size: auto; transition-duration: .3s; }
.faq details[open] p { animation: hero-in .3s var(--ease-out); }
.faq details { border-bottom: 1px solid var(--line-2); }
.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  padding: 24px 0;
  font-size: 1.25rem;
  font-weight: var(--w-strong);
  letter-spacing: var(--track-title);
  line-height: 1.35;
  text-wrap: pretty;
  list-style: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color .2s;
}
.faq summary:active { color: var(--accent); }
.faq summary::-webkit-details-marker { display: none; }
@media (hover: hover) { .faq summary:hover { color: var(--accent); } }
.faq summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: 4px; }
.faq-mark { position: relative; flex: none; width: 18px; height: 18px; }
.faq-mark::before, .faq-mark::after { content: ""; position: absolute; top: 8px; left: 0; width: 18px; height: 2px; border-radius: 2px; background: var(--accent); transition: transform .3s var(--ease-out); }
.faq-mark::after { transform: rotate(90deg); }
.faq details[open] .faq-mark::after { transform: none; }
.faq details p { max-width: 36em; padding: 0 40px 26px 0; color: var(--ink-2); font-size: 1.0625rem; line-height: 1.6; text-wrap: pretty; }
/* Where the link wraps, it starts the next line flush instead of indented. */
.faq-end { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 10px; margin-top: 28px; color: var(--ink-2); font-size: 1.0625rem; line-height: 1.6; }
.ic-up { transform: rotate(-90deg); }
.link:hover .ic-up { transform: rotate(-90deg) translateX(3px); }

/* One column: the form follows the subheading, and what you bring and
   leave with comes after it, still on the grey. */
@media (max-width: 959px) {
  .dc-hero, .dc-faq { --dc-overlap: 0px; }
  .dc-grid, .faq-grid { grid-template-columns: minmax(0, 1fr); }
  .dc-grid { row-gap: 0; }
  .dc-copy { display: contents; }
  .dc-hero h1 { order: 1; }
  .dc-hero .hero-sub { order: 2; }
  .dc-card { order: 3; max-width: 640px; margin-top: 36px; }
  .dc-swap { order: 4; max-width: 640px; margin-top: 48px; margin-bottom: clamp(56px, 9vw, 80px); }
}
@media (max-width: 560px) {
  .dc-row { grid-template-columns: minmax(0, 1fr); }
  .dc-card { padding: 24px 20px; }
  .faq summary { font-size: 1.125rem; }
  .faq details p { padding-right: 0; }
}

/* ---------- Responsive ---------- */

@media (max-width: 1100px) {
  .layers { grid-template-columns: minmax(0, 1fr); }
  .layers-copy { max-width: 640px; }
}

/* The full nav row (logo, six links) needs about 720px; below 760px the links
   move into the menu so they never squeeze or wrap. main.js closes the menu at 760px. */
@media (max-width: 759px) {
  .nav-links { display: none; }
  .nav-end { display: flex; margin-left: auto; }
  .nav-toggle { display: grid; }
}

@media (max-width: 959px) {
  .fixes { grid-template-columns: minmax(0, 1fr); max-width: 560px; margin-inline: auto; }

  .problem-grid { grid-template-columns: minmax(0, 1fr); }
  .problem-head { position: static; }
  .problem-head h2 { max-width: 10.6em; }



  .example-grid { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .phone { height: clamp(300px, 42svh, 520px); min-height: 0; max-width: none; border-radius: 22px; }
  .example-title { font-size: 1.875rem; line-height: 1.15; }
  .ex-label {
    display: block;
    margin-bottom: 14px;
    color: var(--accent);
    font-size: .8125rem;
    font-weight: var(--w-ui);
    letter-spacing: .3em;
    text-transform: uppercase;
  }
  .ex-colon { display: none; }
  .example-intro { margin-top: 12px; font-size: 1.0625rem; line-height: 1.45; }
  .example-sys { margin-top: 24px; font-size: .9375rem; }
  /* Stacked: the example's title and intro sit above the chat window; the
     step list stays below it. */
  .example-steps { display: contents; }
  .example-steps > * { order: 2; }
  .example-phone-col { order: 1; }
  .example-steps > .example-title { order: -2; }
  .example-steps > .example-intro { order: -1; margin: -4px 0 8px; }
  .steps { display: flex; justify-content: space-between; gap: 4px; margin-top: 8px; }
  .step { display: block; width: auto; min-height: 0; padding: 3px; border-radius: 50%; }
  .step::before { width: 32px; height: 32px; }
  /* Narrow phones: smaller dots, so all eight fit across. */
  @media (max-width: 400px) {
    .step { padding: 1px; }
    .step::before { width: 30px; height: 30px; }
  }
  .step-text { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .step:hover { background: none; }
  .step:active { transform: scale(.9); }
  .js .steps li.is-active .step { border-color: transparent; background: none; box-shadow: none; }
  /* With script, the numbered dots give way to the current step alone,
     which the scroll moves on (main.js). */
  .js .steps { display: none; }
  .step-now { display: flex; align-items: center; gap: 20px; min-height: 3.1em; margin-top: 16px; color: var(--ink-2); font-size: 1.125rem; line-height: 1.5; }
  .step-now strong { flex: none; align-self: stretch; display: flex; align-items: center; margin-left: 12px; padding-right: 20px; border-right: 1px solid var(--line); color: var(--accent); font-size: 2.75rem; font-weight: 400; line-height: 1; }
  /* Stacked layout, with script: "The system:" over the current step alone,
     a numbered circle and its text; the scroll moves it on (main.js sets
     the classes). */
  .js .example-sys { margin-top: 6px; color: var(--ink-3); font-size: .8125rem; font-weight: var(--w-ui); letter-spacing: .3em; text-transform: uppercase; }
  .js .step-now { display: none; }
  .js .steps { display: grid; gap: 0; margin-top: 0; min-height: 66px; align-content: start; }
  /* Steps outside the window collapse rather than display:none, so the
     CSS counter still numbers them correctly. */
  .js .steps li { position: relative; height: 0; overflow: hidden; visibility: hidden; }
  .js .steps li.is-active,
  .js .steps:not(:has(.is-active)) li:first-child { height: auto; overflow: visible; visibility: visible; }
  .js .steps .step { display: grid; grid-template-columns: 44px minmax(0, 1fr); width: 100%; padding: 7px 0; border: 0; border-radius: 0; font-size: 1.0625rem; line-height: 1.4; }
  .js .steps .step::before { width: 30px; height: 30px; }
  .js .steps .step-text { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal; }
  .js .steps li.is-active .step { color: var(--ink); font-weight: var(--w-strong); }
  /* Touch: each dot answers a tap about 44px across, reaching into the
     gaps beside it (on the narrowest phones neighbours meet mid-gap). */
  @media (pointer: coarse) {
    .step::after { content: ""; position: absolute; inset: -6px -5px; border-radius: 50%; }
  }
  .example-after { grid-template-columns: minmax(0, 1fr); }
  .handoff { grid-column: 1; }


  .footer-top { grid-template-columns: minmax(0, 1fr); }

  .area-grid { grid-template-columns: minmax(0, 1fr); }
  .walk { position: static; justify-self: stretch; max-width: none; }
  .area-sub { max-width: 24ch; }
  .sol-hero-grid { grid-template-columns: minmax(0, 1fr); }
  .sol-map { max-width: 560px; margin-top: 8px; }
  .hero.sol-hero .hero-top { padding-bottom: clamp(56px, 9vw, 80px); }
  .q-grid { grid-template-columns: minmax(0, 1fr); }
  .q-head { position: static; }
}

@media (max-width: 760px) {
  /* Phones: the board becomes the list of steps, each naming its channels
     and systems. */
  .layers-board { display: block; }
  .layers-board .wires, .tier-label, .tier-channels, .tier-systems, .layers-hint { display: none; }
  .tier-process { grid-template-columns: minmax(0, 1fr); }
  .tier-process li { grid-template-columns: auto minmax(0, 1fr); align-items: center; column-gap: 12px; min-height: 0; padding: 14px 16px; font-size: .9375rem; }
  .tier-process .ic { color: var(--accent); }
  .tier-process .uses { position: static; grid-column: 2; display: grid; gap: 2px; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal; color: var(--ink-3); font-size: .8125rem; }
  .tier-process .uses b { margin-right: 6px; color: var(--ink-2); }

  /* Phones: the steps stack on a rail that fills red as you read down. */
  .route-art { display: none; }
  .route-steps { position: relative; grid-template-columns: minmax(0, 1fr); margin-top: 0; padding-left: 40px; }
  .route-steps::before { content: ""; position: absolute; top: 12px; bottom: 12px; left: 8px; border-left: 1.5px dashed var(--line-2); }
  .route-steps::after { content: ""; position: absolute; top: 12px; left: 7.5px; width: 2px; height: calc((100% - 24px) * var(--fill, 1)); border-radius: 2px; background: var(--accent); }
  .route-steps li { position: relative; padding: 0 0 36px; border-left: 0; }
  .route-steps li:first-child { padding-left: 0; }
  .route-steps li:last-child { padding-bottom: 0; }
  .route-steps li::before {
    content: "";
    position: absolute;
    z-index: 1;
    top: 4px;
    left: -40px;
    width: 18px;
    height: 18px;
    border: 1.5px solid var(--line-2);
    border-radius: 50%;
    background: var(--surface);
    box-shadow: inset 0 0 0 4px var(--surface);
    transform: scale(.9);
    transition: transform .45s var(--ease-out) .2s, background-color .35s .2s, border-color .35s .2s;
  }
  .route-steps li.is-on::before { border-color: var(--accent); background: var(--accent); transform: none; }
  /* The button follows the stacked steps, on the same left edge. */
  .route-cta { justify-content: flex-start; }
  .modules { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .module { padding: 0 0 32px; }
  .module + .module { padding: 28px 0 32px; border-left: 0; border-top: 1px solid rgba(255, 255, 255, .3); }
  .module:last-child { padding-bottom: 0; }
  .module-num { margin-bottom: 8px; }
  /* Two lines each, the top one longest. */
  .module-tag { max-width: 13em; text-wrap: pretty; }
  .journey-areas { display: none; }
  .journey-board .tier-process { grid-template-columns: minmax(0, 1fr); }
  .section-head { flex-direction: column; align-items: flex-start; gap: 20px; }
  .incident { grid-template-columns: minmax(0, 1fr); }
  .incident-copy p { font-size: 1.0625rem; }
}

@media (max-width: 560px) {
  .actions .btn, .final-actions .btn { width: 100%; }
  .sheet-row { font-size: .75rem; }
  .q-row { grid-template-columns: minmax(0, 1fr); }
  .sol-stop { column-gap: 18px; padding: 16px 18px 16px 22px; }
  .sol-step + .sol-step::before, .sol-step + .sol-step::after { left: 42px; }
  .sol-stop strong { font-size: 1.25rem; }
  .walk-row { grid-template-columns: 36px minmax(0, 1fr); column-gap: 14px; font-size: 1rem; }
  .walk-tag { grid-column: 2; justify-self: start; margin-top: 6px; }
}

/* Short laptop screens (about 1366 × 660): the step list sets tighter, so it
   still fits between two nav heights and the returning nav never covers it. */
@media (min-width: 960px) and (max-height: 720px) {
  .example-title { font-size: 1.375rem; }
  .example-sys { margin-top: 12px; }
  .steps { margin-top: 8px; }
  .step { padding-block: 4px; line-height: 1.35; }
}

@media (max-height: 619px) {
  .example-scroll { height: auto; }
  .example-pin { position: static; height: auto; padding-block: 24px; }
}
.example-scroll.is-done { height: auto; }
.example-scroll.is-done .example-pin { position: static; height: auto; padding-block: 24px; }

/* ---------- Reduced motion ---------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-delay: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    transition-delay: 0s !important;
  }
}

/* Final CTA on red */
.final.band-red .final-lines { background: radial-gradient(circle at 1px 1px, rgba(255, 255, 255, .16) 1px, transparent 0) 0 0 / 24px 24px; }
.final.band-red p { color: #fff; }

/* ---------- Home on phones ---------- */
@media (max-width: 760px) {
  /* One size for every section headline, with a little more room under it.
     (The closing question already sets 36px and its own spacing.) */
  #problem-title, #outcomes-title, #process-title, #build-title, #example-title { margin-bottom: 12px; font-size: 2.25rem; }
  /* The workflow: the steps card comes before "Start with what should
     happen…". */
  .layers-board { order: -1; }
  /* The worked example: the chat window takes the screen's spare height,
     with more room under it; the content sits low in the pinned screen,
     clear of the nav when it comes back. */
  .example-pin { align-items: flex-end; padding-bottom: 24px; }
  .example-grid { gap: 12px; }
  /* "The system:" and the current step share one line under the chat. */
  .js .example-grid { grid-template-columns: auto minmax(0, 1fr); column-gap: 10px; }
  .js .example-grid > .example-phone-col,
  .js .example-grid > .example-steps > .example-title,
  .js .example-grid > .example-steps > .example-intro { grid-column: 1 / -1; }
  .js .example-sys { margin-top: 0; letter-spacing: .2em; }
  .js .steps { min-height: 44px; align-content: center; }
  /* The same room above and below the chat window on the page. */
  .example-phone-col { margin-block: 20px 16px; }
  .example-pin { padding-bottom: 14px; }
  .ex-label { margin-bottom: 8px; }
  .phone { height: clamp(240px, calc(100svh - 322px), 560px); }
}

/* ---------- Closing band on larger screens ----------
   The question in three lines ("Where is customer / communication costing
   you time, / leads, or repeat business?"), the line under it in two, a
   larger button with a soft shadow, the dot grid along the sides (clear
   behind the copy) and a soft light at the top. */
.d-br { display: none; }
@media (min-width: 761px) {
  .d-br { display: inline; }
  .home-final { padding-block: clamp(112px, 10vw, 148px); background-image: radial-gradient(45% 60% at 50% 0%, rgba(255, 255, 255, .07), transparent 70%); }
  .home-final .final-lines {
    -webkit-mask-image: radial-gradient(50% 75% at 50% 50%, transparent 35%, #000 100%);
    mask-image: radial-gradient(50% 75% at 50% 50%, transparent 35%, #000 100%);
  }
  .home-final p { max-width: 31em; margin-top: 28px; }
  .home-final .btn { --btn-h: 64px; padding-inline: 56px; border-radius: 14px; font-size: 1.125rem; box-shadow: 0 16px 32px -12px rgba(17, 17, 17, .5); }
}

/* ---------- Footer on phones ----------
   The line sits beside the robot, each sentence over two lines, the wire
   running just under it. */
@media (max-width: 760px) {
  .footer-stage .wrap { padding-bottom: 20px; }
  .footer-line { max-width: 7.2em; }
  .footer-line > span { text-wrap: wrap; }
  .footer-line > span + span { margin-top: .4em; }
  /* The robot sits 60px further right, clear of the line; the wire slice
     follows so the wire still runs edge to edge. */
  .footer-stage::before { background-position: right -60px bottom; }
  .footer-stage::after { right: 664px; }
}
