/*
 * All styles other than the design tokens. Uses only the custom properties from tokens.css for
 * colour, spacing and radius — no hex values anywhere in this file. (Before base/01.3, the
 * monogram avatars' braces were one documented exception; real team photos replaced them, so
 * that exception no longer applies.)
 */

/* ---------- Fonts ---------- */

@font-face {
  font-family: "Archivo";
  src: url("/fonts/archivo-variable.woff2") format("woff2");
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "JetBrains Mono";
  src: url("/fonts/jetbrains-mono-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "JetBrains Mono";
  src: url("/fonts/jetbrains-mono-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "JetBrains Mono";
  src: url("/fonts/jetbrains-mono-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

/* ---------- Reset & base ---------- */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

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

body,
h1,
h2,
h3,
p,
ul,
ol,
figure {
  margin: 0;
}

ul,
ol {
  padding: 0;
  list-style: none;
}

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

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-family-mono);
  font-size: var(--font-body-size);
  line-height: var(--font-body-line-height);
  font-weight: var(--font-body-weight);
}

a {
  color: var(--link);
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
}

/* ---------- Layout helpers ---------- */

.container {
  max-width: 1152px;
  margin-inline: auto;
  padding-inline: var(--space-4);
}

@media (min-width: 768px) {
  .container {
    padding-inline: var(--space-6);
  }
}

/* "Sections are 64px apart on desktop, 48px on mobile" (space-16 / space-12) is the gap between
   one section's content and the next's, not each section's own padding. Splitting the token in
   half on each side, top and bottom, makes two adjoining sections sum to the full token value. */
.section,
.hero {
  padding-block: var(--space-6);
  /* Nav links jump straight to these ids; without this, the sticky 72px header covers the
     section label the visitor just clicked through to. */
  scroll-margin-top: 88px;
}

@media (min-width: 768px) {
  .section,
  .hero {
    padding-block: var(--space-8);
  }
}

/* The full-bleed colour bands are a visual break in their own right, so they get a more
   generous padding of their own rather than the halved inter-section gap above. */
.how-it-works,
.learn-band,
.site-footer {
  padding-block: var(--space-12);
}

@media (min-width: 768px) {
  .how-it-works,
  .learn-band,
  .site-footer {
    padding-block: var(--space-16);
  }
}

.section-label {
  font-family: var(--font-family-mono);
  font-size: var(--font-label-size);
  line-height: var(--font-label-line-height);
  font-weight: var(--font-label-weight);
  letter-spacing: var(--font-label-letter-spacing);
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: var(--space-6);
}

/* ---------- Buttons ---------- */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-6);
  border-radius: var(--radius-0);
  border: 1px solid transparent;
  font-family: var(--font-family-mono);
  font-size: var(--font-button-size);
  line-height: var(--font-button-line-height);
  font-weight: var(--font-button-weight);
  letter-spacing: var(--font-button-letter-spacing);
  text-decoration: none;
  cursor: pointer;
}

.button-primary {
  background: var(--cyanotype);
  border-color: var(--cyanotype);
  color: var(--on-cyanotype);
}

.button-primary:hover {
  background: var(--cyanotype-deep);
  border-color: var(--cyanotype-deep);
}

.button-secondary {
  background: transparent;
  border-color: var(--line-strong);
  color: var(--ink);
}

.button-secondary:hover {
  background: var(--paper-raised);
}

/* ---------- Motion: reveal on scroll + hover lift (base/01.4, D53) ---------- */

/* The hidden/offset state only exists once reveal.js has confirmed motion is allowed (it adds
   reveal-ready to <html>). Without it — JS off, or prefers-reduced-motion — every [data-reveal]
   element is simply visible, exactly as it is without this feature at all.
   --reveal-delay (base/01.5): reveal.js sets this per element for the stagger, instead of the
   `transition-delay` property directly — that property has a single value that applies to every
   transitioned property, which delayed the hover response along with the reveal (D54). Scoping
   the delay to a variable used only in the reveal entries below fixes that: hover keeps its own
   explicit 0ms delay wherever it appears. The `, 0ms` fallback covers any [data-reveal] element
   reveal.js never touched (no data-reveal-group; it only sets this per group member). */
