/* ==========================================================================
   Atlas — marketing site template
   Design system. Tokens at the top are the only thing a rebrand touches;
   brand.json overrides them at render time via an inline <style> block.
   ========================================================================== */

/* Self-hosted: the CSP only allows our own origin. Both are variable fonts, so
   one file each covers every weight. Fraunces carries an optical-size axis;
   the browser picks it from font-size, so large headings get the fine display
   cut and small ones get the sturdier text cut. */
@font-face {
  font-family: "Fraunces";
  src: url("/fonts/fraunces-latin-opsz-normal.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Figtree";
  src: url("/fonts/figtree-latin-wght-normal.woff2") format("woff2");
  font-weight: 300 900;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: light;

  /* Colour — overridable from brand.json */
  --accent: oklch(0.90 0.19 108);
  --accent-ink: oklch(0.18 0.02 100);
  --ink: oklch(0.17 0.008 265);
  --paper: oklch(0.985 0.004 95);

  /* Derived. Never hand-pick these; they follow the two base colours. */
  --ink-70: color-mix(in oklch, var(--ink) 70%, var(--paper));
  --ink-45: color-mix(in oklch, var(--ink) 45%, var(--paper));
  --ink-20: color-mix(in oklch, var(--ink) 20%, var(--paper));
  --ink-08: color-mix(in oklch, var(--ink) 8%, var(--paper));
  --hairline: color-mix(in oklch, var(--ink) 14%, var(--paper));
  --raised: color-mix(in oklch, var(--paper) 96%, var(--ink));

  /* Type */
  --display: "Fraunces", Georgia, "Times New Roman", serif;
  --body: "Figtree", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, monospace;

  --step--1: clamp(0.78rem, 0.76rem + 0.1vw, 0.84rem);
  --step-0: clamp(0.98rem, 0.94rem + 0.2vw, 1.08rem);
  --step-1: clamp(1.2rem, 1.1rem + 0.5vw, 1.5rem);
  --step-2: clamp(1.7rem, 1.4rem + 1.4vw, 2.6rem);
  --step-3: clamp(2.4rem, 1.7rem + 3.2vw, 4.4rem);
  --step-4: clamp(3rem, 1.4rem + 7vw, 7.5rem);

  /* Space + shape */
  --gap: clamp(0.9rem, 0.55rem + 1.3vw, 1.6rem);
  --bay: clamp(3.5rem, 2rem + 7vw, 9rem);
  --radius: 14px;
  --spine: 216px;
  --measure: 68ch;

  /* Motion.
     Custom curves, because the built-in CSS easings are too weak to read as
     a deliberate choice. ease-out for entrances, ease-in-out for something
     already on screen that moves. Interface feedback stays under 300ms; the
     hero load sequence is the one place allowed to be slower, because it is
     seen once per visit rather than dozens of times an hour. */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-soft: cubic-bezier(0.32, 0.72, 0, 1);

  --t-press: 90ms;
  --t-quick: 160ms;
  --t-enter: 240ms;

  --quick: var(--t-quick) var(--ease-out);
}

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-block-start: 5rem;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: var(--step-0);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

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

a { color: inherit; }

:where(a, button, input, textarea, select, summary):focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
  border-radius: 4px;
}

/* --------------------------------------------------------------------------
   Shared primitives
   -------------------------------------------------------------------------- */

.u-shell {
  width: min(100% - (var(--gap) * 2), 1180px);
  margin-inline: auto;
}

.u-eyebrow {
  font-family: var(--mono);
  font-size: var(--step--1);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-45);
  margin: 0 0 1.1rem;
}

.u-display {
  font-family: var(--display);
  font-weight: 400;
  letter-spacing: -0.028em;
  line-height: 0.98;
  text-wrap: balance;
  margin: 0;
}

.u-lede {
  max-width: var(--measure);
  color: var(--ink-70);
  font-size: var(--step-1);
  line-height: 1.5;
  margin: 1.4rem 0 0;
  text-wrap: pretty;
}

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

/* Skip link */
.u-skip {
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0;
  transform: translateY(-120%);
  z-index: 60;
  background: var(--ink);
  color: var(--paper);
  padding: 0.75rem 1.1rem;
  font-size: var(--step--1);
  text-decoration: none;
}
.u-skip:focus { transform: none; }

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

.btn {
  --btn-bg: var(--ink);
  --btn-fg: var(--paper);
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1.35rem;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font: inherit;
  font-size: var(--step--1);
  letter-spacing: 0.02em;
  text-decoration: none;
  cursor: pointer;
  transition:
    transform var(--t-press) var(--ease-out),
    background var(--quick),
    color var(--quick);
}

.btn:hover { transform: translateY(-2px); }

/* Answers the press immediately. Without it a click has no acknowledgement
   until the network replies, and the button feels dead in the meantime. */
.btn:active { transform: scale(0.97); }

.btn--accent {
  --btn-bg: var(--accent);
  --btn-fg: var(--accent-ink);
}

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--ink);
  border-color: var(--hairline);
}
.btn--ghost:hover { background: var(--ink-08); }

.btn__dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: currentColor;
  opacity: 0.5;
  transition: opacity var(--quick), transform var(--quick);
}
.btn:hover .btn__dot { opacity: 1; transform: translateX(3px); }

/* --------------------------------------------------------------------------
   Spine — the signature element.
   A fixed rail carrying the brand mark, the section index and a progress
   thread that fills with document scroll. It is navigation and it is the
   only decorative liberty on the page.
   -------------------------------------------------------------------------- */

.spine {
  display: none;
  position: fixed;
  inset-block: 0;
  inset-inline-start: 0;
  width: var(--spine);
  padding: 2rem 1.5rem;
  border-inline-end: 1px solid var(--hairline);
  background: var(--paper);
  z-index: 40;
  grid-template-rows: auto 1fr auto;
}

.spine__mark {
  font-family: var(--display);
  font-size: var(--step-1);
  letter-spacing: -0.02em;
  text-decoration: none;
  line-height: 1.1;
}

.spine__mark b {
  display: block;
  font-family: var(--mono);
  font-weight: 400;
  font-size: 0.62rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-45);
  margin-block-start: 0.4rem;
}

.spine__index {
  align-self: center;
  display: grid;
  gap: 0.15rem;
  margin: 0;
  padding: 0;
  list-style: none;
  position: relative;
  padding-inline-start: 1.1rem;
}

/* The thread: a hairline track with an accent fill driven by scroll. */
.spine__index::before {
  content: "";
  position: absolute;
  inset-block: 0.35rem;
  inset-inline-start: 0;
  width: 1px;
  background: var(--hairline);
}

.spine__thread {
  position: absolute;
  inset-block-start: 0.35rem;
  inset-inline-start: 0;
  width: 1px;
  height: calc(100% - 0.7rem);
  background: var(--accent);
  transform-origin: top;
  transform: scaleY(0);
}

.spine__link {
  display: block;
  padding: 0.4rem 0;
  font-size: var(--step--1);
  color: var(--ink-45);
  text-decoration: none;
  transition: color var(--quick), transform var(--quick);
}

.spine__link:hover { color: var(--ink); transform: translateX(3px); }
.spine__link[aria-current="true"] { color: var(--ink); }

.spine__foot {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  color: var(--ink-45);
  display: grid;
  gap: 0.3rem;
}

/* --------------------------------------------------------------------------
   Topbar — the spine's small-screen counterpart
   -------------------------------------------------------------------------- */

.topbar {
  position: sticky;
  inset-block-start: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.9rem var(--gap);
  border-block-end: 1px solid var(--hairline);
  background: color-mix(in oklch, var(--paper) 82%, transparent);
  backdrop-filter: blur(14px);
}

.topbar__mark {
  font-family: var(--display);
  font-size: var(--step-1);
  text-decoration: none;
  letter-spacing: -0.02em;
}

/* Declared after both navs on purpose: .spine and .topbar have equal
   specificity, so whichever is written last wins. */
@media (min-width: 1100px) {
  .spine { display: grid; }
  .topbar { display: none; }
  .page { padding-inline-start: var(--spine); }
}

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

.hero {
  position: relative;
  padding-block: clamp(4rem, 3rem + 8vw, 9rem) var(--bay);
  isolation: isolate;
}

/* Cursor-following wash. Ambient, cheap, and it never touches layout. */
.hero__wash {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(
    460px circle at var(--mx, 70%) var(--my, 28%),
    color-mix(in oklch, var(--accent) 30%, transparent),
    transparent 68%
  );
  opacity: 0;
  transition: opacity 700ms var(--ease-out);
}

.hero__wash.is-lit { opacity: 1; }

.hero__headline {
  font-size: var(--step-4);
  margin-block: 0.5rem 0;
}

/* Each line sits in a clipping frame so the reveal is a mask, not a fade. */
.hero__line {
  display: block;
  overflow: hidden;
  /* The mask used to slice the tail off g, y and p. Padding gives them room;
     the negative margin hands the space back so the lines do not drift apart. */
  padding-block-end: 0.14em;
  margin-block-end: -0.14em;
}

.hero__line > span {
  display: block;
  transform: translateY(100%);
  animation: rise 560ms var(--ease-soft) forwards;
  animation-delay: calc(var(--i, 0) * 70ms + 60ms);
}

