@font-face {
  font-family: "JetBrains Mono";
  src: url("/assets/fonts/JetBrainsMono-SemiBold.ttf") format("truetype");
  font-display: swap;
  font-style: normal;
  font-weight: 600;
}

@font-face {
  font-family: "JetBrains Mono";
  src: url("/assets/fonts/JetBrainsMono-ExtraBold.ttf") format("truetype");
  font-display: swap;
  font-style: normal;
  font-weight: 800;
}

@font-face {
  font-family: "Josefin Sans";
  src: url("/assets/fonts/JosefinSans-SemiBold.ttf") format("truetype");
  font-display: swap;
  font-style: normal;
  font-weight: 600;
}

:root {
  --charcoal: #101925;
  --amber: #ffb804;
  --white: #ffffff;
  --mist: #ebf0fa;
  /* Theme colours. Light is the default; the dark theme redefines them. Every
     section, the header, the logo and the diagram draw from these. The
     sections alternate between two shades: --page (the header, hero, How we
     work, Getting started and footer) and --surface-pale (Services and
     About). */
  --page: var(--white);
  --surface-pale: var(--mist); /* also the email template, on Getting started */
  --ink: var(--charcoal); /* text, logo, diagram and icon lines */
  --ink-soft: #3d4859; /* supporting text */
  --ink-rgb: 16, 25, 37; /* translucent rules */
  --accent-ink: #8f5d00; /* amber as text on light backgrounds (5.2:1) */
  --focus: #8f5d00; /* focus rings */
  --rule: rgba(16, 25, 37, 0.2); /* the header's bottom rule */
  --tip: var(--charcoal);
  --tip-ink: var(--white);
  color-scheme: light;
  --page-gutter: clamp(1.25rem, 5vw, 5rem);
  --header-gutter: var(--page-gutter); /* the header's side padding */
  --page-width: 90rem;
  --header-logo-width: clamp(11rem, 18vw, 16rem);
  --header-control-width: 2.75rem;
  --display: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --body: "Helvetica Neue", Arial, ui-sans-serif, system-ui, sans-serif;
  --label: "Josefin Sans", "Helvetica Neue", Arial, ui-sans-serif, system-ui, sans-serif;
}

/* Dark theme: the brand charcoal throughout. The visitor's choice (theme.js),
   or the system setting until they choose. */
:root[data-theme="dark"] {
  --page: var(--charcoal);
  --surface-pale: #1a2738;
  --ink: var(--white);
  --ink-soft: var(--mist);
  --ink-rgb: 235, 240, 250;
  --accent-ink: var(--amber);
  --focus: var(--amber);
  --rule: rgba(235, 240, 250, 0.52);
  --tip: var(--mist);
  --tip-ink: var(--charcoal);
  color-scheme: dark;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --page: var(--charcoal);
    --surface-pale: #1a2738;
    --ink: var(--white);
    --ink-soft: var(--mist);
    --ink-rgb: 235, 240, 250;
    --accent-ink: var(--amber);
    --focus: var(--amber);
    --rule: rgba(235, 240, 250, 0.52);
    --tip: var(--mist);
    --tip-ink: var(--charcoal);
    color-scheme: dark;
  }
}

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

/* Links glide to their sections, but only once the page has loaded
   (slides.js adds the class): opening or reloading an address with a section
   in it goes straight there, without scrolling down from the top. */
html.smooth-scroll {
  scroll-behavior: smooth;
}

/* The visitor's stop control turns off all motion, including smooth scrolling
   and slide snapping. */
html.motion-stopped {
  scroll-behavior: auto;
  scroll-snap-type: none;
}

/* Opened with motion already stopped (a remembered stop: page.mjs), the
   diagram shows complete rather than revealing itself, then or later. */
.motion-held .outcome-diagram * { animation: none !important; }

body {
  margin: 0;
  min-width: 20rem;
  overflow-wrap: break-word;
  color: var(--ink);
  background: var(--page);
  font-family: var(--body);
  font-size: 1rem;
  line-height: 1.55;
  text-rendering: optimizeLegibility;
}

img,
svg {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
}

a:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 4px;
}

p,
h1,
h2,
h3 {
  margin-top: 0;
}

h1,
h2,
h3 {
  font-family: var(--body);
  font-weight: 700;
  letter-spacing: -0.045em;
  line-height: 1.08;
}

h1 {
  max-width: 15ch;
  margin-bottom: 1rem;
  font-size: clamp(2.55rem, 6vw, 6rem);
}

/* Every section heading shares one size. */
h2 {
  font-size: clamp(2.25rem, 4.6vw, 4.5rem);
}

h3 {
  font-size: clamp(1.5rem, 3.25vw, 3rem);
}

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

.skip-link {
  position: fixed;
  z-index: 100;
  top: 0.75rem;
  left: 0.75rem;
  padding: 0.8rem 1rem;
  color: var(--charcoal);
  background: var(--amber);
  font-family: var(--display);
  font-weight: 800;
  transform: translateY(-160%);
  transition: transform 150ms ease;
}

.skip-link:focus {
  transform: translateY(0);
}

.site-header,
.hero {
  color: var(--ink);
  background: var(--page);
}

.header-inner,
.section-inner,
.footer-inner,
.hero-brand,
.hero-lockup,
.hero-content {
  width: min(100%, var(--page-width));
  margin-inline: auto;
}

.site-header {
  position: sticky;
  z-index: 20;
  top: 0;
  padding-inline: var(--header-gutter);
}

/* One gap (--header-gap) separates everything in the header row: the links
   from each other and from the logo, and the last link and each icon from
   the next icon. The icons' 44 px targets already hold about 14-16 px of
   space around each symbol, so their own gaps are that much smaller. */
:root { --header-gap: clamp(1.75rem, 2.5vw, 2.5rem); }

.header-inner {
  display: grid;
  grid-template-columns: var(--header-logo-width) minmax(0, 1fr) auto;
  column-gap: calc(var(--header-gap) - 1rem);
  align-items: center;
  min-height: clamp(6.25rem, 10.3vw, 9.25rem);
  border-bottom: 1px solid var(--rule);
}

nav {
  grid-column: 2;
  grid-row: 1;
  justify-self: end;
}