.reveal-ready [data-reveal] {
  opacity: 0;
  transform: translateY(var(--reveal-offset));
  transition: opacity var(--motion-reveal) var(--motion-ease-out) var(--reveal-delay, 0ms),
              transform var(--motion-reveal) var(--motion-ease-out) var(--reveal-delay, 0ms);
}

.reveal-ready [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}

/* Problem cards, service rows, steps and team cards also lift on hover (see each section below).
   Their transition needs to cover background-color/translate too. A `transition` declaration
   fully replaces any other `transition` on the same element rather than merging with it, so this
   can't be split across two separate rules without one clobbering the other — the more specific
   rule right after this one folds both concerns into one list for exactly these elements.
   --hover-duration (base/01.5, D54): asymmetric timing — 80ms reacting to hover, 200ms easing
   back out on leave. A transition runs with whichever duration is in effect *after* the change,
   so the fast value only needs setting on :hover (per section below); this is the "at rest"/leave
   value. .team-photo's own transition (Team section) reads this same variable by inheritance. */
.problem-card,
.article-card,
.service-row,
.step,
.team-card {
  --hover-duration: var(--motion-hover-out);
  transition: background-color var(--hover-duration) var(--motion-ease-out) 0ms,
              translate var(--hover-duration) var(--motion-ease-out) 0ms;
}

.reveal-ready [data-reveal].problem-card,
.reveal-ready [data-reveal].article-card,
.reveal-ready [data-reveal].service-row,
.reveal-ready [data-reveal].step,
.reveal-ready [data-reveal].team-card {
  transition: opacity var(--motion-reveal) var(--motion-ease-out) var(--reveal-delay, 0ms),
              transform var(--motion-reveal) var(--motion-ease-out) var(--reveal-delay, 0ms),
              background-color var(--hover-duration) var(--motion-ease-out) 0ms,
              translate var(--hover-duration) var(--motion-ease-out) 0ms;
}

@media (prefers-reduced-motion: reduce) {
  .problem-card,
  .article-card,
  .service-row,
  .step,
  .team-card {
    translate: none;
  }
}

/* ---------- Header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--paper);
  border-bottom: 1px solid var(--grid);
}

/* min-height, not height: at 768px+ the row of content is always exactly 72px tall, giving the
   sticky bar its spec'd height, but below 768px this same element also holds the opened mobile
   nav panel (it wraps onto a second row there, see the max-width query below), which needs the
   header to grow instead of clipping it. */
.header-inner {
  min-height: 72px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
}

.logo-link {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}

.logo {
  width: 216px;
  height: auto;
}

@media (min-width: 768px) {
  .logo {
    width: 298px;
  }
}

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  padding: 0;
  background: transparent;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-0);
  cursor: pointer;
  flex-shrink: 0;
}