@keyframes rise { to { transform: translateY(0); } }

/* The accent stroke. One line of the headline gets it. Nothing else does. */
.hero__stroke {
  position: relative;
  display: inline-block;
}

.hero__stroke::after {
  content: "";
  position: absolute;
  inset-inline: -0.06em;
  inset-block-end: 0.17em;
  height: 0.3em;
  border-radius: 0.04em;
  background: color-mix(in oklch, var(--accent) 62%, transparent);
  transform: scaleX(0);
  transform-origin: left;
  animation: draw 460ms var(--ease-out) forwards;
  animation-delay: 480ms;
  z-index: -1;
}

@keyframes draw { to { transform: scaleX(1); } }

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  margin-block-start: 2.4rem;
}

/* --------------------------------------------------------------------------
   Marquee — a slow ticker of operating facts
   -------------------------------------------------------------------------- */

.marquee {
  border-block: 1px solid var(--hairline);
  overflow: hidden;
  padding-block: 0.85rem;
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.marquee__track {
  display: flex;
  width: max-content;
  gap: 0;
  animation: slide 38s linear infinite;
}

.marquee:hover .marquee__track { animation-play-state: paused; }

.marquee__item {
  display: inline-flex;
  align-items: center;
  gap: 1.6rem;
  padding-inline-end: 1.6rem;
  font-family: var(--mono);
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-45);
  white-space: nowrap;
}

.marquee__item::after {
  content: "";
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}

@keyframes slide { to { transform: translateX(-50%); } }

/* --------------------------------------------------------------------------
   Stats
   -------------------------------------------------------------------------- */

.stats {
  display: grid;
  gap: 1px;
  background: var(--hairline);
  border-block-end: 1px solid var(--hairline);
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

.stats__cell {
  background: var(--paper);
  padding: clamp(1.6rem, 1rem + 2vw, 2.6rem) var(--gap);
}

.stats__value {
  font-family: var(--display);
  font-size: var(--step-3);
  letter-spacing: -0.03em;
  line-height: 1;
  display: block;
}

.stats__label {
  display: block;
  margin-block-start: 0.6rem;
  font-size: var(--step--1);
  color: var(--ink-45);
}

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

.bay {
  padding-block: var(--bay);
  border-block-end: 1px solid var(--hairline);
}

.bay__head {
  max-width: var(--measure);
  margin-block-end: clamp(2rem, 1rem + 3vw, 3.5rem);
}

.bay__title { font-size: var(--step-3); }

/* --------------------------------------------------------------------------
   Cards — container-query driven, so the same card works in any column count
   -------------------------------------------------------------------------- */

.cards {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

.card {
  container-type: inline-size;
  position: relative;
  padding: clamp(1.3rem, 1rem + 1vw, 1.9rem);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--raised);
  transition:
    border-color var(--quick),
    transform var(--t-enter) var(--ease-out);
}

.card:hover { border-color: var(--ink-20); }

.card__n {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  color: var(--ink-45);
}

.card__title {
  font-family: var(--display);
  font-size: var(--step-1);
  letter-spacing: -0.02em;
  margin: 0.9rem 0 0.5rem;
}

.card__body {
  margin: 0;
  color: var(--ink-70);
  font-size: var(--step-0);
}

@container (min-width: 400px) {
  .card__title { font-size: var(--step-2); }
}

/* --------------------------------------------------------------------------
   Steps — a real sequence, so it is numbered
   -------------------------------------------------------------------------- */

.steps {
  display: grid;
  gap: 0;
  counter-reset: step;
  margin: 0;
  padding: 0;
  list-style: none;
}

.step {
  counter-increment: step;
  display: grid;
  grid-template-columns: 3.2rem 1fr;
  gap: var(--gap);
  padding-block: clamp(1.4rem, 1rem + 1.5vw, 2.2rem);
  border-block-start: 1px solid var(--hairline);
  align-items: start;
}

.step:last-child { border-block-end: 1px solid var(--hairline); }

.step::before {
  content: counter(step, decimal-leading-zero);
  font-family: var(--mono);
  font-size: var(--step--1);
  color: var(--ink-45);
  padding-block-start: 0.35rem;
}

.step__title {
  font-family: var(--display);
  font-size: var(--step-2);
  letter-spacing: -0.025em;
  margin: 0 0 0.35rem;
}

.step__body {
  margin: 0;
  max-width: 56ch;
  color: var(--ink-70);
}

/* --------------------------------------------------------------------------
   Quotes
   -------------------------------------------------------------------------- */

.quotes {
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}

.quote {
  padding: clamp(1.4rem, 1rem + 1.5vw, 2.2rem);
  border-radius: var(--radius);
  background: var(--ink);
  color: var(--paper);
}

.quote__text {
  font-family: var(--display);
  font-size: var(--step-2);
  letter-spacing: -0.02em;
  line-height: 1.25;
  margin: 0;
  text-wrap: pretty;
}

.quote__who {
  margin-block-start: 1.6rem;
  font-family: var(--mono);
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  color: color-mix(in oklch, var(--paper) 62%, var(--ink));
}

.quote__who b {
  display: block;
  font-weight: 400;
  color: var(--accent);
}

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

.contact {
  display: grid;
  gap: clamp(2rem, 1rem + 4vw, 4rem);
  grid-template-columns: 1fr;
}

@media (min-width: 900px) {
  .contact { grid-template-columns: 1fr 1.1fr; }
}

.form {
  display: grid;
  gap: 1.1rem;
  align-content: start;
}

.field { display: grid; gap: 0.45rem; }

.field__label {
  font-family: var(--mono);
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-45);
}

.field__input {
  width: 100%;
  min-width: 0;
  padding: 0.85rem 1rem;
  border: 1px solid var(--hairline);
  border-radius: 10px;
  background: var(--paper);
  color: inherit;
  font: inherit;
  font-size: var(--step-0);
  transition: border-color var(--quick), box-shadow var(--quick);
}

.field__input:focus {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 3px color-mix(in oklch, var(--accent) 55%, transparent);
}

.field__input[aria-invalid="true"] {
  border-color: light-dark(oklch(0.55 0.19 27), oklch(0.72 0.17 27));
}

.field__note {
  font-size: var(--step--1);
  color: light-dark(oklch(0.5 0.19 27), oklch(0.74 0.17 27));
  min-height: 1.2em;
}

textarea.field__input { resize: vertical; min-height: 8rem; }

/* Honeypot. Off-screen rather than display:none so bots still fill it. */
.form__trap {
  position: absolute;
  inset-inline-start: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.form__status {
  font-size: var(--step--1);
  color: var(--ink-70);
  min-height: 1.4em;
}

.form__status[data-tone="ok"] { color: light-dark(oklch(0.5 0.14 155), oklch(0.78 0.15 155)); }
.form__status[data-tone="bad"] { color: light-dark(oklch(0.5 0.19 27), oklch(0.74 0.17 27)); }

.contact__aside {
  display: grid;
  gap: 1.3rem;
  align-content: start;
  font-size: var(--step-0);
}

.contact__row {
  display: grid;
  gap: 0.25rem;
  padding-block-end: 1.3rem;
  border-block-end: 1px solid var(--hairline);
}

.contact__row dt {
  font-family: var(--mono);
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-45);
}

.contact__row dd { margin: 0; }

.contact__row a { text-decoration-color: var(--accent); text-underline-offset: 3px; }

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

.foot {
  padding-block: 2.5rem 3rem;
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  justify-content: space-between;
  align-items: end;
  font-size: var(--step--1);
  color: var(--ink-45);
}

.foot__links {
  display: flex;
  gap: 1.2rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* --------------------------------------------------------------------------
   Work index — one row per project: number and status, the story, then the
   stack and the way in. Rows, not tiles, so a visitor can scan all four in a
   single pass and open the one they care about.
   -------------------------------------------------------------------------- */

.work {
  list-style: none;
  margin: 0;
  padding: 0;
}

.project {
  position: relative;
  display: grid;
  gap: 1.1rem var(--gap);
  padding-block: clamp(1.8rem, 1rem + 2vw, 3rem);
  border-block-start: 1px solid var(--hairline);
}

.project:last-child { border-block-end: 1px solid var(--hairline); }

/* A hairline that draws across the top edge on hover. Transform only. */
.project::before {
  content: "";
  position: absolute;
  inset-block-start: -1px;
  inset-inline: 0;
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 380ms var(--ease-out);
}

.project:hover::before { transform: scaleX(1); }

@media (min-width: 900px) {
  .project {
    grid-template-columns: 7.5rem minmax(0, 1.7fr) minmax(0, 1fr);
    align-items: start;
  }
}

.project__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.7rem 1rem;
}

@media (min-width: 900px) {
  .project__head { flex-direction: column; align-items: flex-start; }
}

.project__n {
  font-family: var(--mono);
  font-size: var(--step--1);
  letter-spacing: 0.14em;
  color: var(--ink-45);
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.2rem 0.7rem 0.2rem 0.6rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-70);
}

.pill__dot {
  position: relative;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--ink-45);
}

.pill[data-status="live"] .pill__dot { background: var(--accent); }
.pill[data-status="delivered"] .pill__dot { background: var(--ink-70); }