nav ul {
  display: flex;
  align-items: center;
  gap: var(--header-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

nav a,
.text-link,
.footer-inner a {
  display: inline-flex;
  min-height: 2.75rem;
  align-items: center;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.35rem;
}

/* The header's links. */
nav a {
  font-family: var(--display);
  font-size: clamp(0.95rem, 1.4vw, 1.25rem);
  font-weight: 600;
  text-decoration: none;
}

nav a {
  white-space: nowrap;
}

nav a:hover,
.footer-inner a:hover {
  text-decoration: underline;
  text-underline-offset: 0.35rem;
}

/* The theme and stop controls, then "Get in touch" at the right edge. A
   hidden stop control (reduced motion) leaves no gap. */
.header-actions {
  display: flex;
  grid-column: 3;
  grid-row: 1;
  align-items: center;
  justify-self: end;
  gap: max(0px, var(--header-gap) - 1.75rem);
}


/* An envelope marks actions that open an email. */
.mail-icon {
  flex: none;
  width: 1.15em;
  height: 1.15em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* The header logo links home. It appears once the hero logo has scrolled
   away under the header (logo-motion.js). */
.header-logo-slot {
  display: block;
  grid-column: 1;
  grid-row: 1;
  justify-self: start;
  width: var(--header-logo-width);
  aspect-ratio: 610 / 128;
}

/* The header and footer copies are cropped to the same frame by their
   viewBox; drawing past it keeps SOFTWARE whole under phones' pixel rounding
   (there is nothing else outside the crop). */
.header-logo,
.footer-logo { overflow: visible; }

/* Out of the page entirely until it appears: Safari can paint animated parts
   of a merely hidden SVG. Appearing also restarts its unveil. */
.header-logo {
  display: none;
  width: 100%;
  height: auto;
}

.logo-docked .header-logo { display: block; }

/* The header logo replays the hero's unveil each time it appears; this class,
   set for one style update, restarts it (logo-motion.js). */
.header-logo.is-restarting * { animation: none !important; }

.hero {
  padding: clamp(2.5rem, 9vw, 8rem) var(--page-gutter) clamp(3rem, 5.8vw, 5.25rem);
}

.hero-brand {
  position: relative;
  margin-bottom: clamp(3rem, 9vw, 8rem);
}

.hero-lockup {
  position: relative;
  /* Frame the artwork, excluding the source SVG's blue export margins. Its
     stage reaches slightly below; the frame keeps its own height. */
  aspect-ratio: 610 / 128;
  min-height: 0;
}

/* The supplied lockup draws in white and mist on charcoal; here its light
   parts follow the theme's ink, so it reads on light pages too. */
.hero-logo [fill="#FFFFFF"],
.header-logo [fill="#FFFFFF"] { fill: var(--ink); }
.hero-logo [fill="#EBF0FA"],
.header-logo [fill="#EBF0FA"] { fill: var(--ink-soft); }
.hero-logo [stroke="#FFFFFF"],
.header-logo [stroke="#FFFFFF"] { stroke: var(--ink); }
.logo-letter { fill: var(--ink); }

/* The stage shows the lockup without its export margins. SOFTWARE ends less
   than a pixel above the frame's bottom edge, so the stage reaches a little
   below it (without taking up layout space); otherwise phones' pixel rounding
   can trim the letters. */
.hero-logo-stage {
  width: 100%;
  height: calc(100% + 0.25rem);
  margin-bottom: -0.25rem;
  overflow: hidden;
}

.hero-logo-stage > img,
.hero-logo-stage > svg {
  width: calc(100% * 720 / 610);
  max-width: none;
  height: auto;
  margin: 0;
  transform: translate(-7.777778%, -23.333333%);
}

/* The stop/play and theme controls sit in the header's top-right corner, the
   stop control first, then "Get in touch": on desktop an envelope alone,
   with its name as a tooltip like theirs (its words, visually hidden, keep
   the name; tablet widths and phones show them, below). */
.theme-toggle,
.logo-motion-toggle,
.header-email {
  position: relative;
  display: grid;
  flex-shrink: 0;
  width: var(--header-control-width);
  min-height: 2.75rem;
  place-items: center;
  padding: 0;
  border: 0;
  color: var(--ink-soft);
  background: transparent;
  cursor: pointer;
}

/* Keep their columns while scripts start, so the header does not shift.
   Reduced motion has no repeating flow, so the stop column collapses. */
.theme-toggle[hidden],
.logo-motion-toggle[hidden] { display: grid; visibility: hidden; }

@media (prefers-reduced-motion: reduce) {
  .logo-motion-toggle,
  .logo-motion-toggle[hidden] { display: none; }
}

/* The three icons share one 20 px size (page.mjs draws the theme and email
   icons to fill about 16 px of it, the stop square and play triangle a
   little smaller). */
.logo-motion-toggle svg { width: 20px; height: 20px; fill: currentColor; }
.logo-motion-toggle[data-paused="false"] .logo-play-icon,
.logo-motion-toggle[data-paused="true"] .logo-stop-icon { display: none; }

/* A moon switches to dark, a sun to light. */
.theme-toggle svg { width: 20px; height: 20px; fill: currentColor; }
.theme-light-icon path { fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; }
.theme-toggle[data-theme="light"] .theme-light-icon,
.theme-toggle[data-theme="dark"] .theme-dark-icon { display: none; }

.header-email .mail-icon { width: 20px; height: 20px; }

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

.theme-toggle:hover,
.logo-motion-toggle:hover,
.header-email:hover { color: var(--ink); }
.theme-toggle:focus-visible,
.logo-motion-toggle:focus-visible,
.header-email:focus-visible { outline: 3px solid var(--focus); outline-offset: -4px; }

/* Tooltip: the control's accessible name, shown on hover and keyboard focus. */
.theme-toggle::after,
.logo-motion-toggle::after,
.header-email::after {
  content: attr(aria-label);
  position: absolute;
  z-index: 1;
  top: calc(100% + 0.25rem);
  right: 0;
  padding: 0.375rem 0.5rem;
  border-radius: 0.25rem;
  color: var(--tip-ink);
  background: var(--tip);
  font: 600 0.75rem/1 var(--body);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease;
}

/* Only where a pointer can hover: touch screens keep a tapped button
   "hovered" until the next tap elsewhere, which would leave its tooltip up. */
@media (hover: hover) {
  .theme-toggle:hover::after,
  .logo-motion-toggle:hover::after,
  .header-email:hover::after { opacity: 1; transition-delay: 300ms; }
}
.theme-toggle:focus-visible::after,
.logo-motion-toggle:focus-visible::after,
.header-email:focus-visible::after { opacity: 1; }

.logo-diagonal,
.logo-axis,
.logo-star-assembly,
.logo-letter,
.logo-tagline,
.logo-flow-dot,
.logo-halo {
  transform-box: fill-box;
  transform-origin: center;
}

.logo-flow-dot,
.logo-halo { opacity: 0; }

.logo-flow-bottom { --entry-x: 0px; --entry-y: 58px; --pull-x-1: 0px; --pull-y-1: 50px; --pull-x-2: 0px; --pull-y-2: 34px; --flow-delay: 0s; }
.logo-flow-top { --entry-x: 0px; --entry-y: -58px; --pull-x-1: 0px; --pull-y-1: -50px; --pull-x-2: 0px; --pull-y-2: -34px; --flow-delay: 3.2s; }
.logo-flow-left { --entry-x: -58px; --entry-y: 0px; --pull-x-1: -50px; --pull-y-1: 0px; --pull-x-2: -34px; --pull-y-2: 0px; --flow-delay: 6.4s; }

/* Fold unveil. The mark starts folded along both diagonals into its right
   quarter, which is drawn first; it unfolds across one diagonal, then the
   other. The paper is opaque, so folded layers hide what lies beneath them.
   While folded, each triangle is one closed outline as thick as the square's
   outer edge, with rounded corners. Once open, it crossfades into the
   finished frame and thinner diagonal folds (1.55-1.75 s), and the dashed
   guides fade in on the opened square. */
.logo-fold { display: none; }
.fold-paper { fill: color-mix(in srgb, var(--ink) 7%, var(--page)); fill-opacity: 1; }
.fold-shade { fill: var(--ink); fill-opacity: 0; }
.fold-outline {
  fill: none;
  stroke: var(--ink);
  stroke-width: 3.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* A flap turns over a fold through the centre (50, 50) of the mark. */
.fold-flap { transform-box: view-box; transform-origin: 0 0; }

@media (prefers-reduced-motion: no-preference) {
  /* The hero logo appears complete on load. Only the header logo unveils,
     each time it appears (logo-motion.js). */
  .header-logo .logo-fold { display: inline; animation: logo-fold-out 200ms ease 1550ms forwards; }
  /* The drawn outline holds its end state, so it stays listed as settled. */
  .header-logo .fold-r .fold-outline { animation: logo-draw-line 540ms linear both; }
  .header-logo .fold-paper { animation: logo-paper 1750ms linear both; }
  .header-logo .fold-across-first {
    animation: logo-show 1ms 540ms backwards,
      logo-unfold-first 560ms cubic-bezier(.62, 0, .32, 1) 600ms both;
  }
  .header-logo .fold-bottom {
    animation: logo-show 1ms 540ms backwards,
      logo-unfold-second 560ms cubic-bezier(.62, 0, .32, 1) 1160ms both;
  }
  .header-logo .fold-across-first .fold-across-second { animation: logo-unfold-second 560ms cubic-bezier(.62, 0, .32, 1) 1160ms both; }
  /* A flap's back is shaded until it turns edge-on. */
  .header-logo .fold-t .fold-shade { animation: logo-shade 1ms 880ms backwards; }
  .header-logo .fold-l .fold-shade,
  .header-logo .fold-b .fold-shade { animation: logo-shade 1ms 1440ms backwards; }

  .header-logo .logo-frame,
  .header-logo .logo-diagonal { animation: logo-show 200ms ease 1550ms backwards; }
  .header-logo .logo-axis { animation: logo-guides-in 320ms ease 1750ms backwards; }
  .header-logo .logo-star-assembly { animation: logo-assemble-star 580ms 1600ms backwards; }
  .header-logo .logo-letter { animation: logo-letter-in 560ms calc(var(--piece-delay) + 1250ms) backwards; }
  /* The tagline sits at the logo's bottom edge, so it fades in rather than
     rising from below, which the edge would cut off. */
  .header-logo .logo-tagline { animation: logo-show 440ms 2400ms backwards; }
  .header-logo .logo-star-assembly,
  .header-logo .logo-letter,
  .header-logo .logo-tagline { animation-timing-function: cubic-bezier(.22, .8, .25, 1); }

  .is-flowing .logo-flow-dot {
    animation: logo-signal 9.6s linear var(--flow-delay) infinite backwards,
      logo-signal-visibility 9.6s linear var(--flow-delay) infinite backwards,
      logo-signal-shape 9.6s linear var(--flow-delay) infinite backwards;
  }
  .is-flowing .logo-star { animation: logo-illuminate 3.2s linear infinite; }
  .is-flowing .logo-halo { animation: logo-glow 3.2s linear infinite; }
  .is-motion-paused .logo-flow-dot,
  .is-motion-paused .logo-star,
  .is-motion-paused .logo-halo { animation-play-state: paused; }
}

@keyframes logo-show { from { opacity: 0; } }
@keyframes logo-fold-out { to { opacity: 0; visibility: hidden; } }
@keyframes logo-draw-line {
  from { stroke-dasharray: 1 2; stroke-dashoffset: 1; }
  to { stroke-dasharray: 1 2; stroke-dashoffset: 0; }
}
@keyframes logo-paper {
  0%, 30% { fill-opacity: 0; }
  34%, 100% { fill-opacity: 1; }
}
@keyframes logo-guides-in { from { opacity: 0; } }
@keyframes logo-shade { from { fill-opacity: 0.06; } }
/* Turning over the diagonal from top right to bottom left, then the other. */
@keyframes logo-unfold-first {
  from { transform: translate(50px, 50px) rotate(-45deg) scaleY(-1) rotate(45deg) translate(-50px, -50px); }
  to { transform: translate(50px, 50px) rotate(-45deg) scaleY(1) rotate(45deg) translate(-50px, -50px); }
}
@keyframes logo-unfold-second {
  from { transform: translate(50px, 50px) rotate(45deg) scaleY(-1) rotate(-45deg) translate(-50px, -50px); }
  to { transform: translate(50px, 50px) rotate(45deg) scaleY(1) rotate(-45deg) translate(-50px, -50px); }
}
@keyframes logo-assemble-star {
  from { transform: scale(.2) rotate(-45deg); opacity: 0; }
  to { transform: none; opacity: 1; }
}
@keyframes logo-letter-in {
  from { transform: translateY(15px); opacity: 0; }
  to { transform: none; opacity: 1; }
}
@keyframes logo-signal {
  0% { transform: translate(var(--entry-x), var(--entry-y)) scale(1); fill: var(--ink); }
  /* The white approach stays at 1596 ms. The yellow exit takes 638 ms
     at about 35.7 logo units/second, without slowing near the frame edge. */
  7% { transform: translate(var(--pull-x-1), var(--pull-y-1)) scale(.96); fill: var(--ink); }
  12.25% { transform: translate(var(--pull-x-2), var(--pull-y-2)) scale(.78); fill: var(--ink); }
  16.625% { transform: translate(0, 0) scale(.18); fill: var(--ink); }
  /* The output grows from the star's right point before its steady outward travel. */
  20.14583333% { transform: translate(21.65px, 0) scale(.16); fill: var(--amber); }
  20.83333333% { transform: translate(24px, 0) scale(1.15); fill: var(--amber); }
  22.29166667% { transform: translate(29px, 0) scale(1.8); fill: var(--amber); }
  /* Keep moving through the fixed clip at x=89.75 until the trailing edge
     clears it: 50 + 44.43 - (2.6 * 1.8) = 89.75. */
  26.79166666%, 100% { transform: translate(44.43px, 0) scale(1.8); fill: var(--amber); }
}
@keyframes logo-signal-visibility {
  /* Entry is revealed by the square's clip, without an opacity fade. */
  0% { opacity: 0; animation-timing-function: steps(1, end); }
  3.5%, 16.1875% { opacity: 1; }
  16.625%, 20.10208333% { opacity: 0; }
  /* The fixed clip progressively hides the opaque dot as it leaves. */
  20.14583333% { opacity: 1; animation-timing-function: steps(1, end); }
  26.79166666%, 100% { opacity: 0; }
}
/* The white input is round; the yellow output is a diamond with rounded
   points. While the dot is hidden between absorption and output, a clip
   switches to a diamond whose points sit just beyond the dot's circle, so
   the circle rounds them. */
@keyframes logo-signal-shape {
  0% { clip-path: polygon(50% -50%, 150% 50%, 50% 150%, -50% 50%); animation-timing-function: steps(1, end); }
  18%, 100% { clip-path: polygon(50% -9%, 109% 50%, 50% 109%, -9% 50%); }
}
@keyframes logo-illuminate {
  0%, 49.875%, 61.75%, 100% { fill: var(--amber); filter: none; }
  54.75%, 57.375% { fill: #ffd068; filter: drop-shadow(0 0 2px rgba(255, 184, 4, 0.55)); }
}
@keyframes logo-glow {
  0%, 49.875%, 61.75%, 100% { opacity: 0; transform: scale(1); }
  54.75%, 57.375% { opacity: 0.18; transform: scale(1.05); }
  60.875% { opacity: 0; transform: scale(1.16); }
}

/* Copy and diagram side by side, with the two links as the last row at the
   bottom left, level with the diagram's foot. */
.hero-content {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: minmax(0, 1fr) auto;
  grid-template-areas: "copy diagram" "actions diagram";
  gap: 0 clamp(2rem, 3.4vw, 3.25rem);
  align-items: center;
}

.hero-copy { grid-area: copy; }
.outcome-diagram { grid-area: diagram; }
.hero-actions { grid-area: actions; align-self: end; }

.hero-copy > p {
  max-width: 20em;
  margin-bottom: 1.75rem;
  font-size: clamp(1.15rem, 2.1vw, 2rem);
  line-height: 1.45;
}

/* The hero's two text links sit side by side from the left, wrapping onto a
   second line only when there is no room. */
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem 1.75rem;
}

.hero-actions .text-link {
  white-space: nowrap;
}

.button {
  display: inline-flex;
  min-height: clamp(3rem, 4.8vw, 4.5rem);
  align-items: center;
  justify-content: center;
  gap: 0.65rem;
  padding: 0.75rem 1.2rem;
  font-family: var(--body);
  font-size: clamp(1rem, 1.65vw, 1.5rem);
  font-weight: 700;
  line-height: 1.2;
  text-decoration: none;
}

.button-primary {
  color: var(--charcoal);
  background: var(--amber);
}

.button-primary:hover {
  color: var(--page);
  background: var(--ink);
}

/* The arrow is joined to the last word by a no-break space, so it never
   wraps onto a line of its own. */
.text-link {
  gap: 0.35rem;
  font-size: clamp(1rem, 1.5vw, 1.35rem);
  font-weight: 600;
  text-decoration: none;
}

/* Only the words are underlined, not the arrow. */
.text-link .link-label {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.35rem;
}

.outcome-diagram {
  --diagram-label-gap: 0.84375rem;
  --diagram-label-size: clamp(0.8125rem, 1vw, 0.9375rem);
  /* Side room for the gap plus the widest side word, SOFTWARE on the left or
     TAILORED on the right, in Josefin Sans capitals with letter spacing.
     Layouts size the circles from these. */
  --diagram-label-room: calc(var(--diagram-label-gap) + 6.4 * var(--diagram-label-size));
  --diagram-label-room-end: calc(var(--diagram-label-gap) + 6 * var(--diagram-label-size));
  min-width: 0;
  margin: 0;
  padding: clamp(1.5rem, 3vw, 2.25rem) 0;
}

.diagram-visual {
  position: relative;
  width: min(100%, 30rem);
  aspect-ratio: 1;
  margin-inline: auto;
}

.diagram-connections {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.diagram-spoke {
  stroke: var(--ink);
  stroke-opacity: 0.65;
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
  transform-box: fill-box;
}

/* Each dash grows out from the star. */
.spoke-top { transform-origin: 50% 100%; --spoke-from: scaleY(0); }
.spoke-bottom { transform-origin: 50% 0; --spoke-from: scaleY(0); }
.spoke-left { transform-origin: 100% 50%; --spoke-from: scaleX(0); }
.spoke-right { transform-origin: 0 50%; --spoke-from: scaleX(0); }
/* Each circle pops out from the end of its dash. */
.diagram-item[data-node="dashboards"] { --toward-x: 0%; --toward-y: 45%; }
.diagram-item[data-node="website"] { --toward-x: -45%; --toward-y: 0%; }
.diagram-item[data-node="automation"] { --toward-x: 0%; --toward-y: -45%; }
.diagram-item[data-node="tools"] { --toward-x: 45%; --toward-y: 0%; }


.diagram-hub {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 18%;
  transform: translate(-50%, -50%);
}

.diagram-brand-star {
  width: 100%;
  height: auto;
  fill: var(--amber);
}

.diagram-item {
  position: absolute;
  width: 30%;
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  text-align: center;
}

.diagram-item[data-node="dashboards"] { left: 50%; top: 17%; }
.diagram-item[data-node="tools"] { left: 17%; top: 50%; }
.diagram-item[data-node="automation"] { left: 50%; top: 83%; }
.diagram-item[data-node="website"] { left: 83%; top: 50%; }

.diagram-circle {
  display: grid;
  width: 100%;
  aspect-ratio: 1;
  place-items: center;
  border: 2px solid var(--ink);
  border-radius: 50%;
  background: var(--icon-ground, var(--page));
}

.diagram-circle .icon {
  width: 62%;
  color: var(--ink);
  fill: none;
  stroke: currentColor;
  stroke-width: 2.4;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.diagram-icon .icon-accent { stroke: var(--amber); }
.diagram-icon .icon-accent-fill { fill: var(--amber); stroke: none; }
.diagram-icon .icon-muted { stroke-opacity: 0.55; }
.diagram-icon .icon-knockout { fill: var(--icon-ground, var(--page)); }

.diagram-item > span {
  position: absolute;
  top: calc(100% + var(--diagram-label-gap));
  left: 50%;
  width: 16rem;
  transform: translateX(-50%);
  /* Letter spacing also follows the last letter of each line. A matching start
     padding keeps the text centred, and side labels move in by the same amount
     so their visible gap matches the top and bottom labels. */
  --label-side-gap: calc(var(--diagram-label-gap) - 0.1em);
  padding-left: 0.1em;
  font-family: var(--label);
  font-size: var(--diagram-label-size);
  font-weight: 600;
  letter-spacing: 0.1em;
  line-height: 1.2;
  text-transform: uppercase;
  overflow-wrap: normal;
  text-wrap: balance;
  /* Measure capitals from cap height to baseline so vertical gaps are visible gaps. */
  text-box: trim-both cap alphabetic;
}

.diagram-item[data-node="dashboards"] > span {
  top: auto;
  bottom: calc(100% + var(--diagram-label-gap));
  width: 22rem;
}

.diagram-item[data-node="tools"] > span {
  top: 50%;
  left: auto;
  right: calc(100% + var(--label-side-gap));
  width: min-content;
  transform: translateY(-50%);
}

.diagram-item[data-node="website"] > span {
  top: 50%;
  left: calc(100% + var(--label-side-gap));
  width: min-content;
  transform: translateY(-50%);
}

/* The services come out of the star one by one, clockwise from the top: a
   dash grows, then its circle pops out of it with its label. The star pulses
   as each one leaves. It starts shortly after the page loads. */
.outcome-diagram { --diagram-start: 400ms; }

@media (prefers-reduced-motion: no-preference) {
  .diagram-brand-star {
    transform-origin: center;
    animation: diagram-star-in 480ms cubic-bezier(.3, 1.5, .5, 1) var(--diagram-start) backwards,
      diagram-star-pulse 380ms ease-in-out calc(var(--diagram-start) + 500ms) 4 forwards;
  }
  .diagram-spoke { animation: diagram-spoke-in 220ms ease-out calc(var(--diagram-start) + 500ms + var(--i) * 380ms) backwards; }
  .diagram-circle { animation: diagram-circle-in 380ms cubic-bezier(.3, 1.5, .5, 1) calc(var(--diagram-start) + 660ms + var(--i) * 380ms) backwards; }
  /* Each label fades in with its circle. */
  .diagram-item > span { animation: diagram-label-in 380ms ease-out calc(var(--diagram-start) + 660ms + var(--i) * 380ms) backwards; }
}

@keyframes diagram-star-in { from { transform: scale(0) rotate(-120deg); } }
/* One gentle swell per service, spanning the 380 ms between them. */
@keyframes diagram-star-pulse {
  0%, 100% { transform: scale(1); }
  45% { transform: scale(1.22); }
}
@keyframes diagram-spoke-in { from { transform: var(--spoke-from); } }
@keyframes diagram-circle-in { from { transform: translate(var(--toward-x), var(--toward-y)) scale(0); } }
@keyframes diagram-label-in { from { opacity: 0; } }

.section-pale {
  color: var(--ink);
  background: var(--surface-pale);
}

.section-navy,
.site-footer {
  color: var(--ink);
  background: var(--page);
}

.section-inner {
  padding: clamp(3.25rem, 6.5vw, 6rem) var(--page-gutter);
}

/* Capitals use Josefin Sans throughout, like the diagram labels and the
   logo's SOFTWARE line. Section labels are amber. */
.eyebrow {
  color: var(--ink);
  font-family: var(--label);
  font-size: clamp(0.95rem, 1.45vw, 1.3rem);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.eyebrow,
.start-template-label {
  color: var(--accent-ink);
}

.services h2 {
  margin-bottom: clamp(1.25rem, 4dvh, 3rem);
}

.services .eyebrow {
  margin-bottom: 1.25rem;
}

.service-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
}

.service-card {
  min-width: 0;
  padding-right: clamp(0.75rem, 1.5vw, 1.5rem);
}

.service-card + .service-card {
  padding-left: clamp(1rem, 2vw, 2rem);
  border-left: 1px solid rgba(var(--ink-rgb), 0.25);
}

.service-card:last-child {
  padding-right: 0;
}

/* Each service opens with its title on the left and its icon on the right,
   then the summary and examples. */
.service-card {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  column-gap: 1rem;
  align-content: start;
  align-items: center;
}

/* Both lists of steps show their numbers in amber inside an outlined circle.
   Each list sets the circle's size. */
.start-number,
.process-number {
  display: grid;
  width: var(--number-size);
  height: var(--number-size);
  margin: 0;
  place-items: center;
  border: 2px solid var(--ink);
  border-radius: 50%;
  color: var(--accent-ink);
  font: 700 calc(var(--number-size) * 0.46) / 1 var(--body);
  letter-spacing: 0;
}

.service-card .service-icon {
  grid-column: 2;
  grid-row: 1;
  margin: 0;
}

/* Titles wrap only between words. */
.service-card h3 { grid-column: 1; grid-row: 1; overflow-wrap: normal; hyphens: manual; }

/* Where four columns leave a title too little room beside its icon (desktop
   layouts under 960 px wide), the icon sits above the title. */
@media (min-width: 52.001rem) and (max-width: 59.999rem) and (min-aspect-ratio: 4/5) {
  .service-card .service-icon { grid-column: 1; grid-row: 1; justify-self: start; margin-bottom: 0.75rem; }
  .service-card h3 { grid-column: 1 / -1; grid-row: 2; }
  .service-card .service-summary { grid-row: 3; }
  .service-card .service-details { grid-row: 4; }
}

.service-summary,
.service-details { grid-column: 1 / -1; }

/* A faint rule runs under each service's title and icon. */
.service-summary { margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid rgba(var(--ink-rgb), 0.14); }

/* Each service shows the hero diagram's white-and-amber artwork on its own,
   without a circle. */
.service-icon {
  --icon-ground: var(--surface-pale);
  display: grid;
  width: clamp(3.75rem, 5.8vw, 5.75rem);
  height: clamp(3.75rem, 5.8vw, 5.75rem);
  margin-bottom: 1rem;
  place-items: center;
  color: var(--ink);
}

.service-icon .icon {
  width: 100%;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.service-card h3 {
  margin: 0;
  font-size: clamp(1.4rem, 2.1vw, 2rem);
}

.service-summary {
  max-width: 23rem;
  margin-bottom: 0;
  font-size: clamp(1.05rem, 1.35vw, 1.3rem);
}

/* What each service can include, marked with small amber squares. */
.service-details {
  display: grid;
  gap: 0.45rem;
  margin: 1rem 0 0;
  padding: 0;
  color: rgba(var(--ink-rgb), 0.8);
  font-size: clamp(0.95rem, 1.05vw, 1.05rem);
  line-height: 1.35;
  list-style: none;
}

.service-details li {
  position: relative;
  padding-left: 1rem;
}

.service-details li::before {
  content: "";
  position: absolute;
  top: 0.5em;
  left: 0;
  width: 0.4rem;
  height: 0.4rem;
  background: var(--amber);
}

/* The email template's button is for phones only (below). */
.template-toggle { display: none; }

/* How we work: the heading, then its two kinds of work (tracks), with no
   tabs. Above phone sizes they are two lanes, one above the other: each has
   its track's icon and name, introduction and questions, and its four steps
   side by side along a line (below, after the steps' shared rules). Phones
   show them as cards, swiped sideways (below). */
.process-layout {
  display: grid;
  gap: 2rem;
}

.process-head h2 {
  margin-bottom: 0;
  text-wrap: balance;
}

.process-track-name {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin: 0 0 0.5rem;
  letter-spacing: -0.02em;
}

.process-track-name .icon {
  flex: none;
  width: 1.75em;
  height: 1.75em;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.process-intro > p {
  margin-bottom: 0;
  color: var(--ink-soft);
  line-height: 1.45;
}

/* Questions to think through, marked like the services' examples. */
.process-questions {
  display: grid;
  font-style: italic;
  gap: 0.3rem;
  margin: 0.5rem 0 0;
  padding: 0;
  color: var(--ink-soft);
  line-height: 1.4;
  list-style: none;
}

.process-questions li {
  position: relative;
  padding-left: 1.1rem;
}

.process-questions li::before {
  content: "";
  position: absolute;
  top: 0.55em;
  left: 0;
  width: 0.4rem;
  height: 0.4rem;
  background: var(--amber);
}

.process-list {
  --number-size: 2rem;
  display: grid;
  gap: var(--step-gap);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Each step's title and description sit beside its circled number, with a
   line down to the next number (below); in the lanes, beneath it. */
.process-list li {
  display: grid;
  grid-template-columns: var(--number-size) minmax(0, 1fr);
  gap: 0 0.75rem;
}

.process-list h3 {
  margin-bottom: 0;
  letter-spacing: -0.02em;
}

.process-list p {
  margin: 0.4rem 0 0;
  color: var(--ink-soft);
  line-height: 1.4;
}

/* In both lists of steps, a faint rule runs under each step's title, as
   under the services'. */
.start-steps li p,
.process-list li p { padding-top: 0.4rem; border-top: 1px solid rgba(var(--ink-rgb), 0.14); }

/* About: Starfold (heading and story) on the left, Michael (his experience,
   as a list) on the right. */
.about-layout {
  display: grid;
  grid-template-columns: minmax(18rem, 1.15fr) minmax(16rem, 0.85fr);
  gap: clamp(2.5rem, 7vw, 7rem);
  align-items: start;
}

.about-layout h2 {
  max-width: 24ch;
  margin-bottom: clamp(1rem, 2.4dvh, 1.75rem);
}

.about-copy p {
  max-width: 40rem;
  margin-bottom: 0.9em;
  color: var(--ink-soft);
  font-size: clamp(1.05rem, 1.35vw, 1.3rem);
}

.about-copy p:last-child {
  margin-bottom: 0;
}

/* The name in the logo's own font: JetBrains Mono ExtraBold. */
.brand-name {
  color: var(--ink);
  text-transform: lowercase;
  font-family: var(--display);
  font-weight: 800;
  letter-spacing: -0.02em;
}

/* Michael's experience, under a top rule, marked like the services' examples. */
.about-founder {
  padding-top: 1.5rem;
  border-top: 2px solid var(--ink);
}

.about-founder .eyebrow { margin: 0 0 1rem; }

.about-points {
  display: grid;
  gap: 0.75rem;
  margin: 0;
  padding: 0;
  font-size: clamp(1rem, 1.2vw, 1.15rem);
  line-height: 1.45;
  list-style: none;
}

.about-points li {
  position: relative;
  padding-left: 1.1rem;
}

.about-points li::before {
  content: "";
  position: absolute;
  top: 0.55em;
  left: 0;
  width: 0.4rem;
  height: 0.4rem;
  background: var(--amber);
}

/* Not sure where to start: the approach for new clients, with an email
   template they can send to book a free consultation. */
.start-layout {
  display: grid;
  grid-template-columns: minmax(18rem, 1fr) minmax(20rem, 0.9fr);
  gap: clamp(3rem, 7vw, 7rem);
  align-items: center;
}

.start-intro h2 {
  max-width: 12ch;
  margin-bottom: 1.25rem;
}

.start-intro > p:not(.eyebrow) {
  max-width: 36rem;
  margin-bottom: 1.5rem;
  font-size: clamp(1.05rem, 1.45vw, 1.3rem);
}

.start-steps {
  --number-size: 2rem;
  --step-gap: 0.9rem;
  display: grid;
  gap: var(--step-gap);
  margin: 0;
  padding: 1.5rem 0 0;
  border-top: 1px solid rgba(var(--ink-rgb), 0.25);
  list-style: none;
}

.start-steps li {
  display: grid;
  grid-template-columns: var(--number-size) 1fr;
  gap: 0.2rem 0.75rem;
}

.start-steps li > div,
.process-list li > div { display: contents; }

/* Both lists of steps (S1-STEPS-001): each number sits at the top of its
   step, with the title centred on it when it fits one line, and a thin line
   runs from each number down to the next, carried across the space between
   steps by --step-gap (the list's gap). Getting started's list holds the
   signal's dot (below). */
.start-steps { position: relative; }

.start-steps li,
.process-list li { position: relative; }

.start-number,
.process-number { position: relative; z-index: 1; grid-column: 1; grid-row: 1; }

/* Each number's circle is filled with its section's colour (on phones, How
   we work's cards'), so in Getting started it hides the signal's dot as it
   passes under. */
.start-number { background: var(--page); }
.process-number { background: var(--page); }

.start-steps h3,
.process-list h3 {
  display: flex;
  min-height: var(--number-size);
  align-items: center;
  grid-column: 2;
  grid-row: 1;
}

.start-steps li:not(:last-of-type)::before,
.process-list li:not(:last-of-type)::before {
  content: "";
  position: absolute;
  top: calc(var(--number-size) + 6px);
  bottom: calc(6px - var(--step-gap, 0px));
  left: calc(var(--number-size) / 2 - 1px);
  width: 2px;
  background: rgba(var(--ink-rgb), 0.22);
}

/* The signal (steps.js), in Getting started only: the first time the list
   comes on screen, its numbers light in turn, with a small dot running down
   each part of the line between them, never across a number. */
.step-signal {
  position: absolute;
  z-index: 0;
  top: 0;
  left: calc(var(--number-size) / 2 - 4px);
  width: 8px;
  height: 8px;
  margin-top: -4px;
  border-radius: 50%;
  background: var(--ink);
  box-shadow: 0 0 10px 2px rgba(255, 184, 4, 0.7);
  opacity: 0;
  pointer-events: none;
}

.start-number.is-lit { animation: step-lit 1100ms ease-out; }

@keyframes step-lit {
  0%, 100% { border-color: var(--ink); box-shadow: 0 0 0 0 rgba(255, 184, 4, 0); transform: none; }
  20% { border-color: var(--accent-ink); box-shadow: 0 0 14px 3px rgba(255, 184, 4, 0.45); transform: scale(1.14); }
}

.start-steps li p,
.process-list li p { grid-column: 2; grid-row: 2; }


.start-steps h3 {
  margin-bottom: 0;
  font-size: clamp(1.15rem, 1.6vw, 1.45rem);
  letter-spacing: -0.02em;
}

.start-steps p {
  margin-bottom: 0;
  color: rgba(var(--ink-rgb), 0.78);
  font-size: clamp(0.98rem, 1.2vw, 1.1rem);
}

/* Words marked **…** in the steps' descriptions are bold. */
.start-steps strong,
.process-list strong { font-weight: 700; }

/* Above phone sizes, How we work's two tracks are lanes, one above the
   other, a rule between them: its name, introduction and questions, then its
   four steps side by side, each number at the top of its step, its title and
   description beneath, and a line across between each number and the next. On
   wide landscape screens the name, introduction and questions sit to the left
   of the steps. Slide-sized screens scale the lanes' type and spacing with
   the screen's height, so both fit the slide (below). */
@media (min-width: 40rem) {
  .process-track {
    display: grid;
    gap: 1rem 3rem;
    padding: 1.5rem 0;
    border-top: 1px solid rgba(var(--ink-rgb), 0.25);
  }

  /* The heading needs no rule beneath it. */
  .process-track:first-child { border-top: 0; }

  .process-track-name { font-size: clamp(1.1rem, 1.5vw, 1.35rem); }
  .process-intro > p { font-size: clamp(0.9rem, 1.05vw, 1rem); }
  .process-questions { font-size: clamp(0.825rem, 0.95vw, 0.9rem); }

  .process-list {
    --step-gap: clamp(1rem, 2vw, 1.75rem);
    grid-template-columns: repeat(4, minmax(0, 1fr));
    row-gap: 0;
  }

  /* The four steps share their rows (number, title, description), so their
     titles' rules and descriptions line up across the lane even where a
     title takes two lines. */
  .process-list li {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: subgrid;
    grid-row: span 3;
    row-gap: 0;
  }

  .process-list h3 {
    display: block;
    min-height: 0;
    grid-column: 1;
    grid-row: 2;
    margin-top: 0.75rem;
    font-size: clamp(1rem, 1.3vw, 1.2rem);
  }

  .process-list li p { grid-column: 1; grid-row: 3; padding-top: 0.5rem; }
  .process-list p { margin-top: 0.5rem; font-size: clamp(0.825rem, 1vw, 0.95rem); }

  /* Each step's line runs back to the previous number, so nothing reaches
     past a step's right edge. */
  .process-list li:not(:last-of-type)::before { content: none; }

  .process-list li:not(:first-of-type)::before {
    content: "";
    position: absolute;
    top: calc(var(--number-size) / 2 - 1px);
    right: calc(100% + 6px);
    bottom: auto;
    left: calc(var(--number-size) + 6px - 100% - var(--step-gap));
    width: auto;
    height: 2px;
    background: rgba(var(--ink-rgb), 0.22);
  }
}

@media (min-width: 64rem) and (min-aspect-ratio: 5/4) {
  .process-track { grid-template-columns: minmax(16rem, 0.44fr) minmax(0, 1fr); }
}

.start-template {
  display: grid;
  gap: 1rem;
  justify-items: start;
}

/* A long address wraps anywhere rather than overflow. */
.footer-inner > a:last-child {
  margin: 0;
  overflow-wrap: anywhere;
}

.start-template-label {
  margin-bottom: 0;
  font-family: var(--label);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.email-template {
  width: 100%;
  padding: 1.1rem 1.25rem;
  border: 1px solid rgba(var(--ink-rgb), 0.2);
  background: var(--surface-pale);
  font-size: clamp(0.9rem, 1.05vw, 1rem);
  line-height: 1.5;
}

.email-template-subject {
  margin-bottom: 0.75rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid rgba(var(--ink-rgb), 0.15);
  font-weight: 700;
}

/* Each blank-line-separated part of the body is a paragraph, a little apart
   rather than a whole empty line, so the template stays compact; the email
   itself keeps the blank lines. */
.email-template-body p {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.email-template-body p + p { margin-top: 0.55em; }

.site-footer {
  padding-inline: var(--page-gutter);
  border-top: 1px solid rgba(var(--ink-rgb), 0.28);
}

/* A slim footer: the last slide (Getting started) leaves --footer-height for it. Under
   760 px wide it leaves out the site map, which would wrap onto a second
   line there; the header's links are always in view. */
@media (max-width: 47.499rem) {
  .footer-links { display: none; }
}

:root { --footer-height: 5rem; }

.footer-inner {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 2rem;
  align-items: center;
  min-height: var(--footer-height);
  font-size: 0.92rem;
}

/* Without the site map, the logo and the email address sit at either end. */
@media (max-width: 47.499rem) {
  .footer-inner {
    grid-template-columns: auto auto;
    justify-content: space-between;
  }
}

/* The site map: the page's sections, in the header links' font. */
.footer-links ul {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0 clamp(1rem, 2.5vw, 2rem);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Smaller than the header's links: the footer is a quiet index. */
.footer-links a {
  font-family: var(--display);
  font-size: clamp(0.75rem, 0.9vw, 0.8125rem);
  font-weight: 600;
  text-decoration: none;
}

/* The same lockup as the header, cropped and sized like the docked logo. */
.footer-brand {
  text-decoration: none;
}

.footer-logo {
  width: var(--header-logo-width);
  height: auto;
}

main,
section[id] {
  scroll-margin-top: calc(var(--opening-header-height, 6rem) + 1rem);
}

@media (min-width: 52.001rem) and (min-aspect-ratio: 4/5), (min-width: 64.001rem) {
  :root {
    --desktop-header-height: clamp(4.5rem, 10dvh, 6rem);
    --hero-diagram-size: clamp(16rem, 39dvh, 23rem);
  }

  .header-inner {
    min-height: var(--desktop-header-height);
  }

  nav a {
    font-size: clamp(0.75rem, 1.1vw, 1rem);
  }

  .hero {
    display: flex;
    flex-direction: column;
    justify-content: safe center;
    padding-block: 2rem 1rem;
  }

  .hero-brand {
    /* Give the logo the remaining screen height after content and controls. */
    width: min(100%, var(--page-width), max(30rem,
      calc((100dvh - var(--desktop-header-height) - var(--hero-diagram-size) - 8rem) * 610 / 128)));
    flex-shrink: 0;
    margin-inline: auto;
    margin-bottom: 3rem;
  }

  /* On tall screens the content fills the rest of the frame, so the links
     sit at its bottom. */
  .hero-content { flex: 1 0 auto; }

  .hero h1 {
    font-size: clamp(2.5rem, min(4.4vw, 8dvh), 4rem);
  }

  .hero-copy > p {
    margin-bottom: 1.5rem;
    font-size: clamp(1.125rem, min(1.6vw, 2.8dvh), 1.4rem);
  }

  .hero-actions .text-link {
    font-size: 1rem;
  }

  .outcome-diagram {
    --diagram-label-size: clamp(0.8125rem, min(1.55dvh, 1.1vw), 0.9375rem);
    padding-block: 2.25rem;
  }

  .diagram-visual {
    width: min(calc(100% - 2 * var(--diagram-label-room)), calc(var(--hero-diagram-size) - 2.5rem));
  }
}

@media (max-width: 52rem), (max-width: 64rem) and (max-aspect-ratio: 799/1000) {
  :root {
    /* The logo takes the first row's room, up to 9rem, beside the stop and
       theme targets (5.5rem), "Get in touch" (about 7.95rem), 0.25rem
       between the controls and 0.5rem before them. */
    --header-logo-width: clamp(6.25rem, calc(100vw - 2 * var(--header-gutter) - 14.625rem), 9rem);
    --header-control-width: 2.75rem;
  }

  .hero-content {
    grid-template-columns: 1fr;
  }

  .header-inner {
    grid-template-columns: var(--header-logo-width) minmax(0, 1fr);
    column-gap: 0.5rem;
    padding-block: 0.75rem;
  }

  .header-actions { grid-column: 2; gap: 0.25rem; }

  .header-logo-slot { grid-column: 1; grid-row: 1; }

  /* Below 640 px wide the links take a second row, spread across it (below). */
  nav {
    grid-column: 1 / -1;
    grid-row: 2;
    justify-self: stretch;
  }

  .hero-copy {
    display: block;
  }

  .hero-copy h1,
  .hero-copy > p {
    margin-bottom: 1.4rem;
  }

  .service-grid,
  .start-layout,
  .about-layout {
    grid-template-columns: 1fr;
  }


  .service-card {
    padding: 2rem 0;
    border-top: 1px solid rgba(var(--ink-rgb), 0.25);
  }

  .service-card + .service-card {
    padding-left: 0;
    border-left: 0;
  }

  .service-card:last-child {
    border-bottom: 1px solid rgba(var(--ink-rgb), 0.25);
  }

  /* The title and icon share the first row; the summary and examples run
     beneath. */
  .service-summary { grid-row: 2; max-width: none; }
  .service-details { grid-row: 3; }
}

/* Tablet widths: the services sit two by two. */
@media (min-width: 40rem) and (max-width: 52rem),
  (min-width: 40rem) and (max-width: 64rem) and (max-aspect-ratio: 799/1000) {
  .service-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 2rem;
  }

  .service-card { padding: 1.5rem 0; }

  .service-card .service-icon {
    width: 3.25rem;
    height: 3.25rem;
  }


  /* Only the lines between the cards remain, forming a cross. */
  .service-card:nth-child(-n + 2) { border-top: 0; }
  .service-card:last-child { border-bottom: 0; }

  /* A divider runs down between the columns, from the top of the first
     row's content to the bottom of the last row's (the cards' padding), and
     the Starfold star sits where it crosses the line between the rows. Like
     the logo's guides, the lines stop short of the star. */
  .service-grid { position: relative; }

  .service-grid::before {
    content: "";
    position: absolute;
    top: 1.5rem;
    bottom: 1.5rem;
    left: 50%;
    width: 1px;
    background: rgba(var(--ink-rgb), 0.25);
  }

  .service-card:nth-child(3) { position: relative; }

  .service-card:nth-child(3)::before,
  .service-card:nth-child(3)::after {
    content: "";
    position: absolute;
    z-index: 1;
    top: -0.5px;
    right: -1rem;
    transform: translate(50%, -50%);
  }

  /* A patch of the section's colour, so the lines stop short of the star. */
  .service-card:nth-child(3)::before {
    width: 2.25rem;
    height: 2.25rem;
    background: var(--surface-pale);
  }

  /* The logo's star outline, scaled to 24 px. */
  .service-card:nth-child(3)::after {
    width: 24px;
    height: 24px;
    background: var(--amber);
    clip-path: path("M12 0Q13.8 10.2 24 12Q13.8 13.8 12 24Q10.2 13.8 0 12Q10.2 10.2 12 0Z");
  }
}

@media (max-width: 43rem) {
  .hero {
    padding-top: 3.25rem;
  }

  .hero-brand {
    margin-bottom: 3.5rem;
  }
}

@media (max-width: 30rem) {
  :root { --header-gutter: 1rem; }
}

/* On phones (under 640 px wide, or landscape up to 932 px), "Get in touch"
   keeps its words beside the envelope in an outlined box. */
@media (max-width: 39.999rem), (max-height: 600px) and (min-aspect-ratio: 1/1) and (max-width: 58.25rem) {
  .header-email {
    display: inline-flex;
    width: auto;
    gap: 0.55rem;
    align-items: center;
    justify-content: center;
    padding-inline: 0.5rem;
    border: 1px solid var(--ink);
    color: var(--ink);
    font-family: var(--display);
    font-size: 0.75rem;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
  }

  .header-email > span {
    position: static;
    width: auto;
    height: auto;
    overflow: visible;
    clip-path: none;
  }

  .header-email .mail-icon { width: 1.15em; height: 1.15em; }

  .header-email:hover {
    color: var(--charcoal);
    background: var(--amber);
    border-color: var(--amber);
  }

  /* Its words are on show, so it needs no tooltip. */
  .header-email::after { content: none; }
}

/* The narrowest phones show the box with its envelope alone, keeping the
   words for assistive technology, so the logo keeps its size. */
@media (max-width: 22.5rem) {
  :root {
    --header-logo-width: clamp(6.25rem, calc(100vw - 2 * var(--header-gutter) - 9.25rem), 9rem);
  }
}

/* So do landscape phones up to 736 px wide; there the envelope matches the
   other icons and shows the tooltip. */
@media (max-width: 22.5rem), (max-height: 600px) and (min-aspect-ratio: 1/1) and (max-width: 46rem) {
  .header-email > span {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }

  .header-email { width: 2.75rem; padding: 0; }
  .header-email .mail-icon { width: 20px; height: 20px; }
  .header-email::after { content: attr(aria-label); }
}

/* Below 640 px wide, where the links take the header's second row, they span
   it with a thin rule centred between each pair: every link but the last
   takes an equal share of the spare width, with its rule in the middle of
   that share. Short landscape windows keep one row (below). */
@media (max-width: 39.999rem) and (min-height: 600.001px), (max-width: 39.999rem) and (max-aspect-ratio: 999/1000) {
  nav ul {
    justify-content: flex-start;
    gap: 0;
  }

  nav li:not(:last-child) {
    display: flex;
    flex: 1 1 auto;
    align-items: center;
  }

  nav li:not(:last-child)::after {
    content: "";
    flex: none;
    width: 1px;
    height: 0.9rem;
    margin-inline: auto;
    background: rgba(var(--ink-rgb), 0.35);
  }
}

@media (max-width: 30rem) {
  .hero-actions {
    column-gap: 1.5rem;
  }

  .service-card { column-gap: 0.75rem; }

  .service-icon {
    width: 3.75rem;
    height: 3.75rem;
  }

  /* The logo and the email address share one row. */
  .footer-inner {
    gap: 1rem;
    min-height: 4.25rem;
    padding-block: 0.75rem;
  }


  .footer-inner > a:last-child {
    overflow-wrap: anywhere;
  }
}

/* Phones: the sections sit closer, and the services are tiles, one per row
   (S1-MOBILE-001); How we work's steps follow their line and Michael's points
   stay a list. Getting started's email template opens from its label
   (template-toggle.js). */
@media (max-width: 39.999rem) {
  /* The tiles share one inner padding and gap. */
  :root { --tile-padding: clamp(0.875rem, 4vw, 1rem); --tile-gap: 0.625rem; }

  .section-inner { padding-block: 2.5rem; }
  h2 { font-size: 2rem; }
  .services h2 { margin-bottom: 1.25rem; }

  .service-grid { display: grid; gap: var(--tile-gap); }

  .service-card,
  .service-card + .service-card,
  .service-card:last-child {
    position: relative;
    padding: var(--tile-padding);
    border: 1px solid rgba(var(--ink-rgb), 0.25);
    border-radius: 0.75rem;
  }

  /* Each service keeps its title on the left and its icon on the right, with
     a faint rule beneath them, then the summary and examples. */
  .service-card .service-icon {
    width: 2rem;
    height: 2rem;
  }

  .service-card h3 { font-size: 1.125rem; }
  .service-summary { margin-top: 0.625rem; padding-top: 0.625rem; font-size: 0.875rem; line-height: 1.4; }
  .service-details { gap: 0.35rem; margin-top: 0.625rem; font-size: 0.8125rem; }

  /* How we work's tracks are cards here, swiped sideways: a swipe moves
     from one to the other, which peeks in at the edge, and settles on it.
     Each card is filled with the paler shade, set off from the section's
     page colour (its numbers too), and opens with its icon and name over a
     faint rule, as the services do. The
     page scrolls normally here. */
  .process-layout { row-gap: 1.25rem; }

  .process-tracks {
    display: flex;
    gap: var(--tile-gap);
    margin-inline: calc(-1 * var(--page-gutter));
    padding-inline: var(--page-gutter);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-padding-inline: var(--page-gutter);
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
  }

  .process-tracks::-webkit-scrollbar { display: none; }

  .process-track {
    --icon-ground: var(--surface-pale);
    flex: 0 0 86%;
    padding: 0 var(--tile-padding) var(--tile-padding);
    border: 1px solid rgba(var(--ink-rgb), 0.25);
    border-radius: 0.75rem;
    background: var(--surface-pale);
    scroll-snap-align: start;
  }

  .process-number { background: var(--surface-pale); }

  .process-track-name {
    gap: 0.625rem;
    margin-bottom: 0.875rem;
    padding: var(--tile-padding) 0 0.75rem;
    border-bottom: 1px solid rgba(var(--ink-rgb), 0.14);
    font-size: 1.0625rem;
  }

  .process-track-name .icon { width: 1.75rem; height: 1.75rem; }
  .process-intro > p { font-size: 0.95rem; }
  .process-questions { gap: 0.5rem; margin-top: 0.75rem; font-size: 0.875rem; }

  /* The steps follow the line joining their numbers, without tiles. */
  .process-list { --step-gap: 1.25rem; gap: var(--step-gap); margin-top: 1.25rem; }
  .process-list h3 { font-size: 1.0625rem; }
  .process-list p { font-size: 0.8125rem; }

  .start-layout { gap: 1.75rem; }
  .start-steps { --step-gap: 0.75rem; }

  /* Getting started's template label becomes a button, sized like it, that
     shows and hides the template (template-toggle.js), its chevron pointing down, and
     up once the template is open. */
  .js .start-template > .start-template-label,
  .js .start-template:not(.is-open) > .email-template { display: none; }

  .js .template-toggle {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    min-height: 2.75rem;
    margin-block: -0.75rem;
    padding: 0;
    border: 0;
    color: var(--accent-ink);
    background: none;
    font: 600 0.85rem / 1 var(--label);
    letter-spacing: 0.16em;
    text-transform: uppercase;
    cursor: pointer;
  }

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

  .template-toggle::after {
    content: "";
    width: 0.375rem;
    height: 0.375rem;
    border-right: 2px solid;
    border-bottom: 2px solid;
    transform: translateY(-0.15rem) rotate(45deg);
  }

  .template-toggle[aria-expanded="true"]::after { transform: translateY(0.1rem) rotate(-135deg); }

  .about-layout { gap: 2rem; }
  /* About runs compact: Starfold's story at 15 px, and Michael's points in
     full, at 14 px and 8 px apart. */
  .about-copy p { font-size: 0.95rem; }
  .about-points { gap: 0.5rem; font-size: 0.88rem; }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .skip-link {
    transition: none;
  }
}

/* Keep the opening frame tied to the live browser viewport. */
:root {
  --opening-height: 100vh;
  --opening-header-height: var(--desktop-header-height, 6rem);
}

@supports (height: 100dvh) {
  :root { --opening-height: 100dvh; }
}

.site-header {
  height: var(--opening-header-height);
}

.header-inner {
  height: 100%;
  min-height: 0;
}

.hero {
  height: calc(var(--opening-height) - var(--opening-header-height));
  min-height: 0;
  overflow-y: auto;
}

@media (max-width: 52rem), (max-width: 64rem) and (max-aspect-ratio: 799/1000) {
  /* Even spacing: the gap above the header's controls matches the gap between them and
     the links' text, and the gap from that text down to the header's rule
     (the links' 44 px targets centre their text). */
  :root { --opening-header-height: 6.5rem; }

  .header-inner {
    grid-template-rows: 44px 44px;
    padding-block: 0.875rem 0;
  }

  nav ul { margin: 0; }
  nav a { font-size: 0.75rem; }

  .hero {
    display: grid;
    grid-template-rows: auto minmax(0, 1fr);
    padding-block: 0.75rem 0.5rem;
  }

  .hero-brand {
    width: 100%;
    margin: 0 0 3rem;
  }

  .hero-content {
    min-height: 0;
    grid-template-rows: auto minmax(0, 1fr) auto;
    grid-template-areas: "copy" "diagram" "actions";
    gap: 0.5rem;
  }

  .hero h1 {
    margin-bottom: 0.5rem;
    font-size: clamp(1.625rem, 4dvh, 2.25rem);
  }

  .hero-copy > p {
    margin-bottom: 0.625rem;
    font-size: clamp(0.875rem, 2dvh, 1.125rem);
    line-height: 1.35;
  }

  .hero-actions {
    column-gap: 1.5rem;
  }

  .hero-actions .text-link {
    min-height: 2.75rem;
    font-size: 0.8125rem;
    line-height: 1.2;
  }

  .outcome-diagram {
    --diagram-label-gap: 0.5625rem;
    --diagram-label-size: clamp(0.75rem, 2.4cqw, 0.875rem);
    display: grid;
    height: 100%;
    min-height: 9rem;
    padding-block: 1.75rem;
    place-items: center;
    container-type: size;
  }

  .diagram-visual {
    width: min(calc(100cqw - 2 * var(--diagram-label-room)), 100cqh);
    max-width: 28rem;
  }

  .diagram-item > span {
    top: calc(100% + var(--diagram-label-gap));
    width: min(14rem, 100cqw);
  }

  .diagram-item[data-node="dashboards"] > span {
    top: auto;
    bottom: calc(100% + var(--diagram-label-gap));
    width: min(16rem, 100cqw);
  }

  .diagram-item[data-node="tools"] > span {
    top: 50%;
    left: auto;
    right: calc(100% + var(--label-side-gap));
    transform: translateY(-50%);
  }

  .diagram-item[data-node="website"] > span {
    top: 50%;
    left: calc(100% + var(--label-side-gap));
    transform: translateY(-50%);
  }
}

/* Portrait phones and tablets: the opening screen's spare height is shared
   evenly above the logo and between the logo, copy, diagram and links, so the
   logo sits centred between the header and the headline, and the links stay
   at the bottom. The diagram takes the size its width allows, up to 40% of
   the screen's height, shrinking only when the screen is short. */
@media (max-width: 39.999rem) and (max-aspect-ratio: 1/1),
  (max-width: 64rem) and (max-aspect-ratio: 799/1000) {
  .hero {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    gap: 0.75rem;
    padding-block: 0.875rem 0.5rem;
  }

  /* An empty first item takes a share of the space above the logo. */
  .hero::before { content: ""; }

  /* The copy's own margin and the diagram's label padding already add space
     on either side of the diagram, so the logo gets the same. */
  .hero-brand { margin: 0 0 1rem; }
  .hero-content { display: contents; }
  .hero-copy > p { margin-bottom: 0; }
  .hero-copy,
  .outcome-diagram,
  .hero-actions { align-self: stretch; }

  .outcome-diagram {
    height: calc(min(100vw - 2 * var(--page-gutter) - 2 * var(--diagram-label-room), 28rem, 40dvh - 3.5rem) + 3.5rem);
  }

  /* The links sit flush with both edges. */
  .hero-actions { justify-content: space-between; }
}

/* Where each link fits on one line, its 44 px target adds space above the
   words; draw the links up by that much so the gaps stay even. */
@media (max-width: 39.999rem) and (max-aspect-ratio: 1/1),
  (min-width: 40rem) and (max-width: 64rem) and (max-aspect-ratio: 799/1000) {
  .hero-actions { margin-top: -0.75rem; }
}

@media (max-height: 600px) and (min-aspect-ratio: 1/1) {
  :root {
    --opening-header-height: clamp(3.5rem, 12dvh, 4rem);
    --header-logo-width: 7.5rem;
    --header-control-width: 2.75rem;
  }

  .header-inner {
    grid-template-columns: var(--header-logo-width) minmax(0, 1fr) auto;
    grid-template-rows: 1fr;
    column-gap: 0.5rem;
    padding-block: 0;
  }

  nav { grid-column: 2; grid-row: 1; justify-self: end; }
  nav ul { gap: 0.75rem; margin: 0; }
  nav a { font-size: 0.75rem; }
  .header-actions { grid-column: 3; gap: 0.5rem; }
  .header-logo-slot { grid-column: 1; grid-row: 1; }

  .hero {
    display: grid;
    grid-template-columns: minmax(0, min(100%, 45rem));
    grid-template-rows: auto minmax(0, 1fr);
    gap: 0.5rem;
    justify-content: center;
    padding-block: 0.75rem 0.5rem;
  }

  .hero-brand {
    display: flex;
    width: min(100%, var(--page-width));
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin: 0 auto;
  }

  .hero-lockup {
    width: min(calc(100% - 6rem),
      calc(clamp(3.5rem, calc(var(--opening-height) - var(--opening-header-height) - 14.25rem), 12rem) * 610 / 128));
    margin: 0;
  }

  .hero-content {
    min-height: 0;
    /* The diagram column holds the circles plus both three-line capital side labels. */
    grid-template-columns: minmax(0, 0.97fr) minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr) auto;
    grid-template-areas: "copy diagram" "actions diagram";
    gap: 0 1rem;
  }

  .hero-copy { align-self: center; }
  .hero h1 { margin-bottom: 0.375rem; font-size: clamp(1.5rem, 7dvh, 2.25rem); }
  .hero-copy > p { margin-bottom: 0.5rem; font-size: clamp(0.875rem, 2.7dvh, 1.125rem); line-height: 1.35; }

  /* Too narrow for both links on one line: each wraps its words instead,
     keeping them side by side so the hero still fits the screen. */
  .hero-actions {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, max-content));
    justify-content: start;
    gap: 0 1rem;
  }
  /* Block layout keeps each arrow right after the last word when it wraps. */
  .hero-actions .text-link { display: block; min-height: 2.75rem; padding-block: 0.4rem; font-size: 0.75rem; line-height: 1.2; white-space: normal; }

  .outcome-diagram {
    --diagram-label-gap: 0.5625rem;
    --diagram-label-size: 0.75rem;
    --diagram-shift: calc((var(--diagram-label-room) - var(--diagram-label-room-end)) / 2);
    display: grid;
    height: 100%;
    min-height: 0;
    padding-block: 1.75rem;
    place-items: center;
    container-type: size;
  }

  /* Reserve both captions and gaps; the circles span 96% of the visual width.
     The shift gives the wider left caption its extra room. */
  .diagram-visual {
    width: min(calc((100cqw - var(--diagram-label-room) - var(--diagram-label-room-end)) / 0.96), 100cqh);
    max-width: 28rem;
    transform: translateX(var(--diagram-shift));
  }
  .diagram-item > span { top: calc(100% + var(--diagram-label-gap)); width: min(14rem, calc(100cqw - 2 * var(--diagram-shift))); }
  .diagram-item[data-node="dashboards"] > span { top: auto; bottom: calc(100% + var(--diagram-label-gap)); width: min(16rem, calc(100cqw - 2 * var(--diagram-shift))); }
  .diagram-item[data-node="tools"] > span { top: 50%; left: auto; right: calc(100% + var(--label-side-gap)); transform: translateY(-50%); }
  .diagram-item[data-node="website"] > span { top: 50%; left: calc(100% + var(--label-side-gap)); transform: translateY(-50%); }
}

/* Tablet-width windows that are not tall and narrow put the copy and diagram
   side by side, as on desktop, rather than leaving the space beside the copy
   empty. Tall portrait tablets keep the single column, where the diagram
   fills the height. */
@media (min-width: 40rem) and (max-width: 52rem) and (min-height: 601px) and (min-aspect-ratio: 4/5) {
  /* As on phones, the spare height is shared evenly: equal rows of space sit
     above the logo, between the logo and the copy and diagram, and above the
     links. The diagram gets the wider column, as its labels need side room,
     and the links run along the bottom on one line, flush with both edges. */
  .hero {
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1.2fr);
    grid-template-rows: 1fr auto 1fr auto 1fr auto;
    column-gap: 1.25rem;
    padding-block: 0 0.5rem;
  }

  .hero-brand { grid-column: 1 / -1; grid-row: 2; margin: 0; }
  .hero-content { display: contents; }
  .hero-copy { grid-column: 1; grid-row: 4; align-self: center; }
  .hero-copy > p { margin-bottom: 0; }

  /* The diagram's box keeps room around its labels, and the links' targets
     add space above their words; negative margins take both out of the gaps,
     so the gaps measure to what you see. */
  .outcome-diagram {
    grid-column: 2;
    grid-row: 4;
    height: calc(min((100vw - 2 * var(--page-gutter) - 1.25rem) * 0.6 - 2 * var(--diagram-label-room), 28rem, 50dvh - 3.5rem) + 3.5rem);
    margin-block: -0.875rem;
  }

  .hero-actions {
    grid-column: 1 / -1;
    grid-row: 6;
    justify-content: space-between;
    margin-top: -0.875rem;
  }
  .hero h1 { font-size: clamp(1.75rem, min(4.6vw, 6dvh), 2.5rem); }
  .hero-copy > p { font-size: clamp(1rem, 2.2vw, 1.2rem); }
}

/* The narrowest phones keep the hero's two links side by side, each on one
   line: their type shrinks with the width (about 12 px at 349 px wide and
   11 px at 320 px), which leaves at least 0.75rem between them. */
@media (max-width: 24rem) {
  .hero-actions { column-gap: 0.75rem; }
  .hero-actions .text-link { font-size: min(0.8125rem, calc((100vw - 2 * var(--page-gutter) - 0.75rem) / 24.5)); }
}

/* Landscape phones as narrow as 568 px keep the logo, four links and three
   controls in one row with a smaller logo and link text. */
@media (max-height: 600px) and (min-aspect-ratio: 1/1) and (max-width: 40rem) {
  :root { --header-logo-width: 6.25rem; }
  nav ul { gap: 0.4rem; }
  nav a { font-size: 0.6875rem; }
}

@media (min-width: 844px) and (max-height: 600px) and (min-aspect-ratio: 1/1) {
  /* One-line labels need less vertical space at wider landscape sizes. */
  .outcome-diagram { padding-block: 1.625rem; }
}

/* Slides: where each section fits the screen, scrolling moves one section at
   a time. Sections fill the space below the sticky header, and the last
   section (Getting started) shares the last screen with the footer (--footer-height
   plus its border). */
/* From 640 px wide, tablets and narrow windows have room for the header in
   one row, as on desktop: the logo, then the links, the theme and stop
   buttons and the Get in touch envelope. Short landscape
   windows have their own single row (above). */
@media (min-width: 40rem) and (max-width: 52rem) and (min-height: 600.001px),
  (min-width: 40rem) and (max-width: 64rem) and (max-aspect-ratio: 799/1000) {
  /* The shared gap grows from about 18 px at 640 px wide to 28 px from
     about 700 px; the logo takes the room the links (15.75rem), icons
     (8.25rem, side by side) and five gaps leave inside the 5vw gutters:
     about 120 px at 640-700 px wide, up to the desktop's 176 px. */
  :root {
    --opening-header-height: 4.75rem;
    --header-gap: clamp(1rem, calc(18vw - 6.1rem), 1.75rem);
    --header-logo-width: clamp(6rem, calc(90vw - 23rem - 5 * var(--header-gap)), 11rem);
  }

  .header-inner {
    grid-template-columns: var(--header-logo-width) minmax(0, 1fr) auto;
    grid-template-rows: auto;
    column-gap: calc(var(--header-gap) - 1rem);
    padding-block: 0;
  }

  /* The logo's gap to the links is the full shared gap. */
  nav { grid-column: 2; grid-row: 1; justify-self: end; margin-left: 1rem; }
  nav ul { justify-content: flex-end; margin: 0; }
  .header-actions { grid-column: 3; grid-row: 1; gap: 0; }
}

/* Portrait tablets scale the whole page up with their width, from 100% at
   768 px to 125% at 1024 px, so larger tablets show larger type rather than
   empty space. Breakpoints are unaffected: media queries use the default
   size. */
@media (min-width: 40rem) and (max-width: 64rem) and (max-aspect-ratio: 799/1000) {
  html { font-size: clamp(100%, 2.083vw, 125%); }
}

/* Tablets and tablet-width windows showing slides: Get started puts its
   template beside the introduction and steps, as on desktop, so the section
   fits one screen. */
@media (min-width: 40rem) and (max-width: 52rem) and (min-height: 43.75rem),
  (min-width: 40rem) and (max-width: 64rem) and (min-height: 43.75rem) and (max-aspect-ratio: 799/1000) {
  .start-layout {
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.9fr);
    gap: 2rem;
    align-items: center;
  }
}

/* Tablet-width windows that are not tall and narrow put About's two parts
   side by side, as on landscape tablets. */
@media (min-width: 40rem) and (max-width: 52rem) and (min-height: 43.75rem) and (min-aspect-ratio: 4/5) {
  .about-layout {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
    gap: 2rem;
  }

}

/* Sections are slides on screens at least 640 px wide and 700 px tall:
   desktops, tablets and narrower windows. Each fits its slide: on screens
   short for the content, slides.js scales it down (--fit, below), and where
   that is not enough, it turns slides off (html.slides-unfit). */
@media (min-width: 40rem) and (min-height: 43.75rem) {
  /* Read by slides.js and logo-motion.js, so the breakpoint lives only here. */
  :root { --slides: 1; }

  /* slides.js moves between sections itself, for a mouse, trackpad or touch,
     so CSS snapping stays off: when it switched back on after each glide,
     browsers re-aligned the page by a fraction of a pixel, which showed as a
     small up-and-down settle, and touch screens snapped at the browser's own,
     abrupt pace. On touch screens the script follows the finger itself while
     it runs (html.touch-slides); pinch zoom still works. Stopped or reduced
     motion scrolls entirely normally. */
  html.touch-slides { touch-action: pinch-zoom; }

  /* Align each section directly below the sticky header, for snapping and
     links alike. A margin rather than scroll padding keeps header controls
     from counting as hidden, so focusing them does not scroll the page. */
  main > section,
  section[id] {
    scroll-margin-top: var(--opening-header-height);
    scroll-snap-align: start;
  }

  main > section:not(.hero) {
    display: grid;
    align-content: center;
    min-height: calc(var(--opening-height) - var(--opening-header-height));
  }

  /* --fit (set by slides.js, 0.8–1) scales each section's content down by
     the same factor; the side margins keep their size. */
  main > section:not(.hero) > .section-inner {
    width: 100%;
    padding-block: clamp(2rem, 5dvh, 4rem);
    padding-inline: calc(var(--page-gutter) / var(--fit, 1));
    zoom: var(--fit, 1);
  }

  main > section:last-child {
    min-height: calc(var(--opening-height) - var(--opening-header-height) - var(--footer-height) - 1px);
  }

  /* How we work's two lanes scale their type and spacing with the screen's
     height too, so both fit the slide. */
  .process-layout { row-gap: clamp(0.6rem, 1.6dvh, 1.5rem); }
  .process-track { row-gap: clamp(0.5rem, 1.2dvh, 1rem); padding-block: clamp(0.6rem, 1.8dvh, 1.5rem); }
  .process-track-name { font-size: clamp(1rem, min(1.5vw, 2.6dvh), 1.35rem); }
  .process-intro > p { font-size: clamp(0.85rem, min(1.05vw, 1.9dvh), 1rem); }
  .process-questions {
    gap: clamp(0.2rem, 0.5dvh, 0.3rem);
    margin-top: clamp(0.3rem, 0.8dvh, 0.5rem);
    font-size: clamp(0.825rem, min(0.95vw, 1.75dvh), 0.9rem);
  }
  .process-list { --number-size: clamp(1.6rem, min(2.2vw, 3.6dvh), 2rem); }
  .process-list h3 { margin-top: clamp(0.4rem, 1.2dvh, 0.75rem); font-size: clamp(0.95rem, min(1.3vw, 2.3dvh), 1.2rem); }
  .process-list p { margin-top: clamp(0.2rem, 0.5dvh, 0.4rem); font-size: clamp(0.825rem, min(1vw, 1.75dvh), 0.95rem); }
  .process-list li p { padding-top: clamp(0.2rem, 0.5dvh, 0.4rem); }

  /* On wide but short screens, scale the larger type with height as well. */
  h2 { font-size: clamp(2.25rem, min(4.6vw, 7dvh), 4.5rem); }
  h3 { font-size: clamp(1.4rem, min(3.25vw, 4.5dvh), 3rem); }

  .service-icon {
    width: clamp(3.25rem, min(5.8vw, 8.6dvh), 5.75rem);
    height: clamp(3.25rem, min(5.8vw, 8.6dvh), 5.75rem);
  }

  .service-card h3 { font-size: clamp(1.4rem, min(2.1vw, 3.6dvh), 2rem); }
  /* Getting started is the last slide, which shares its screen with the
     footer, so its heading takes one line where it fits and its columns,
     steps and template sit a little closer. */
  .start-layout { column-gap: clamp(2.5rem, 5vw, 5rem); }
  .start-intro h2 { max-width: none; margin-bottom: clamp(0.75rem, 2dvh, 1.25rem); }
  .start-intro > p:not(.eyebrow) {
    margin-bottom: clamp(1rem, 2.4dvh, 1.5rem);
    font-size: clamp(1rem, min(1.3vw, 2.1dvh), 1.25rem);
  }
  .start-steps { --step-gap: clamp(0.5rem, 1.4dvh, 0.9rem); padding-top: clamp(0.75rem, 2dvh, 1.5rem); }
  .start-steps h3 { font-size: clamp(1.05rem, min(1.6vw, 2.6dvh), 1.45rem); }
  .start-steps p { font-size: clamp(0.92rem, min(1.2vw, 2dvh), 1.1rem); }
  .start-steps li p { padding-top: clamp(0.3rem, 0.8dvh, 0.4rem); }
  .start-template { gap: clamp(0.75rem, 1.6dvh, 1rem); }
  .email-template {
    padding: clamp(0.8rem, 2dvh, 1.1rem) clamp(1rem, 1.6vw, 1.25rem);
    font-size: clamp(0.85rem, min(1.05vw, 1.75dvh), 1rem);
    line-height: 1.4;
  }
  .service-summary { font-size: clamp(1rem, min(1.35vw, 2.2dvh), 1.3rem); }
  .about-copy p { font-size: clamp(1rem, min(1.35vw, 2.15dvh), 1.3rem); }
  .about-points {
    gap: clamp(0.5rem, 1.2dvh, 0.75rem);
    font-size: clamp(0.95rem, min(1.2vw, 2dvh), 1.15rem);
  }
  .service-details { font-size: clamp(0.9rem, min(1.05vw, 1.8dvh), 1.05rem); }
}

/* Desktop slides: Services, with its four cards in one row, has the most room
   on its slide, so the cards' type, icons and spacing grow with the screen's
   height to use it. */
@media (min-width: 52.001rem) and (min-aspect-ratio: 4/5) and (min-height: 43.75rem),
  (min-width: 64.001rem) and (min-height: 43.75rem) {
  .services h2 { margin-bottom: clamp(1.25rem, 6dvh, 4.5rem); }

  .service-icon {
    width: clamp(3.25rem, min(5.8vw, 9.5dvh), 6.5rem);
    height: clamp(3.25rem, min(5.8vw, 9.5dvh), 6.5rem);
  }

  .service-card h3 { font-size: clamp(1.25rem, min(2.1vw, 3.9dvh), 2.25rem); }

  .service-summary {
    margin-top: clamp(0.5rem, 1.3dvh, 0.875rem);
    padding-top: clamp(0.5rem, 1.3dvh, 0.875rem);
    font-size: clamp(1rem, min(1.5vw, 2.6dvh), 1.5rem);
  }

  .service-details {
    gap: clamp(0.45rem, 1.2dvh, 0.8rem);
    margin-top: clamp(1rem, 2.6dvh, 1.75rem);
    font-size: clamp(0.9rem, min(1.2vw, 2.1dvh), 1.25rem);
  }
}

/* Desktop slides give How we work's lanes more room: under the heading,
   inside each lane, and between each step's number, title, rule and
   description. */
@media (min-width: 64rem) and (min-aspect-ratio: 5/4) and (min-height: 43.75rem) {
  .process-layout { row-gap: clamp(1rem, 2.6dvh, 2.25rem); }
  .process-track { padding-block: clamp(0.875rem, 2.2dvh, 1.75rem); }
  .process-list h3 { margin-top: clamp(0.5rem, 1.2dvh, 0.9rem); }
  .process-list p { margin-top: clamp(0.35rem, 0.8dvh, 0.6rem); }
  .process-list li p { padding-top: clamp(0.35rem, 0.8dvh, 0.6rem); }
}