.nav-toggle-icon {
  width: 20px;
  height: 20px;
  stroke: var(--ink);
  stroke-width: 2;
  stroke-linecap: square;
  fill: none;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.nav-list {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.nav-list a {
  font-size: var(--font-meta-size);
  line-height: var(--font-meta-line-height);
  font-weight: var(--font-meta-weight);
  letter-spacing: var(--font-meta-letter-spacing);
  color: var(--ink-muted);
  text-decoration: none;
  white-space: nowrap;
}

.nav-list li {
  flex-shrink: 0;
}

.nav-list a:hover {
  color: var(--cyanotype);
}

/* The 4 nav links + CTA button are tight against the 720px content width right at the 768px
   breakpoint (where the logo also jumps to its full 298px). A smaller horizontal padding on the
   header's own "Book a call" button, only here, keeps it on one line at that width. */
@media (min-width: 768px) {
  .nav-cta {
    padding-inline: var(--space-3);
    white-space: nowrap;
    flex-shrink: 0;
  }
}

@media (max-width: 767.98px) {
  .header-inner {
    flex-wrap: wrap;
  }

  /* Below 768px, the nav-toggle button and the collapsed state only exist once menu.js has run
     (see the .js-enabled rules below). Without it, .site-nav keeps its default flex layout, just
     wrapped onto its own row: stacked and always visible, per the prompt's no-JS requirement. */
  .site-nav {
    order: 3;
    flex-basis: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-4);
    padding-block: var(--space-4);
  }

  .nav-list {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-3);
  }

  .nav-cta {
    width: 100%;
  }

  .js-enabled .nav-toggle {
    display: inline-flex;
  }

  .js-enabled .site-nav {
    display: none;
  }

  .js-enabled .site-nav.is-open {
    display: flex;
  }
}

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

.hero {
  position: relative;
  overflow: hidden;
}

/* Faint plus-mark drawing grid, hero only, 24px pitch, in the --grid token colour. url() can't
   reference a CSS variable, so the value is inlined here, percent-encoded, inside the data URI. */
.hero::before,
.hero::after {
  content: "";
  position: absolute;
  /* 24px bigger on every side than the hero itself, so the drift animation below never exposes
     an empty edge as it shifts the pattern around. .hero's own overflow: hidden clips it back. */
  inset: -24px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath d='M12 8v8M8 12h8' stroke='%23d5dde7' stroke-width='1' fill='none'/%3E%3C/svg%3E");
  background-repeat: repeat;
  pointer-events: none;
  z-index: 0;
  will-change: transform, opacity;
}

/* The second layer, offset by half a pitch, so its crosses sit between the first layer's. */
.hero::after {
  background-position: 12px 12px;
}

@media (prefers-reduced-motion: no-preference) {
  .hero::before,
  .hero::after {
    animation: hero-grid-shimmer 6s ease-in-out infinite alternate,
               hero-grid-drift 20s ease-in-out infinite alternate;
  }

  /* A negative delay of half the shimmer's duration starts this layer already mid-cycle, so the
     two layers shimmer in opposite phase — a twinkle, not a unison pulse. The drift stays in
     sync between the two (no delay on the second animation), so the crosses move together. */
  .hero::after {
    animation-delay: -3s, 0s;
  }
}

@media (prefers-reduced-motion: reduce) {
  /* Static grid only: .hero::before at its default full opacity (no animation ever touches it
     here), .hero::after hidden entirely rather than shown as a second motionless layer. */
  .hero::after {
    display: none;
  }
}

@keyframes hero-grid-shimmer {
  from {
    opacity: 0.35;
  }
  to {
    opacity: 1;
  }
}

@keyframes hero-grid-drift {
  from {
    transform: translate(0, 0);
  }
  to {
    transform: translate(12px, 8px);
  }
}

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

.hero-title {
  font-family: var(--font-family-display);
  font-size: var(--font-h1-size-mobile);
  line-height: var(--font-h1-line-height);
  font-weight: var(--font-h1-weight);
  letter-spacing: var(--font-h1-letter-spacing);
  max-width: 800px;
  margin-bottom: var(--space-4);
}

@media (min-width: 768px) {
  .hero-title {
    font-size: var(--font-h1-size);
  }
}

.hero-subheadline {
  font-size: var(--font-hero-subheadline-size);
  line-height: var(--font-hero-subheadline-line-height);
  font-weight: var(--font-hero-subheadline-weight);
  color: var(--ink-muted);
  max-width: 640px;
  margin-bottom: var(--space-8);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

/* ---------- Problems we solve ---------- */

.problems-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-8);
  align-items: stretch;
}