/* The live dot breathes. A ring scaling and fading is transform and opacity,
   so it costs nothing while the page is busy. Stopped for reduced motion. */
.pill[data-status="live"] .pill__dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0;
  animation: ring 2.4s var(--ease-out) infinite;
}

@keyframes ring {
  0% { transform: scale(1); opacity: 0.55; }
  100% { transform: scale(3.2); opacity: 0; }
}

.project__kind {
  font-family: var(--mono);
  font-size: var(--step--1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-45);
  margin: 0 0 0.5rem;
}

.project__title {
  font-family: var(--display);
  font-weight: 400;
  font-size: var(--step-3);
  letter-spacing: -0.03em;
  line-height: 1;
  margin: 0;
  text-wrap: balance;
}

.project__body {
  max-width: 58ch;
  margin: 1.1rem 0 0;
  color: var(--ink-70);
  font-size: var(--step-1);
  line-height: 1.5;
  text-wrap: pretty;
}

.project__points {
  list-style: none;
  margin: 1.4rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.55rem;
  max-width: 62ch;
}

.project__points li {
  position: relative;
  padding-inline-start: 1.4rem;
  color: var(--ink-70);
  font-size: var(--step-0);
}

.project__points li::before {
  content: "/";
  position: absolute;
  inset-inline-start: 0;
  font-family: var(--mono);
  color: var(--ink-45);
}

.project__side {
  display: grid;
  gap: 1.1rem;
  align-content: start;
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.chips li {
  padding: 0.22rem 0.7rem;
  border: 1px solid var(--hairline);
  border-radius: 999px;
  font-family: var(--mono);
  font-size: var(--step--1);
  color: var(--ink-70);
}

.project__links { display: flex; flex-wrap: wrap; gap: 0.6rem; }

.project__note {
  margin: 0;
  font-family: var(--mono);
  font-size: var(--step--1);
  color: var(--ink-45);
}

/* --------------------------------------------------------------------------
   Motion layer.
   Finished state is the default above. Everything below is enhancement and
   is stripped for reduced motion, so nothing can get stuck invisible.
   -------------------------------------------------------------------------- */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .spine__thread {
      animation: thread linear both;
      animation-timeline: scroll(root block);
    }

    @keyframes thread { to { transform: scaleY(1); } }

    .card,
    .project,
    .step,
    .quote,
    .stats__cell {
      animation: enter 1ms linear both;
      animation-timeline: view(block);
      animation-range: entry 0% entry 45%;
    }

    /* Range-driven, so the curve is the animation-range, not a duration.
       10px, finished by the time the block is under half-way into view: a long
       travel reads as decoration, a short one reads as the content arriving,
       and content near the bottom of the page never sits half-faded. */
    @keyframes enter {
      from { opacity: 0; transform: translateY(10px); }
      to { opacity: 1; transform: none; }
    }
  }
}

/* Reduced motion keeps the meaning and drops the movement. The headline
   still fades in so the page still reads as arriving; it just does not
   travel. Flattening every duration to zero would be simpler and worse. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  .hero__line { overflow: visible; }

  .hero__line > span {
    transform: none;
    animation: fade-in 320ms linear forwards;
    animation-delay: calc(var(--i, 0) * 60ms);
  }

  @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

  .hero__stroke::after { transform: scaleX(1); animation: none; }
  .hero__wash { display: none; }
  .marquee__track { animation: none; }
  .btn:hover, .btn:active { transform: none; }
  .card:hover { transform: none; }
  .pill[data-status="live"] .pill__dot::after { animation: none; }
  .project::before { transition: none; }
}

/* View transitions between pages. Same-document, so it is safe everywhere
   that supports it and a no-op where it does not. */
@view-transition { navigation: auto; }

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 220ms;
  animation-timing-function: var(--ease-out);
}

@media print {
  .spine, .topbar, .marquee, .hero__wash { display: none; }
  .page { padding: 0; }
}

/* ==========================================================================
   Portfolio layer: the shop-window version.
   Light, warm paper with near-black ink. One accent (amber), one green that
   is only ever used for WhatsApp. Everything above this line is the shared
   Atlas system; everything below is what makes this site its own.
   ========================================================================== */

:root {
  /* Eyebrows and captions were too faint on warm paper. Pulled up to pass
     AA contrast for body-size text. */
  --ink-45: color-mix(in oklch, var(--ink) 60%, var(--paper));
  --ink-70: color-mix(in oklch, var(--ink) 78%, var(--paper));
  --wa: oklch(0.5 0.13 152);
  --wa-hover: oklch(0.44 0.12 152);
  --bay: clamp(2rem, 1.2rem + 2.4vw, 3rem);
  --step-hero: clamp(2.3rem, 1.2rem + 4.1vw, 4.1rem);
  --shadow-soft: 0 1px 2px color-mix(in oklch, var(--ink) 8%, transparent),
    0 12px 32px -12px color-mix(in oklch, var(--ink) 22%, transparent);
}

body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(120% 60% at var(--glow-x, 80%) -10%, color-mix(in oklch, var(--accent) var(--glow, 10%), var(--paper)), var(--paper) 60%);
}

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

.btn { min-height: 44px; }

.btn--wa {
  --btn-bg: var(--wa);
  --btn-fg: oklch(0.99 0.005 95);
}
.btn--wa:hover { --btn-bg: var(--wa-hover); }
.btn--wa .wa-icon { flex: none; }

.btn--lg { padding: 1rem 1.7rem; font-size: var(--step-0); }
.btn--block { width: 100%; justify-content: center; }

/* -- Hero: has to show headline, promise and button on one laptop screen -- */

.hero { padding-block: clamp(2.5rem, 1rem + 4.5vw, 5rem) clamp(2.5rem, 1.5rem + 4vw, 5rem); }

.hero__grid {
  display: grid;
  gap: 2rem var(--gap);
  align-items: center;
}

.hero__headline { font-size: var(--step-hero); margin-block-start: 0.4rem; }
.hero .u-lede { font-size: var(--step-1); margin-block-start: 1.2rem; max-width: 52ch; }
.hero__actions { margin-block-start: 1.8rem; }

.hero__reassure {
  margin: 1.1rem 0 0;
  font-size: var(--step--1);
  color: var(--ink-45);
  max-width: 62ch;
  text-wrap: balance;
}

@media (min-width: 900px) {
  .hero__grid { grid-template-columns: minmax(0, 1fr) 17rem; }
}

/* -- Portrait: swaps to the real photo when public/assets/me.jpg exists ----- */

.portrait { margin: 0; max-width: 17rem; }

.portrait__frame {
  aspect-ratio: 4 / 5;
  border-radius: calc(var(--radius) + 6px);
  overflow: hidden;
  background:
    radial-gradient(90% 70% at 30% 20%, color-mix(in oklch, var(--accent) 55%, var(--paper)), transparent 70%),
    color-mix(in oklch, var(--ink) 7%, var(--paper));
  box-shadow: var(--shadow-soft);
  border: 1px solid var(--hairline);
}

.portrait__img { width: 100%; height: 100%; object-fit: cover; object-position: center 20%; }

.portrait__ph {
  height: 100%;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 0.9rem;
  text-align: center;
  color: var(--ink-70);
}

.portrait__mark {
  font-family: var(--display);
  font-size: 5rem;
  line-height: 1;
  color: var(--ink);
  opacity: 0.85;
}

.portrait__ph small { font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.08em; line-height: 1.5; }

.portrait__cap {
  margin-block-start: 0.7rem;
  font-family: var(--mono);
  font-size: var(--step--1);
  letter-spacing: 0.08em;
  color: var(--ink-45);
}

@media (max-width: 899px) {
  .portrait { max-width: 13rem; }
}

/* -- Trust strip ------------------------------------------------------------ */

.trust { border-block: 1px solid var(--hairline); background: color-mix(in oklch, var(--paper) 70%, var(--accent) 6%); }

.trust__list {
  list-style: none;
  margin-block: 0;
  padding: 1.1rem 0;
  display: grid;
  gap: 0.7rem 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}

.trust__item { display: flex; align-items: center; gap: 0.6rem; font-size: var(--step--1); color: var(--ink-70); }
.trust__item svg { flex: none; color: var(--wa); }

/* -- Work: one project, shown properly -------------------------------------- */

.project--feature { gap: 2rem var(--gap); }

@media (min-width: 1000px) {
  .project--feature { grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr); align-items: center; }
}

.project--feature .project__title { font-size: var(--step-3); }
.project--feature .project__body { font-size: var(--step-0); max-width: 52ch; }

.project__meta { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem 1rem; margin-block-end: 1rem; }
.project__meta .project__kind { margin: 0; }

.project__role {
  margin: 1rem 0 0;
  padding-inline-start: 0.9rem;
  border-inline-start: 2px solid var(--accent);
  color: var(--ink);
  font-size: var(--step-0);
  max-width: 52ch;
}

.project--feature .project__points { margin-block-start: 1.2rem; gap: 0.5rem; }

.project--feature .project__points li { padding-inline-start: 1.2rem; }
.project--feature .project__points li::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  inset-block-start: 0.7em;
}

.project--feature .project__links { margin-block-start: 1.6rem; }
.project--feature .project__note { margin-block-start: 1rem; }

/* Browser frame */