@media (min-width: 640px) {
  .problems-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1024px) {
  .problems-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.problem-card {
  background: var(--paper-raised);
  border-left: 2px solid var(--redline);
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.problem-card h3 {
  font-family: var(--font-family-display);
  font-size: var(--font-card-title-size);
  line-height: var(--font-card-title-line-height);
  font-weight: var(--font-card-title-weight);
}

.problem-card p {
  font-size: var(--font-body-size);
  line-height: var(--font-body-line-height);
  color: var(--ink-muted);
}

.card-link {
  margin-top: auto;
  font-size: var(--font-meta-size);
  line-height: var(--font-meta-line-height);
  letter-spacing: var(--font-meta-letter-spacing);
}

@media (hover: hover) and (pointer: fine) {
  .problem-card:hover {
    background: var(--cyanotype-tint);
    translate: 0 var(--hover-lift);
    --hover-duration: var(--motion-hover-in);
  }
}

/* ---------- Articles ---------- */

/* The card's secondary text on deep blue. Derived from --on-deep (like --step-divider in the
   HOW IT WORKS band), so there's no new colour. */
.article-card {
  --on-deep-muted: color-mix(in srgb, var(--on-deep) 75%, transparent);
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
}

@media (min-width: 768px) {
  .article-card {
    grid-template-columns: 1fr 1fr;
  }

  .article-card--no-media {
    grid-template-columns: 1fr;
  }
}

.article-card-media {
  display: block;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  align-self: start;
}

.article-card-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--hover-duration) var(--motion-ease-out) 0ms;
}

.article-card-panel {
  background: var(--cyanotype-deep);
  color: var(--on-deep);
  padding: var(--space-8);
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}

.article-card-title {
  font-family: var(--font-family-display);
  font-size: var(--font-feature-title-size-mobile);
  line-height: var(--font-feature-title-line-height);
  font-weight: var(--font-feature-title-weight);
}

@media (min-width: 768px) {
  .article-card-title {
    font-size: var(--font-feature-title-size);
  }
}

.article-card-title a {
  color: var(--on-deep);
  text-decoration: none;
}

.article-card-title a:hover,
.article-card-title a:focus-visible {
  text-decoration: underline;
}

/* Stretched link: the title link covers the whole card, so the card is one link (one tab stop,
   named by the title). */
.article-card-title a::after {
  content: "";
  position: absolute;
  inset: 0;
}

/* The link's own ring would only hug the title text, so the ring goes on the whole card. */
.article-card:has(.article-card-title a:focus-visible) {
  box-shadow: var(--focus-ring);
}

.article-card-title a:focus-visible {
  box-shadow: none;
}

.article-card-description {
  /* 20px: there's no spacing token for it (George, 2026-09-30). */
  margin-top: 20px;
  color: var(--on-deep-muted);
  /* Visual only: a long first paragraph must not make the panel taller than the picture. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 4;
  line-clamp: 4;
  overflow: hidden;
}

/* Two columns, narrow panel. */
@media (min-width: 768px) and (max-width: 1023.98px) {
  .article-card-description {
    -webkit-line-clamp: 3;
    line-clamp: 3;
  }
}

/* The footer row sits on the panel's bottom line: the link on the left, the byline on the right. */
.article-card-footer {
  margin-top: auto;
  padding-top: var(--space-6);
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: var(--space-4);
}

.article-card .card-link {
  margin-top: 0;
  color: var(--on-deep);
  text-decoration: underline;
}

@media (max-width: 639.98px) {
  .article-card .card-link {
    display: none;
  }
}

@media (hover: hover) and (pointer: fine) {
  .article-card:hover {
    translate: 0 var(--hover-lift);
    --hover-duration: var(--motion-hover-in);
  }

  .article-card:hover .article-card-media img {
    transform: scale(1.04);
  }

  .article-card:hover .article-card-title a {
    text-decoration: underline;
  }
}

@media (prefers-reduced-motion: reduce) {
  .article-card-media img {
    transform: none !important;
  }
}

.section-header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  column-gap: var(--space-6);
  margin-bottom: var(--space-6);
}

.section-header .section-label {
  margin-bottom: 0;
}

.section-link {
  font-size: var(--font-meta-size);
  line-height: var(--font-meta-line-height);
  letter-spacing: var(--font-meta-letter-spacing);
}

.articles-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
}

/* Side by side, the picture alternates: every even card puts it on the right. Stacked, all cards
   keep the picture on top. */
@media (min-width: 768px) {
  .articles-list > .article-card:nth-child(even) .article-card-media {
    order: 2;
  }
}

/* ---------- Home: article carousel ---------- */

.article-carousel {
  --carousel-slide: 900ms;
  --carousel-ease: cubic-bezier(0.65, 0, 0.35, 1);
}

/* All cards share one grid cell, so the block keeps the height of the tallest card and the page
   never jumps. Stacked, the panel absorbs the extra height, not a gap under the picture. */
.article-carousel-track {
  display: grid;
}

.article-carousel-track > .article-card {
  grid-area: 1 / 1;
  grid-template-rows: auto 1fr;
}

@media (min-width: 768px) {
  .article-carousel-track > .article-card {
    grid-template-rows: auto;
  }
}

/* Without the script: the newest card only, no dots. */
.article-carousel:not(.is-ready) .article-carousel-track > .article-card + .article-card,
.article-carousel:not(.is-ready) .article-carousel-dots {
  display: none;
}

/* The slide: the incoming card rises from the bottom while the outgoing one leaves through the top.
   The track clips both, so the hover lift is off inside it and the focus ring is inset. */
.article-carousel.is-ready .article-carousel-track {
  overflow: hidden;
}

.article-carousel.is-ready .article-carousel-track > .article-card {
  transform: translateY(100%);
  visibility: hidden;
  pointer-events: none;
  translate: none;
  transition: transform var(--carousel-slide) var(--carousel-ease),
              visibility 0s linear var(--carousel-slide);
}

.article-carousel.is-ready .article-carousel-track > .article-card.is-active {
  transform: translateY(0);
  visibility: visible;
  pointer-events: auto;
  transition: transform var(--carousel-slide) var(--carousel-ease),
              visibility 0s;
}

.article-carousel.is-ready .article-carousel-track > .article-card.is-leaving {
  transform: translateY(-100%);
}

.article-carousel.is-ready .article-carousel-track > .article-card.is-parked,
.article-carousel.is-ready.is-first .article-carousel-track > .article-card {
  transition: none;
}

@media (prefers-reduced-motion: reduce) {
  .article-carousel.is-ready .article-carousel-track > .article-card {
    transition: none;
  }
}

.article-carousel .article-card:has(.article-card-title a:focus-visible) {
  box-shadow: inset var(--focus-ring);
}

.article-carousel-dots {
  display: flex;
  justify-content: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
}

.article-carousel-dot {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}

.article-carousel-dot::before {
  content: "";
  width: 10px;
  height: 10px;
  border-radius: var(--radius-full);
  background: var(--grid);
  transition: width 600ms var(--carousel-ease), background-color 600ms var(--carousel-ease);
}

.article-carousel-dot[aria-current="true"]::before {
  width: 24px;
  background: var(--cyanotype);
}

.article-carousel-dot:focus-visible {
  outline: none;
  box-shadow: var(--focus-ring);
  border-radius: var(--radius-full);
}

.byline {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.author-photo {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-full);
  object-fit: cover;
  flex: none;
}

.byline-text {
  display: flex;
  flex-wrap: wrap;
  column-gap: var(--space-3);
  font-size: var(--font-meta-size);
  line-height: var(--font-meta-line-height);
  letter-spacing: var(--font-meta-letter-spacing);
  color: var(--ink-muted);
}

.author-name {
  color: var(--ink);
  font-weight: 500;
}