.browser__link { display: block; text-decoration: none; border-radius: var(--radius); }

.browser {
  margin: 0;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--paper);
  box-shadow: var(--shadow-soft);
  transition: transform var(--t-enter) var(--ease-out), box-shadow var(--t-enter) var(--ease-out);
}

.browser__link:hover .browser { transform: translateY(-4px); }

.browser__bar {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.65rem 0.9rem;
  background: color-mix(in oklch, var(--ink) 5%, var(--paper));
  border-block-end: 1px solid var(--hairline);
}

.browser__dots { display: flex; gap: 6px; }
.browser__dots i { width: 9px; height: 9px; border-radius: 50%; background: var(--ink-20); }

.browser__url {
  flex: 1;
  max-width: 22rem;
  padding: 0.2rem 0.8rem;
  border-radius: 999px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--ink-45);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.browser__view { aspect-ratio: 16 / 10; background: color-mix(in oklch, var(--ink) 4%, var(--paper)); }
.browser__view img { width: 100%; height: 100%; object-fit: cover; object-position: top center; }

.browser__ph {
  height: 100%;
  display: grid;
  place-content: center;
  gap: 0.5rem;
  text-align: center;
  color: var(--ink-45);
  background:
    linear-gradient(var(--hairline), var(--hairline)) 12% 18% / 30% 10px no-repeat,
    linear-gradient(var(--hairline), var(--hairline)) 12% 28% / 52% 10px no-repeat,
    linear-gradient(var(--hairline), var(--hairline)) 12% 38% / 22% 26px no-repeat;
}
.browser__ph span { font-size: var(--step-0); color: var(--ink-70); }
.browser__ph small { font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.06em; }

/* -- Services: always 2 x 2 on anything wider than a phone ------------------- */

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

.card { background: color-mix(in oklch, var(--paper) 60%, white); box-shadow: 0 1px 0 var(--hairline); }
.card__title { font-size: var(--step-2); }

/* -- Contact: WhatsApp first, form second, and the whole thing compact ------- */

.contact { gap: clamp(1.8rem, 1rem + 3vw, 3.2rem); }
.contact__cta { margin-block-start: 1.8rem; }

.contact__aside { margin: 2rem 0 0; gap: 0; }
.contact__row { padding-block: 0.8rem; gap: 0.15rem; }
.contact__row:first-child { border-block-start: 1px solid var(--hairline); }

.form {
  gap: 0.9rem;
  padding: clamp(1.1rem, 0.8rem + 1.2vw, 1.8rem);
  border: 1px solid var(--hairline);
  border-radius: calc(var(--radius) + 4px);
  background: color-mix(in oklch, var(--paper) 55%, white);
  box-shadow: var(--shadow-soft);
}

.form__intro { margin: 0; font-size: var(--step--1); color: var(--ink-70); }

.form__row { display: grid; gap: 0.9rem; }
@media (min-width: 560px) {
  .form__row { grid-template-columns: 1fr 1fr; }
}

.field { gap: 0.3rem; }
.field__label { font-size: 0.7rem; }
.field__input { padding: 0.65rem 0.85rem; background: white; }
textarea.field__input { min-height: 5.5rem; }
.field__note { margin: 0; min-height: 0; }
.field__note:empty { display: none; }

.form__foot { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem 1rem; }
.form__status { margin: 0; min-height: 0; }

/* -- Spine foot carries the WhatsApp button --------------------------------- */

.spine__foot { gap: 0.8rem; font-size: 0.68rem; }
.spine__foot .btn { font-size: 0.78rem; letter-spacing: 0.01em; padding-inline: 1rem; }

/* -- Floating WhatsApp ------------------------------------------------------- */

.wa-float {
  position: fixed;
  inset-block-end: max(1rem, env(safe-area-inset-bottom));
  inset-inline-end: 1rem;
  z-index: 50;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  min-width: 56px;
  min-height: 56px;
  padding: 0 1.15rem;
  justify-content: center;
  border-radius: 999px;
  background: var(--wa);
  color: oklch(0.99 0.005 95);
  font-size: var(--step--1);
  font-weight: 600;
  letter-spacing: 0.02em;
  text-decoration: none;
  box-shadow: 0 10px 28px -8px color-mix(in oklch, var(--wa) 70%, black);
  transition: transform var(--t-enter) var(--ease-out), opacity var(--t-enter) var(--ease-out), background var(--quick);
}

.wa-float:hover { background: var(--wa-hover); transform: translateY(-2px); }
.wa-float:active { transform: scale(0.97); }
.wa-float.is-hidden { opacity: 0; transform: translateY(10px); pointer-events: none; }

@media (max-width: 599px) {
  .wa-float { padding: 0; width: 56px; }
  .wa-float span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}

@media (prefers-reduced-motion: reduce) {
  .wa-float, .browser { transition: none; }
  .wa-float:hover, .browser__link:hover .browser { transform: none; }
}

@media print { .wa-float { display: none; } }

/* -- Section rhythm: headings introduce the work, they are not the work ----- */

.bay__title { font-size: clamp(2.1rem, 1.3rem + 2.8vw, 3.4rem); }
.bay__head { margin-block-end: clamp(1.5rem, 0.8rem + 2vw, 2.4rem); }
.bay .u-lede { font-size: var(--step-0); margin-block-start: 1rem; }
#work .project:first-child { border-block-start: 0; padding-block-start: 0.5rem; }
.project--feature .project__title { font-size: var(--step-2); }

.card__title, .step__title { font-weight: 400; }

/* -- FAQ: native details, so it works with no script ------------------------ */

.faq { max-width: 52rem; border-block-start: 1px solid var(--hairline); }
.faq__item { border-block-end: 1px solid var(--hairline); }
.faq__q {
  list-style: none;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding: 1.15rem 0;
  min-height: 44px;
  font-family: var(--display);
  font-size: var(--step-1);
  letter-spacing: -0.015em;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q::after { content: "+"; font-family: var(--mono); color: var(--ink-45); transition: transform var(--t-enter) var(--ease-out); }
.faq__item[open] .faq__q::after { transform: rotate(45deg); }
.faq__a { margin: 0 0 1.3rem; max-width: 58ch; color: var(--ink-70); }

/* -- What happens next ------------------------------------------------------- */

.next { margin-block-start: 1.8rem; }
.next__title { margin: 0 0 0.6rem; font-family: var(--mono); font-size: var(--step--1); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-45); }
.next__list { margin: 0; padding: 0; list-style: none; counter-reset: n; display: grid; gap: 0.5rem; }
.next__list li { counter-increment: n; display: flex; gap: 0.7rem; align-items: baseline; font-size: var(--step-0); color: var(--ink-70); }
.next__list li::before { content: counter(n); flex: none; width: 1.5rem; height: 1.5rem; display: grid; place-items: center; border-radius: 50%; background: var(--accent); color: var(--accent-ink); font-family: var(--mono); font-size: 0.72rem; }

/* A real screenshot keeps its own proportions, so nothing is cropped. */
.browser[data-has-shot="yes"] .browser__view { aspect-ratio: auto; }
.browser[data-has-shot="yes"] .browser__view img { height: auto; }

/* ==========================================================================
   Tightening layer: spacing, type and motion.
   Sits last on purpose. Every selector here has the same specificity as the
   rule it refines, so source order is what makes it win.
   ========================================================================== */

:root {
  /* Labels and data now share the body face. A tracked-out monospace on every
     eyebrow, pill, caption and form label was the loudest thing on the page. */
  --mono: var(--body);
  --lede: clamp(1.04rem, 0.98rem + 0.3vw, 1.2rem);
}

/* -- Type ------------------------------------------------------------------- */

.u-display {
  font-weight: 380;
  letter-spacing: -0.024em;
  line-height: 1.04;
}

.hero__headline { font-weight: 360; letter-spacing: -0.03em; line-height: 1.02; }

.card__title,
.step__title,
.project__title,
.faq__q { font-weight: 440; letter-spacing: -0.012em; }

/* Labels: sentence case, one weight up, no tracking. They read as labels
   because of size and weight, not because they are shouting. */
.u-eyebrow,
.project__kind,
.field__label,
.contact__row dt,
.next__title,
.pill,
.spine__mark b,
.portrait__cap {
  text-transform: none;
  letter-spacing: 0.01em;
  font-weight: 600;
}

.u-eyebrow { font-size: 0.88rem; margin: 0 0 0.65rem; }
.project__kind { font-size: 0.9rem; font-weight: 500; }
.pill { font-size: 0.78rem; padding: 0.15rem 0.65rem 0.15rem 0.55rem; }
.field__label { font-size: 0.82rem; letter-spacing: 0; }
.contact__row dt { font-size: 0.85rem; }
.next__title { font-size: 0.9rem; }
.spine__mark b { font-size: 0.76rem; font-weight: 500; margin-block-start: 0.3rem; }
.portrait__cap { font-size: 0.86rem; font-weight: 500; }
.project__note { font-size: 0.86rem; }
.browser__url { font-size: 0.76rem; letter-spacing: 0; }

.u-lede,
.bay .u-lede,
.hero .u-lede {
  font-size: var(--lede);
  line-height: 1.55;
  margin-block-start: 0.8rem;
}