/* Inside the deep-blue card only: text on the left, photo at the far right, right-aligned, with
   a ring so a dark photo doesn't melt into the panel. The DOM order stays photo -> text. */
.article-card .byline-text {
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  color: var(--on-deep-muted);
}

@media (min-width: 640px) {
  .article-card .byline {
    flex-direction: row-reverse;
    justify-content: flex-start;
  }

  .article-card .byline-text {
    align-items: flex-end;
    text-align: right;
  }
}

.article-card .author-name {
  color: var(--on-deep);
}

.article-card .author-photo {
  box-shadow: 0 0 0 2px var(--on-deep);
}

.article-title {
  font-family: var(--font-family-display);
  font-size: var(--font-contact-heading-size-mobile);
  line-height: var(--font-contact-heading-line-height);
  font-weight: var(--font-contact-heading-weight);
  margin-bottom: var(--space-6);
}

@media (min-width: 768px) {
  .article-title {
    font-size: var(--font-contact-heading-size);
  }
}

.article-body {
  margin-top: var(--space-8);
}

.article-body > * + * {
  margin-top: var(--space-4);
}

/* One reading column: the title, byline, pictures, diagrams, divider and text share the same left
   and right edges, left-aligned on the logo's left edge. */
.article-container > *,
.article-body > * {
  max-width: var(--article-measure);
}

/* The `---` before the closing call to action. */
.article-body hr {
  border: 0;
  border-top: 1px solid var(--grid);
  margin: var(--space-12) 0;
  max-width: var(--article-measure);
}

.page-updated {
  margin-top: var(--space-12);
  font-size: var(--font-meta-size);
  line-height: var(--font-meta-line-height);
  letter-spacing: var(--font-meta-letter-spacing);
  color: var(--ink-muted);
}

.article-body h2 {
  font-family: var(--font-family-display);
  font-size: var(--font-contact-heading-size-mobile);
  line-height: var(--font-contact-heading-line-height);
  font-weight: var(--font-contact-heading-weight);
  margin-top: var(--space-12);
}

.article-body h3 {
  font-family: var(--font-family-display);
  font-size: var(--font-h3-size);
  line-height: var(--font-h3-line-height);
  font-weight: var(--font-h3-weight);
  margin-top: var(--space-8);
}

.article-body ul,
.article-body ol {
  padding-left: var(--space-6);
}

.article-body ul {
  list-style: disc;
}

.article-body ol {
  list-style: decimal;
}

.article-body li + li {
  margin-top: var(--space-2);
}

.article-body img {
  width: 100%;
  height: auto;
  margin-block: var(--space-6);
}

/* ---------- Services ---------- */

.services-list {
  display: flex;
  flex-direction: column;
}

.service-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
  padding-block: var(--space-8);
  /* The hover fill (below) shouldn't hug the text: this pushes the content in by space-4, then
     pulls the row's own box back out by the same amount, so the text sits exactly where it did
     before, while the row's background/border box now extends 16px beyond it on each side. At
     375px the container's own side padding is also 16px, so the two exactly cancel and the fill
     reaches the viewport edge without overflowing it. */
  padding-inline: var(--space-4);
  margin-inline: calc(-1 * var(--space-4));
}

.service-row + .service-row {
  border-top: 1px solid var(--grid);
}

@media (hover: hover) and (pointer: fine) {
  .service-row:hover {
    background: var(--paper-raised);
    translate: 0 var(--hover-lift);
    --hover-duration: var(--motion-hover-in);
  }
}

@media (min-width: 1024px) {
  .service-row {
    grid-template-columns: 28fr 40fr 32fr;
    gap: var(--space-8);
    align-items: start;
  }
}

.service-title {
  font-family: var(--font-family-display);
  font-size: var(--font-h3-size);
  line-height: var(--font-h3-line-height);
  font-weight: var(--font-h3-weight);
  margin-bottom: var(--space-2);
}

.service-format {
  font-size: var(--font-format-size);
  line-height: var(--font-format-line-height);
  font-weight: var(--font-format-weight);
  letter-spacing: var(--font-format-letter-spacing);
  color: var(--ink-muted);
}

.service-text {
  font-size: var(--font-body-size);
  line-height: var(--font-body-line-height);
  color: var(--ink-muted);
}

.service-includes {
  font-size: var(--font-you-get-size);
  line-height: var(--font-you-get-line-height);
  font-weight: var(--font-you-get-weight);
  color: var(--ink-muted);
}

.you-get-label {
  font-weight: var(--font-you-get-label-weight);
  color: var(--ink);
}

/* ---------- How it works ---------- */

.how-it-works {
  background: var(--cyanotype-deep);
  color: var(--on-deep);
  /* The band's step dividers have no token in design-tokens.json. Proposed default: on-deep at
     25% opacity (see REPORT.md), derived from the token rather than a hard-coded colour. */
  --step-divider: color-mix(in srgb, var(--on-deep) 25%, transparent);
}

.how-it-works .section-label {
  color: var(--on-deep);
}

.steps {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-8);
}

.step {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

@media (hover: hover) and (pointer: fine) {
  .how-it-works .step:hover {
    background: color-mix(in srgb, var(--on-deep) 6%, transparent);
    translate: 0 var(--hover-lift);
    --hover-duration: var(--motion-hover-in);
  }
}

@media (max-width: 767.98px) {
  .step + .step {
    border-top: 1px solid var(--step-divider);
    padding-top: var(--space-6);
  }
}

@media (min-width: 768px) {
  .steps {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--space-8);
  }

  .step + .step {
    border-left: 1px solid var(--step-divider);
    padding-left: var(--space-8);
  }
}

.step-number {
  font-family: var(--font-family-mono);
  font-size: var(--font-display-size);
  line-height: var(--font-display-line-height);
  font-weight: 400;
}

.step-title {
  font-family: var(--font-family-display);
  font-size: var(--font-h3-size);
  line-height: var(--font-h3-line-height);
  font-weight: var(--font-h3-weight);
}

.step-text {
  font-size: var(--font-body-size);
  line-height: var(--font-body-line-height);
}

/* ---------- Team ---------- */

.team-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-8);
}

@media (min-width: 768px) {
  .team-grid {
    grid-template-columns: repeat(2, 1fr);
    align-items: stretch;
  }
}

.team-card {
  background: var(--paper-raised);
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.team-photo {
  width: 96px;
  height: 96px;
  border-radius: var(--radius-full);
  object-fit: cover;
  display: block;
  /* --hover-duration isn't set here: it inherits whatever value is currently in effect on the
     ancestor .team-card (200ms at rest, 80ms on hover), so the photo's own zoom speeds up and
     slows down in step with the card's lift, without needing its own :hover rule for the timing. */
  transition: transform var(--hover-duration) var(--motion-ease-out) 0ms;
}

@media (hover: hover) and (pointer: fine) {
  /* No background change on team cards (unlike the other hoverable blocks): the lift plus the
     photo zoom below are their hover response. Hovering anywhere on the card triggers the zoom,
     not just the photo itself. */
  .team-card:hover {
    translate: 0 var(--hover-lift);
    --hover-duration: var(--motion-hover-in);
  }

  .team-card:hover .team-photo {
    /* 96px × 1.2 ≈ 115px: about 10px of growth per side, staying inside the card's 24px padding. */
    transform: scale(1.2);
  }
}

@media (prefers-reduced-motion: reduce) {
  .team-photo {
    transform: none;
  }
}

.team-name {
  font-family: var(--font-family-display);
  font-size: var(--font-team-name-size);
  line-height: var(--font-team-name-line-height);
  font-weight: var(--font-team-name-weight);
}

.team-title {
  font-size: var(--font-meta-size);
  line-height: var(--font-meta-line-height);
  font-weight: var(--font-meta-weight);
  letter-spacing: var(--font-meta-letter-spacing);
  color: var(--cyanotype);
}

.team-bio {
  font-size: var(--font-body-size);
  line-height: var(--font-body-line-height);
  color: var(--ink-muted);
}

.team-link {
  font-size: var(--font-meta-size);
  line-height: var(--font-meta-line-height);
  font-weight: 500;
  letter-spacing: var(--font-meta-letter-spacing);
  margin-top: auto;
  align-self: flex-start;
}

/* ---------- Learn with us ---------- */

.learn-band {
  background: var(--cyanotype-tint);
}

.learn-content {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-4);
}