.btn { font-size: 0.92rem; font-weight: 600; letter-spacing: 0.005em; padding: 0.75rem 1.25rem; }
.btn--lg { font-size: 1rem; padding: 0.9rem 1.5rem; }

.trust__item { font-size: 0.9rem; font-weight: 500; }
.spine__link { font-size: 0.92rem; font-weight: 500; }
.spine__foot { font-size: 0.78rem; letter-spacing: 0; }

/* Numerals in the display face, so the counters belong to the headings. */
.step::before {
  font-family: var(--display);
  font-size: 1.05rem;
  font-variant-numeric: lining-nums tabular-nums;
  padding-block-start: 0.2rem;
}

.next__list li::before { font-weight: 600; font-size: 0.75rem; }

/* -- Spacing ---------------------------------------------------------------- */

.hero { padding-block: clamp(1.75rem, 0.8rem + 3vw, 3.25rem) clamp(2rem, 1rem + 3vw, 3.5rem); }
.hero__grid { gap: 1.5rem var(--gap); }
.hero__actions { margin-block-start: 1.3rem; }
.hero__reassure { margin-block-start: 0.85rem; }

.trust__list {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.5rem 1.5rem;
  padding-block: 0.85rem;
}

.bay__title { font-size: clamp(1.9rem, 1.2rem + 2.4vw, 3rem); }
.bay__head { margin-block-end: clamp(1.1rem, 0.6rem + 1.6vw, 1.75rem); }

.project { padding-block: clamp(1.25rem, 0.8rem + 1.4vw, 2rem); }
.project--feature { gap: 1.5rem var(--gap); }
.project__role { margin-block-start: 0.85rem; }
.project--feature .project__points { margin-block-start: 1rem; }
.project--feature .project__links { margin-block-start: 1.3rem; }
.project--feature .project__note { margin-block-start: 0.8rem; }

.card { padding: clamp(1.1rem, 0.9rem + 0.7vw, 1.5rem); }
.card__title { font-size: clamp(1.3rem, 1.1rem + 0.6vw, 1.6rem); margin: 0 0 0.4rem; }

.step {
  grid-template-columns: 2.6rem 1fr;
  padding-block: clamp(0.95rem, 0.7rem + 0.9vw, 1.4rem);
}
.step__title { font-size: clamp(1.3rem, 1.1rem + 0.7vw, 1.7rem); margin-block-end: 0.2rem; }

.faq__q { padding-block: 0.9rem; font-size: clamp(1.1rem, 1.02rem + 0.35vw, 1.3rem); }
.faq__a { margin-block-end: 1.1rem; }

.contact { align-items: start; }
.contact__cta { margin-block-start: 1.4rem; }
.contact__aside { margin-block-start: 1.5rem; }
.next { margin-block-start: 1.4rem; }

.foot { padding-block: 1.75rem 2.25rem; }

/* One hairline between sections, not two. The last row of a list used to add
   its own bottom border just above the section's, so the divider doubled up. */
.project:last-child,
.step:last-child,
.faq__item:last-child { border-block-end: 0; }

.project:last-child,
.step:last-child { padding-block-end: 0; }

.faq__item:last-child .faq__q { padding-block-end: 0; }
.faq__item:last-child .faq__a { margin-block-end: 0; }

/* -- Motion ----------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  /* The headline mask is the opening move. The rest of the hero settles in
     right behind it, once, so the first screen reads as one sequence. */
  .portrait,
  .hero .u-lede,
  .hero__actions,
  .hero__reassure { animation: settle 520ms var(--ease-out) both; }

  .portrait { animation-delay: 240ms; }
  .hero .u-lede { animation-delay: 300ms; }
  .hero__actions { animation-delay: 380ms; }
  .hero__reassure { animation-delay: 450ms; }

  @keyframes settle {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: none; }
  }

  /* Answers the tap: an answer opens and closes instead of snapping.
     Browsers without ::details-content ignore the rule and keep the snap. */
  .faq { interpolate-size: allow-keywords; }

  .faq__item::details-content {
    block-size: 0;
    overflow: clip;
    transition: block-size 260ms var(--ease-out), content-visibility 260ms allow-discrete;
  }

  .faq__item[open]::details-content { block-size: auto; }
}

/* ==========================================================================
   Rhythm + phone layer.
   ========================================================================== */

/* iOS zooms the page on focus when an input is under 16px. */
.field__input { font-size: max(16px, var(--step-0)); }

/* Notch, home bar and rounded corners (viewport-fit=cover in the meta tag). */
.topbar {
  padding-block-start: max(0.9rem, env(safe-area-inset-top));
  padding-inline: max(var(--gap), env(safe-area-inset-left)) max(var(--gap), env(safe-area-inset-right));
}
.foot { padding-block-end: max(2.25rem, calc(env(safe-area-inset-bottom) + 1.25rem)); }
.wa-float { inset-inline-end: max(1rem, env(safe-area-inset-right)); }

html { scroll-padding-block-start: 4.5rem; }

@media (max-width: 899px) {
  /* The topbar already carries WhatsApp on every phone screen, and the
     floating copy sat on top of the screenshot and the form. */
  .wa-float { display: none; }

  /* Portrait: a compact card instead of a full-width block that pushed the
     trust strip a screen and a half down. */
  .portrait { max-width: 10.5rem; }
  .hero__grid { gap: 1.25rem; }
}

@media (max-width: 599px) {
  .hero__actions .btn { flex: 1 1 100%; justify-content: center; }
  .contact__cta .btn { width: 100%; justify-content: center; }
  .trust__list { justify-content: flex-start; gap: 0.45rem 1.25rem; }
  .step { grid-template-columns: 2rem 1fr; }
  .faq__q { gap: 0.75rem; }
}

/* Short landscape phones: the sticky bar must not eat the viewport. */
@media (max-height: 480px) and (orientation: landscape) {
  .topbar { position: static; }
  html { scroll-padding-block-start: 1rem; }
}

/* -- Review pass ------------------------------------------------------------ */

/* Trust strip: 2 x 2 until there is room for one row of four. Flex-wrap left
   a single orphan on its own line. */
.trust { container-type: inline-size; }

.trust__list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.6rem 1.5rem;
}

@container (min-width: 1160px) {
  .trust__list { grid-template-columns: repeat(4, auto); justify-content: space-between; }
}

@media (max-width: 479px) {
  .trust__list { grid-template-columns: 1fr; }
}

/* No single-word last lines on short copy. */
.u-lede,
.step__body,
.project__role,
.faq__a { text-wrap: balance; }

/* One reading column for the two list sections, so their hairlines end on
   the same edge instead of one running to the screen and one stopping short. */
.steps,
.faq { max-width: 52rem; }

/* Contact: the form follows the scroll beside the longer left column rather
   than leaving a block of empty space under it. */
@media (min-width: 900px) {
  .form { position: sticky; inset-block-start: 5rem; }
}

/* Inputs and the select share one height; the select used to sit 2px lower. */
input.field__input,
select.field__input { height: 3.05rem; }

/* ==========================================================================
   Kenyan layer: Nairobi time, Thika Road spine, receipt, lite mode.
   ========================================================================== */

/* -- Nairobi time in the hero eyebrow -------------------------------------- */



.live { display: inline-flex; align-items: center; }

.live__dot {
  position: relative;
  width: 7px;
  height: 7px;
  margin-inline-end: 0.55rem;
  border-radius: 50%;
  background: var(--ink-45);
}

.live[data-open="true"] .live__dot { background: var(--accent); }

.live[data-open="true"] .live__dot::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0;
  animation: ring 2.4s var(--ease-out) infinite;
}

.sep { white-space: pre; }

.clock {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
  white-space: pre;
}

.clock:hover { text-decoration-style: solid; }

/* -- Thika Road: the spine as a route ---------------------------------------- */

.spine__index { position: relative; gap: 0.35rem; }

.spine__stop { position: relative; }

.spine__link { padding-block: 0.3rem; }

.spine__stage {
  display: block;
  margin-block-start: 0.05rem;
  font-size: 0.74rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--ink-45);
}

.spine__stop::before {
  content: "";
  position: absolute;
  z-index: 1;
  inset-inline-start: calc(-1.1rem - 4px);
  inset-block-start: 1.05rem;
  width: 9px;
  height: 9px;
  margin-block-start: -4.5px;
  border-radius: 50%;
  background: var(--paper);
  border: 1.5px solid var(--ink-20);
  transition: background var(--quick), border-color var(--quick), box-shadow var(--quick);
}

.spine__stop.is-passed::before { background: var(--accent); border-color: var(--accent); }

.spine__stop:has([aria-current="true"])::before {
  box-shadow: 0 0 0 4px color-mix(in oklch, var(--accent) 32%, transparent);
}

.spine__thread {
  width: 2px;
  inset-inline-start: -0.5px;
  height: var(--track, calc(100% - 0.7rem));
  animation: none;
}

.spine__rider {
  position: absolute;
  z-index: 2;
  inset-block-start: 0;
  inset-inline-start: -6.5px;
  width: 14px;
  height: 30px;
  margin-block-start: -15px;
  pointer-events: none;
  filter: drop-shadow(0 1px 1px color-mix(in oklch, var(--ink) 30%, transparent));
}

.spine__map { width: 100%; height: auto; overflow: visible; --f: 0; }

.spine__thika { stroke: color-mix(in oklch, var(--ink) 28%, var(--paper)); stroke-width: 1.6; }

.spine__thika-run {
  stroke: var(--accent);
  stroke-width: 2.4;
  stroke-dasharray: 1;
  stroke-dashoffset: calc(1 - var(--f));
}

.spine__city { fill: var(--paper); stroke: var(--ink-45); stroke-width: 1.2; }
.spine__city--hub { fill: var(--accent); stroke: var(--ink); }

.spine__bus { fill: var(--ink); stroke: var(--paper); stroke-width: 1.2; }

.spine__maplabel { font-family: var(--body); font-size: 9px; font-weight: 600; fill: var(--ink-70); }
.spine__maplabel--hub { fill: var(--ink); font-family: ui-monospace, Menlo, Consolas, monospace; letter-spacing: 0.08em; }

.spine__plate {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  font-size: 0.74rem;
  font-weight: 600;
  line-height: 1.25;
  color: var(--ink-70);
}

.spine__plate b {
  flex: none;
  padding: 0.12rem 0.4rem;
  border-radius: 3px;
  background: var(--ink);
  color: var(--paper);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  white-space: nowrap;
}


/* Below 1100px the spine is hidden: the same route runs as a line under the bar. */
.topbar::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: -1px;
  height: 2px;
  background: var(--accent);
  transform-origin: left;
  transform: scaleX(var(--page-f, 0));
}

@media (min-width: 1100px) { .topbar::after { display: none; } }

/* -- Receipt ----------------------------------------------------------------- */

.proof__grid { display: grid; gap: clamp(1.8rem, 1rem + 3vw, 3.2rem); align-items: start; }

@media (min-width: 900px) {
  .proof__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 24rem); }
}

.proof__mode { margin: 1.2rem 0 0; font-size: var(--step--1); color: var(--ink-70); }

.proof__switch {
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-underline-offset: 3px;
  cursor: pointer;
}

.slip-wrap { display: flex; justify-content: center; }

.slip {
  width: min(100%, 24rem);
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono", Menlo, Consolas, monospace;
  font-size: 0.8rem;
  line-height: 1.5;
  color: oklch(0.27 0.01 60);
}

.slip__nojs { margin: 0 0 1rem; font-family: var(--body); color: var(--ink-70); }

.slip__paper {
  --cut: 0px;
  --s: 14px;
  padding: 1.5rem 1.3rem 2.4rem;
  background: oklch(0.975 0.008 85);
  border-radius: 3px 3px 0 0;
  filter: drop-shadow(0 18px 30px rgb(0 0 0 / 0.5));
  -webkit-mask: conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) 50% / var(--s) 100%;
  mask: conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) 50% / var(--s) 100%;
  clip-path: inset(0 0 var(--cut) 0);
  transition: clip-path 140ms linear;
  position: relative;
}

.slip__head {
  display: grid;
  justify-items: center;
  gap: 0.1rem;
  padding-block-end: 0.9rem;
  border-block-end: 1px dashed color-mix(in oklch, var(--ink) 35%, transparent);
  text-align: center;
  font-size: 0.74rem;
}

.slip__head strong { font-size: 1.2rem; letter-spacing: 0.34em; padding-inline-start: 0.34em; }

.slip__rows { list-style: none; margin: 0.9rem 0 0; padding: 0; }

.slip__row { display: flex; align-items: baseline; gap: 0.5rem; padding-block: 0.2rem; }
.slip__row > span { flex: none; max-width: 62%; }
.slip__row > i { flex: 1; min-width: 0.5rem; border-block-end: 1px dotted currentColor; opacity: 0.4; transform: translateY(-0.28em); }
.slip__row > b { flex: none; font-weight: 700; font-variant-numeric: tabular-nums; text-align: end; }

.slip__total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin: 0.8rem 0 0;
  padding-block: 0.7rem;
  border-block: 1px dashed color-mix(in oklch, var(--ink) 35%, transparent);
  font-size: 1rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.slip__not { margin-block-start: 0.9rem; font-size: 0.74rem; }
.slip__not p { margin: 0 0 0.25rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; }
.slip__not ul { list-style: none; margin: 0; padding: 0; }
.slip__not li { padding-inline-start: 1.1rem; position: relative; }
.slip__not li::before { content: "x"; position: absolute; inset-inline-start: 0; font-weight: 700; }

.slip__thanks { margin: 1.1rem 0 0; text-align: center; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; }

/* Printing: each line appears in turn, the paper revealing as it goes. */
.slip[data-state="idle"] [data-print],
.slip[data-state="ready"] [data-print],
.slip[data-state="printing"] [data-print]:not(.is-printed) { opacity: 0; transform: translateY(-5px); }

.slip [data-print] { transition: opacity 120ms linear, transform 180ms var(--ease-out); }

.slip[data-state="idle"] .slip__paper { --cut: 0px; }

@media (prefers-reduced-motion: reduce) {
  .slip__paper, .slip [data-print] { transition: none; }
}

/* -- Lite mode: the same rules reduced motion applies, plus no blur ---------- */

html[data-lite] .hero__line { overflow: visible; }
html[data-lite] .hero__line > span { transform: none; animation: none; }
html[data-lite] .hero__stroke::after { transform: scaleX(1); animation: none; }
html[data-lite] .hero__wash { display: none; }
html[data-lite] .marquee__track { animation: none; }
html[data-lite] .portrait,
html[data-lite] .hero .u-lede,
html[data-lite] .hero__actions,
html[data-lite] .hero__reassure,
html[data-lite] .card,
html[data-lite] .project,
html[data-lite] .step,
html[data-lite] .quote,
html[data-lite] .stats__cell { animation: none; }
html[data-lite] .live[data-open="true"] .live__dot::after,
html[data-lite] .pill[data-status="live"] .pill__dot::after { animation: none; }
html[data-lite] .topbar { backdrop-filter: none; background: var(--paper); }
html[data-lite] .faq__item::details-content { transition: none; }
html[data-lite] .slip__paper,
html[data-lite] .slip [data-print] { transition: none; }
html[data-lite] { scroll-behavior: auto; }

@media (prefers-reduced-motion: reduce) {
  .live[data-open="true"] .live__dot::after { animation: none; }
}

@media print { .proof { display: none; } }

/* -- Live message preview ---------------------------------------------------- */

.preview { margin-block-start: 0.4rem; }

.preview__label {
  margin: 0 0 0.45rem;
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--ink-45);
}

.bubble {
  position: relative;
  max-width: 100%;
  margin-inline-start: auto;
  padding: 0.6rem 0.8rem 0.35rem;
  border-radius: 0.9rem 0.9rem 0.2rem 0.9rem;
  background: color-mix(in oklch, var(--wa) 13%, white);
  box-shadow: 0 1px 1px color-mix(in oklch, var(--ink) 14%, transparent);
  font-size: 0.92rem;
  line-height: 1.45;
  color: var(--ink);
}

.bubble__text {
  margin: 0;
  max-height: 11rem;
  overflow: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.bubble[data-empty="true"] .bubble__text { color: var(--ink-45); }

.bubble__meta {
  display: flex;
  justify-content: flex-end;
  gap: 0.35rem;
  margin-block-start: 0.15rem;
  font-size: 0.7rem;
  color: var(--ink-45);
  font-variant-numeric: tabular-nums;
}

/* -- Hero: coordinates ------------------------------------------------------- */

.geo {
  display: block;
  margin-block-start: 0.3rem;
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono", Menlo, Consolas, monospace;
  font-size: 0.74rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  color: var(--ink-45);
}

/* -- Proof band: the engineering side, on obsidian ---------------------------
   Warm for people and promises, dark for proof. Only the tokens change.     */

.proof {
  --paper: #07090e;
  --ink: #e8ebf1;
  --ink-70: color-mix(in oklch, var(--ink) 72%, var(--paper));
  --ink-45: color-mix(in oklch, var(--ink) 52%, var(--paper));
  --ink-20: color-mix(in oklch, var(--ink) 22%, var(--paper));
  --ink-08: color-mix(in oklch, var(--ink) 9%, var(--paper));
  --hairline: color-mix(in oklch, var(--ink) 14%, var(--paper));
  background: var(--paper);
  color: var(--ink);
}

.proof .u-eyebrow {
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono", Menlo, Consolas, monospace;
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}

.proof__switch { color: var(--ink); }

.spine__plate span { flex-basis: 100%; }

/* -- Review pass 2 ------------------------------------------------------------ */

/* The time button: a 24px minimum target (WCAG 2.2), bigger on touch, no layout cost. */
.clock { padding: 0.12rem 0.1rem; margin-block: -0.12rem; min-height: 24px; }

@media (pointer: coarse) {
  .clock { padding-block: 0.5rem; margin-block: -0.5rem; }
}

.hero__stack {
  margin: 0.7rem 0 0;
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono", Menlo, Consolas, monospace;
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-70);
}

@media (prefers-reduced-motion: no-preference) {
  .hero__stack { animation: settle 520ms var(--ease-out) both; animation-delay: 520ms; }
}

html[data-lite] .hero__stack { animation: none; }

/* ==========================================================================
   Voice note, under the portrait.
   ========================================================================== */