.learn-content p {
  font-size: var(--font-learn-text-size);
  line-height: var(--font-learn-text-line-height);
  font-weight: var(--font-learn-text-weight);
  color: var(--ink-muted);
}

.tag {
  display: inline-block;
  font-family: var(--font-family-mono);
  font-size: var(--font-tag-size);
  line-height: var(--font-tag-line-height);
  font-weight: var(--font-tag-weight);
  letter-spacing: var(--font-tag-letter-spacing);
  text-transform: uppercase;
  color: var(--ink-muted);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: 6px var(--space-3);
}

/* ---------- Contact ---------- */

.contact-text {
  font-size: var(--font-contact-text-size);
  line-height: var(--font-contact-text-line-height);
  font-weight: var(--font-contact-text-weight);
  color: var(--ink-muted);
  max-width: 640px;
}

.contact-heading {
  font-family: var(--font-family-display);
  font-size: var(--font-contact-heading-size-mobile);
  line-height: var(--font-contact-heading-line-height);
  font-weight: var(--font-contact-heading-weight);
  margin-bottom: var(--space-4);
}

@media (min-width: 768px) {
  .contact-heading {
    font-size: var(--font-contact-heading-size);
  }
}

.contact-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  max-width: 640px;
  margin-top: var(--space-8);
}

.contact-form[hidden] {
  display: none;
}

.form-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.form-field label {
  font-size: var(--font-form-label-size);
  line-height: var(--font-form-label-line-height);
  font-weight: var(--font-form-label-weight);
  letter-spacing: var(--font-form-label-letter-spacing);
  text-transform: uppercase;
  color: var(--ink-muted);
}

.form-field input,
.form-field textarea {
  font-size: var(--font-input-size);
  line-height: var(--font-input-line-height);
  font-weight: var(--font-input-weight);
  color: var(--ink);
  background: var(--paper-raised);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
}

.form-field textarea {
  min-height: 160px;
  resize: vertical;
}

.contact-form .button {
  align-self: flex-start;
}

.form-field input[aria-invalid="true"],
.form-field textarea[aria-invalid="true"] {
  border-color: var(--redline);
}

.form-trap {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-note {
  font-size: var(--font-format-size);
  line-height: var(--font-format-line-height);
  color: var(--ink-muted);
}

.form-status {
  font-size: var(--font-body-size);
  line-height: var(--font-body-line-height);
  font-weight: var(--font-body-weight);
  max-width: 640px;
  margin-top: var(--space-4);
  color: var(--redline);
}

.form-status[data-status="success"] {
  color: var(--ink);
}

.form-status[hidden] {
  display: none;
}

.contact-alt {
  font-size: var(--font-contact-alt-size);
  line-height: var(--font-contact-alt-line-height);
  font-weight: var(--font-contact-alt-weight);
  color: var(--ink-muted);
  margin-top: var(--space-4);
}

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

.site-footer {
  background: var(--cyanotype-deep);
  color: var(--on-deep);
  font-size: var(--font-meta-size);
  line-height: var(--font-meta-line-height);
  font-weight: var(--font-meta-weight);
  letter-spacing: var(--font-meta-letter-spacing);
}

.site-footer a {
  color: var(--on-deep);
}

.footer-inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

@media (min-width: 768px) {
  .footer-inner {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

.footer-right {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}