.hero__aside { display: grid; gap: 1.1rem; max-width: 17rem; align-content: start; }

@media (max-width: 899px) {
  .hero__aside { max-width: 22rem; }
}

.vn {
  --on: var(--accent);
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-areas: "btn meta" "track track" "foot foot" "script script";
  align-items: center;
  column-gap: 0.85rem;
  row-gap: 0.6rem;
  padding: 0.85rem 0.95rem 0.8rem;
  border: 1px solid var(--hairline);
  border-radius: 1.2rem;
  background: color-mix(in oklch, white 62%, var(--paper));
  box-shadow: var(--shadow-soft);
  --level: 0;
}

.vn__btn {
  grid-area: btn;
  position: relative;
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  cursor: pointer;
  transition: transform 220ms var(--ease-out), background 220ms var(--ease-out);
  -webkit-tap-highlight-color: transparent;
}

/* The halo breathes with the real loudness of the voice. It lives on the card,
   behind the button, so the button's own transform cannot stack it on top. */
.vn::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset-block-start: 0.85rem;
  inset-inline-start: 0.95rem;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  background: var(--accent);
  opacity: calc(var(--level) * 0.4);
  transform: scale(calc(1 + var(--level) * 0.14));
  pointer-events: none;
}

.vn__btn:hover { transform: scale(1.06); }
.vn__btn:active { transform: scale(0.95); }
.vn__btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }

.vn__ico {
  position: absolute;
  width: 1.15rem;
  height: 1.15rem;
  transition: transform 300ms var(--ease-out), opacity 180ms linear;
}

.vn__ico--play { transform: translateX(1px); }
.vn__ico--pause { opacity: 0; transform: scale(0.4) rotate(-45deg); }

.vn[data-state="playing"] .vn__ico--play,
.vn[data-state="loading"] .vn__ico--play { opacity: 0; transform: scale(0.4) rotate(45deg); }

.vn[data-state="playing"] .vn__ico--pause,
.vn[data-state="loading"] .vn__ico--pause { opacity: 1; transform: none; }

.vn[data-state="loading"] .vn__btn { animation: vn-wait 1.1s ease-in-out infinite; }

@keyframes vn-wait {
  50% { background: color-mix(in oklch, var(--ink) 72%, var(--paper)); }
}

.vn__meta { grid-area: meta; display: grid; gap: 0.1rem; min-width: 0; }
.vn__title { font-size: 0.98rem; font-weight: 600; line-height: 1.25; }

.vn__time {
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono", Menlo, Consolas, monospace;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: var(--ink-45);
  font-variant-numeric: tabular-nums;
}

.vn__err { font-size: 0.78rem; line-height: 1.35; color: var(--ink-70); }

.vn__track {
  grid-area: track;
  position: relative;
  height: 44px;
  margin-inline: -0.15rem;
  cursor: pointer;
  touch-action: pan-y;
  border-radius: 0.5rem;
  -webkit-tap-highlight-color: transparent;
}

.vn__track:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.vn__track canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }

.vn__foot {
  grid-area: foot;
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: 0.8rem;
}

.vn__read,
.vn__reply {
  padding: 0.2rem 0;
  border: 0;
  background: none;
  font: inherit;
  font-weight: 600;
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 3px;
  cursor: pointer;
}

.vn__reply { color: var(--ink-70); font-weight: 500; }
.vn__read:hover, .vn__reply:hover { text-decoration-color: var(--ink); }
.vn__read:focus-visible, .vn__reply:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px; }

/* The words: height animates through grid rows, so it needs no measuring. */
.vn__script {
  grid-area: script;
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows 420ms var(--ease-out), opacity 260ms linear;
}

.vn__script[data-open="true"] { grid-template-rows: 1fr; opacity: 1; }
.vn__script-in { overflow: hidden; min-height: 0; }

.vn__script-in p {
  margin: 0;
  padding-block-start: 0.55rem;
  font-size: 0.86rem;
  line-height: 1.55;
  color: var(--ink-70);
}

.vn__script-in p:first-child { border-block-start: 1px solid var(--hairline); margin-block-start: 0.15rem; padding-block-start: 0.75rem; }

/* Until public/assets/voice.m4a exists. */
.vn--empty { grid-template-areas: "btn meta"; border-style: dashed; box-shadow: none; background: transparent; }
.vn__btn--off { opacity: 0.4; cursor: not-allowed; background: var(--ink-45); }
.vn__btn--off:hover { transform: none; }
.vn__ph { font-family: ui-monospace, "SF Mono", "Cascadia Mono", "Roboto Mono", Menlo, Consolas, monospace; font-size: 0.68rem; letter-spacing: 0.06em; line-height: 1.5; color: var(--ink-45); }

@media (prefers-reduced-motion: no-preference) {
  .vn { animation: settle 520ms var(--ease-out) both; animation-delay: 560ms; }
}

@media (prefers-reduced-motion: reduce) {
  .vn *, .vn::before { transition: none !important; animation: none !important; }
  .vn::before { display: none; }
}

html[data-lite] .vn { animation: none; }
html[data-lite] .vn *, html[data-lite] .vn__btn { transition: none; animation: none; }
html[data-lite] .vn::before { display: none; }

/* ==========================================================================
   Logo and wordmark: the mark assembles, the letters rise, 047 counts up.
   Pure CSS and inline SVG, no request. It plays once; hover the logo to replay.
   ========================================================================== */

@property --n { syntax: "<integer>"; inherits: false; initial-value: 0; }

.brand { display: grid; gap: 0.3rem; color: inherit; text-decoration: none; }
.brand__row { display: inline-flex; align-items: center; gap: 0.6rem; }

.brand__mark { display: block; flex: none; width: 1.7rem; height: auto; overflow: visible; }
.brand__mark path { transform-box: fill-box; }

.wm {
  display: inline-flex;
  align-items: baseline;
  font-family: var(--display);
  font-size: var(--step-1);
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.wm__word { display: inline-flex; overflow: hidden; padding-block: 0.12em; margin-block: -0.12em; }
.wm__word > span { display: inline-block; }

.wm__num { position: relative; font-variant-numeric: tabular-nums; }

/* The highlighter under 047 is the hero's mark in miniature, and stays. */
.wm__num::before {
  content: "";
  position: absolute;
  inset-inline: -0.02em;
  inset-block-end: 0.02em;
  height: 0.16em;
  z-index: -1;
  border-radius: 0.04em;
  background: color-mix(in oklch, var(--accent) 70%, transparent);
}

@media (prefers-reduced-motion: no-preference) {
  html:not([data-lite]) .brand--go .g-a { animation: g-a 620ms var(--ease-out) backwards; }
  html:not([data-lite]) .brand--go .g-i { animation: g-i 620ms var(--ease-out) 70ms backwards; }

  html:not([data-lite]) .brand--go .wm__word > span {
    animation: wm-rise 520ms var(--ease-out) backwards;
    animation-delay: calc(180ms + var(--i, 0) * 55ms);
  }

  /* The real digits stay in the layout, so nothing shifts; the counter paints over them. */
  html:not([data-lite]) .brand--go .wm__num { color: transparent; animation: wm-in 380ms var(--ease-out) 300ms backwards; }
  html:not([data-lite]) .brand--go .wm__num::after {
    --n: var(--to);
    content: var(--pre, "") counter(n, decimal-leading-zero);
    counter-reset: n var(--n);
    position: absolute;
    inset: 0;
    color: var(--ink);
    animation: wm-count 780ms cubic-bezier(0.2, 0.8, 0.2, 1) 420ms backwards;
  }
  html:not([data-lite]) .brand--go .wm__num::before {
    transform-origin: left;
    animation: wm-bar 420ms var(--ease-out) 1050ms backwards;
  }
}

@keyframes g-a { from { transform: translate(26px, -26px); opacity: 0; } }
@keyframes g-i { from { transform: translate(-26px, 26px); opacity: 0; } }
@keyframes wm-rise { from { transform: translateY(115%); } }
@keyframes wm-count { from { --n: 0; } }
@keyframes wm-bar { from { transform: scaleX(0); } }
@keyframes wm-in { from { opacity: 0; transform: translateY(0.3em); } }

.spine__mark.brand { gap: 0.4rem; }
.spine__mark .brand__row { gap: 0.65rem; }
.spine__mark .brand__mark { width: 1.9rem; }
.topbar__mark .brand__mark { width: 1.45rem; }
.topbar__mark .wm { font-size: 1.2rem; }
.topbar__mark.brand { display: inline-flex; }

.foot__mark { display: inline-block; width: 1.15rem; height: auto; margin-inline-end: 0.55rem; vertical-align: -0.3em; }
.slip__mark { width: 1.7rem; height: auto; margin-block-end: 0.35rem; }

/* -- Route spine on short screens: fit it, never hide it ---------------------- */

@media (min-width: 1100px) and (max-height: 760px) {
  .spine { padding-block: 1.25rem; }
  .spine__mark.brand { gap: 0.25rem; }
  .spine__mark .brand__mark { width: 1.6rem; }

  /* Stage name on the same line as the section: five rows instead of ten. */
  .spine__link { display: flex; align-items: baseline; gap: 0.5rem; }
  .spine__stage { margin: 0; }
  .spine__index { gap: 0.2rem; }
  .spine__foot { gap: 0.55rem; }
}

@media (min-width: 1100px) and (max-height: 500px) {
  .spine__plate { display: none; }
}

@media (min-width: 1100px) and (max-height: 440px) {
  .spine__map { display: none; }
}

/* -- Touch targets, narrow phones, receipt row --------------------------------
   Links and buttons that were 15 to 38px tall get a larger hit area. The
   negative margin cancels the padding so nothing moves on the page. Every
   size gets the 24px WCAG minimum; phones and touch screens get 44px. */

.contact__row a,
.foot__links a,
.proof__switch {
  display: inline-block;
  padding-block: 0.25rem;
  margin-block: -0.25rem;
}

@media (max-width: 1099px), (pointer: coarse) {
  .contact__row a,
  .foot__links a,
  .proof__switch,
  .topbar__mark,
  .clock {
    display: inline-block;
    padding-block: 0.8rem;
    margin-block: -0.8rem;
  }
  .foot__links { gap: 0.4rem 1.2rem; }
  .foot__links a,
  .proof__switch,
  .clock { padding-inline: 0.4rem; margin-inline: -0.4rem; }
}

/* The top-bar button wrapped to two lines at 320px. */
.topbar .btn { white-space: nowrap; }

/* A long value in a receipt row must shrink, not push the page wider. */
.slip__row > b { flex: 0 1 auto; min-width: 0; overflow-wrap: anywhere; }

/* Small decorative labels, one step larger. */
.spine__maplabel { font-size: 10.5px; }
.spine__plate b { font-size: 0.75rem; }

/* == MOBILE LEAN ================================================================
   Phones only (700px and under). A short version of the page: say who we are,
   show one real piece of work, answer the questions, make WhatsApp easy.
   Only CSS lives here, so desktop and tablet are untouched. Delete any line in
   this block to bring that item back on phones. */

@media (max-width: 700px) {
  /* Top of page: greeting, headline, one line, one button. */
  .hero__stack,
  .hero__reassure,
  .hero__actions .btn--ghost { display: none; }

  /* Photo and voice note become one small row. With no photo yet, the empty
     tile and the setup card are hidden instead of taking up the screen. */
  .hero__aside { display: flex; align-items: center; gap: 0.9rem; max-width: none; }
  .portrait { flex: none; width: 5.5rem; max-width: 5.5rem; }
  .portrait[data-has-photo="no"],
  .vn--empty { display: none; }
  .hero__aside .vn { flex: 1 1 auto; min-width: 0; }

  /* Work: the shop, one paragraph, the button. Details stay on desktop. */
  .project__points,
  .project__role,
  .project__note { display: none; }

  /* Two promises, not three. */
  .trust__item:nth-child(3) { display: none; }

  /* What we build and How we work: titles only. */
  .card__body,
  .step__body { display: none; }
  #build .card { padding-block: 0.8rem; }

  /* The receipt is for bigger screens. */
  #proof { display: none; }
}

/* == DESKTOP: heading beside content ============================================
   On wide screens the three list sections put their heading in a left column and
   the content on the right, instead of stacking a tall heading over a list with
   empty space beside it. The heading stays in view while the list scrolls.
   Below 1200px nothing changes. Delete this block to go back to stacked. */

@media (min-width: 1200px) {
  #build > .u-shell,
  #how > .u-shell,
  #faq > .u-shell {
    display: grid;
    grid-template-columns: minmax(15rem, 21rem) minmax(0, 1fr);
    column-gap: clamp(2.5rem, 5vw, 4.5rem);
    align-items: start;
  }

  #build .bay__head,
  #how .bay__head,
  #faq .bay__head {
    margin-block-end: 0;
    position: sticky;
    top: 2.5rem;
  }

  #build .bay__title,
  #how .bay__title,
  #faq .bay__title { font-size: clamp(1.9rem, 1rem + 1.7vw, 2.5rem); }

  /* The four rules sit two by two, number above the title. */
  #how .steps {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: clamp(2rem, 4vw, 3rem);
    max-width: none;
  }
  #how .step { grid-template-columns: minmax(0, 1fr); gap: 0.5rem; }
  #how .step::before { padding-block-start: 0; }
  #how .step:nth-last-child(2) { border-block-end: 0; padding-block-end: 0; }
}

/* Between 1200 and 1399px the right column is too narrow for two service cards. */
@media (min-width: 1200px) and (max-width: 1399px) {
  #build .cards { grid-template-columns: minmax(0, 1fr); }
  #how .steps { grid-template-columns: minmax(0, 1fr); }
  #how .step:nth-last-child(2) { border-block-end: 1px solid var(--hairline); padding-block-end: clamp(0.95rem, 0.7rem + 0.9vw, 1.4rem); }
  #how .step { grid-template-columns: 2.6rem 1fr; gap: var(--gap); }
}

/* == DECLUTTER ==================================================================
   One main button in the hero, services as a plain list, the contact form and the
   full receipt folded away until someone wants them. Applies on every screen. */

.hero__actions .btn--ghost {
  background: none;
  border-color: transparent;
  box-shadow: none;
  padding-inline: 0.4rem;
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-underline-offset: 4px;
}
.hero__actions .btn--ghost:hover { background: none; }

/* What we build: four rows, title then one line. */
#build .cards { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0; border-block-start: 1px solid var(--hairline); }
#build .card {
  display: grid;
  grid-template-columns: minmax(9rem, 13rem) minmax(0, 1fr);
  gap: 0.2rem 1.5rem;
  align-items: baseline;
  padding: 0.95rem 0;
  border: 0;
  border-block-end: 1px solid var(--hairline);
  border-radius: 0;
  background: none;
  box-shadow: none;
}
#build .card__title { margin: 0; font-size: clamp(1.2rem, 1.05rem + 0.5vw, 1.45rem); }
@media (max-width: 560px) {
  #build .card { grid-template-columns: minmax(0, 1fr); }
}

/* Contact: phone and email beside the WhatsApp column, the form behind one line. */
.contact__side { display: grid; gap: 1.4rem; align-content: start; }
.contact__side .contact__aside { margin: 0; }
.formfold__sum,
.slipfold__sum {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 44px;
  padding: 0.8rem 1.1rem;
  border: 1px solid var(--hairline);
  border-radius: calc(var(--radius) + 4px);
  background: color-mix(in oklch, var(--paper) 55%, white);
  color: var(--ink);
  font-weight: 600;
}
.formfold__sum::-webkit-details-marker,
.slipfold__sum::-webkit-details-marker { display: none; }
.formfold__sum::after,
.slipfold__sum::after { content: "+"; font-family: var(--mono); color: var(--ink-45); }
.formfold[open] > .formfold__sum::after,
.slipfold[open] > .slipfold__sum::after { content: "\2212"; }
.formfold[open] > .formfold__sum { margin-block-end: 0.8rem; }
.formfold .form { position: static; }

/* Proof: the numbers in one line, the full receipt on request. */
.proof__facts b { color: var(--ink); font-weight: 600; white-space: nowrap; }
.slipfold__sum { background: none; border-color: var(--ink-20); }
.slipfold[open] > .slipfold__sum { margin-block-end: 1.5rem; }


/* ==========================================================================
   Legal pages (/privacy, /terms) and the consent line under the form
   ========================================================================== */

.legal__bar { border-block-end: 1px solid var(--hairline); background: var(--paper); }

.legal__barin {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem 1.5rem;
  padding-block: 0.9rem;
}

.legal__nav { display: flex; flex-wrap: wrap; gap: 0.2rem 1.4rem; font-size: var(--step--1); }

.legal__nav a {
  color: var(--ink-70);
  text-decoration: none;
  padding-block: 0.5rem;
}

.legal__nav a:hover { color: var(--ink); }

.legal__nav a[aria-current="page"] {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 6px;
}

.legal { padding-block: clamp(2rem, 1rem + 5vw, 5rem) var(--bay); }

.legal__col { max-width: 44rem; margin-inline: auto; }

.legal__title { font-size: var(--step-3); margin: 0.2rem 0 0.7rem; }

.legal__meta { margin: 0 0 1.6rem; color: var(--ink-45); font-size: var(--step--1); }

.legal__intro {
  margin: 0;
  color: var(--ink-70);
  font-size: var(--step-1);
  line-height: 1.5;
  text-wrap: pretty;
}

.legal h2 {
  margin: 2.6rem 0 0.7rem;
  font-family: var(--display);
  font-weight: 500;
  font-size: var(--step-1);
  letter-spacing: -0.015em;
  line-height: 1.2;
  text-wrap: balance;
}

.legal p,
.legal li { color: var(--ink-70); line-height: 1.65; max-width: 68ch; }

.legal p { margin: 0 0 0.9rem; text-wrap: pretty; }

.legal ul { display: grid; gap: 0.6rem; margin: 0 0 0.9rem; padding-inline-start: 1.25rem; }

.legal li::marker { color: var(--accent); }

.legal a {
  color: var(--ink);
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

.form__consent {
  margin: 0 0 0.9rem;
  color: var(--ink-70);
  font-size: var(--step--1);
  line-height: 1.5;
}

.form__consent a {
  color: inherit;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

@media print { .legal__bar { display: none; } }
