/* ============ Design tokens ============ */
:root {
  --bg: #ffffff;
  --bg-tint: #f4faf8;
  --green-deep: #1e6f5c;
  --green-mid: #2e8b74;
  --green-soft: #5bb39a;
  --green-dark: #0f3d33;
  --sky: #bfe6e0;
  --sky-light: #ddf1ee;
  --sun: #efc75e;
  --ink: #3a3a3a;
  --muted: #7a8580;
  --line: #e3ece8;

  --font-display: "Cormorant", Georgia, serif;
  --font-body: "IBM Plex Sans", system-ui, -apple-system, sans-serif;

  --container: 1100px;
  --header-h: 68px;

  /* Motion: confident, calm deceleration — no bounce, no elastic.
     Matches the organic, editorial mood of the brand. */
  --ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-cue: cubic-bezier(0.23, 1, 0.32, 1);
}

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

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.65;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
  font-family: var(--font-display);
  color: var(--green-deep);
  line-height: 1.1;
  margin: 0 0 0.5em;
}

h1 {
  font-size: clamp(2.6rem, 6vw, 4.2rem);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

h2 {
  font-size: clamp(2rem, 4vw, 2.8rem);
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

h3 {
  font-family: var(--font-body);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--green-dark);
  letter-spacing: 0.01em;
}

p {
  margin: 0 0 1em;
}

a {
  color: var(--green-deep);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
}

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

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

.kicker {
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--green-soft);
  margin-bottom: 0.4em;
}

/* ============ Buttons ============ */
.btn {
  display: inline-block;
  background: var(--green-deep);
  color: #fff;
  font-family: var(--font-body);
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  border: none;
  border-radius: 999px;
  padding: 14px 36px;
  cursor: pointer;
  transition:
    background 0.2s ease,
    transform 0.18s var(--ease-out-quint),
    box-shadow 0.2s ease;
}

@media (hover: hover) and (pointer: fine) {
  .btn:hover {
    background: var(--green-mid);
    transform: translateY(-2px);
    box-shadow: 0 8px 20px -8px rgba(30, 111, 92, 0.5);
  }
}

.btn:active {
  transform: translateY(0) scale(0.97);
  box-shadow: none;
}

.btn-small {
  padding: 9px 24px;
  font-size: 0.75rem;
}

/* ============ Header / nav ============ */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}

/* With JS the header starts transparent so the hero art flows to the very
   top of the screen (as in the reference), and gains its white fill once
   the page scrolls. Without JS it stays solid — always readable. */
.js .site-header {
  background: transparent;
  backdrop-filter: none;
  border-bottom-color: transparent;
  transition: background 0.3s ease, border-color 0.3s ease;
}

.js .site-header.scrolled {
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(8px);
  border-bottom-color: var(--line);
}

.nav-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 68px;
}

.wordmark {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

.wordmark img {
  width: 168px;
  height: auto;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 28px;
}

.site-nav a:not(.btn) {
  position: relative;
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  transition: color 0.2s ease;
}

.site-nav a:not(.btn)::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -5px;
  width: 100%;
  height: 1.5px;
  background: var(--green-soft);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.28s var(--ease-out-quint);
}

@media (hover: hover) and (pointer: fine) {
  .site-nav a:not(.btn):hover {
    color: var(--green-deep);
  }

  .site-nav a:not(.btn):hover::after {
    transform: scaleX(1);
  }
}

.nav-toggle {
  display: none;
  flex-direction: column;
  gap: 5px;
  background: none;
  border: none;
  padding: 8px;
  cursor: pointer;
}

.nav-toggle span {
  width: 22px;
  height: 2px;
  background: var(--green-deep);
  border-radius: 2px;
}

/* ============ Hero ============ */
.hero {
  position: relative;
  overflow: hidden;
  /* The hero slides up under the transparent header so the illustration
     reaches the very top of the screen; the padding keeps the copy clear
     of the nav. svh avoids the iOS Safari URL-bar jump that 100vh causes. */
  min-height: 100svh;
  margin-top: calc(-1 * var(--header-h));
  padding-top: var(--header-h);
  display: flex;
  align-items: center;
}

.hero-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: 40px;
  width: 100%;
  padding-block: 48px;
}

.hero-copy .lede {
  max-width: 42ch;
  color: var(--muted);
  font-size: 1.05rem;
  margin-bottom: 2em;
}

.hero-copy {
  min-width: 0;
}

/* Highlighted word in the headline: a hand-drawn sun-yellow swash
   underneath, echoing the sun and organic curves of the illustration. */
.hl {
  position: relative;
  z-index: 0;
  white-space: nowrap;
}

.hl::after {
  content: "";
  position: absolute;
  left: -1%;
  right: -1%;
  bottom: 0.02em;
  height: 0.16em;
  z-index: -1;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 12' preserveAspectRatio='none'%3E%3Cpath d='M3 9 Q30 3 60 7 T117 5' fill='none' stroke='%23EFB95C' stroke-width='5' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat center / 100% 100%;
}

/* The swash draws in left-to-right once the headline has landed. */
.js .hero .hl::after {
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 0.7s var(--ease-out-expo) 0.75s;
}

.js .hero.loaded .hl::after {
  transform: scaleX(1);
}

/* The technology illustration bleeds to the screen edge and fills the
   entire right half of the hero. */
.hero-art {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 50%;
  overflow: hidden;
}

.hero-art img {
  width: 100%;
  height: calc(100% + 60px);
  margin-top: -60px;
  object-fit: cover;
  object-position: center;
}

/* ---- Hero load-in sequence (JS enhancement) ----
   On first paint, the headline, lede, CTA, then the illustration rise and
   fade in one after another. JS-gated so the page is fully visible without
   JS. The hero-copy uses .reveal, so we drive its children directly here
   and let .loaded release them in order. */
.js .hero .hero-load {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity 0.8s var(--ease-out-quint),
    transform 0.8s var(--ease-out-quint);
  transition-delay: calc(var(--seq, 0) * 110ms);
}

.js .hero.loaded .hero-load {
  opacity: 1;
  transform: none;
}

/* The illustration drifts up from the floor a touch later, anchored bottom. */
.js .hero .hero-art {
  opacity: 0;
  transform: translateY(28px);
  transition:
    opacity 1.1s var(--ease-out-expo),
    transform 1.1s var(--ease-out-expo);
  transition-delay: 0.32s;
}

.js .hero.loaded .hero-art {
  opacity: 1;
  transform: none;
}

.js .hero .scroll-cue {
  opacity: 0;
  transition: opacity 0.8s var(--ease-out-quint);
  transition-delay: 1s;
}

.js .hero.loaded .scroll-cue {
  opacity: 1;
}

/* ============ Scroll affordance ============ */
.scroll-cue {
  position: absolute;
  /* Centered under the copy column — the art now owns the right half. */
  left: 25%;
  bottom: 22px;
  transform: translateX(-50%);
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--green-soft);
  text-decoration: none;
}

.scroll-cue .scroll-track {
  width: 22px;
  height: 34px;
  border: 1.5px solid var(--green-soft);
  border-radius: 999px;
  display: flex;
  justify-content: center;
  padding-top: 6px;
}

.scroll-cue .scroll-dot {
  width: 3px;
  height: 7px;
  border-radius: 999px;
  background: var(--green-soft);
  animation: scroll-cue-drift 1.9s cubic-bezier(0.23, 1, 0.32, 1) infinite;
}

@keyframes scroll-cue-drift {
  0% {
    opacity: 0;
    transform: translateY(-3px);
  }
  35% {
    opacity: 1;
  }
  70% {
    opacity: 0;
    transform: translateY(9px);
  }
  100% {
    opacity: 0;
    transform: translateY(9px);
  }
}

/* ============ Sections ============ */
.section {
  padding-block: 96px;
}

.section-tint {
  background: var(--bg-tint);
}

/* ============ Grids & cards ============ */
.grid {
  display: grid;
  gap: 24px;
  margin-top: 48px;
}

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

.grid-3 {
  grid-template-columns: repeat(3, 1fr);
}

.grid > * {
  min-width: 0;
}

.card {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 28px 24px;
  transition:
    transform 0.32s var(--ease-out-quint),
    box-shadow 0.32s var(--ease-out-quint),
    border-color 0.32s var(--ease-out-quint);
}

@media (hover: hover) and (pointer: fine) {
  .card:hover {
    transform: translateY(-4px);
    border-color: var(--sky);
    box-shadow: 0 18px 36px -20px rgba(15, 61, 51, 0.28);
  }

  /* Ghost cards are placeholders — lift, but no heavy shadow on dashed edges. */
  .card-ghost:hover {
    transform: translateY(-3px);
    box-shadow: none;
  }
}

.card p {
  font-size: 0.92rem;
  color: var(--muted);
  margin-bottom: 0;
}

.card h3 a {
  color: inherit;
  text-decoration: none;
}

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

.glyph {
  width: 32px;
  height: 32px;
  color: var(--green-mid);
  margin-bottom: 16px;
}

.work-card .tag {
  display: inline-block;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green-deep);
  background: var(--sky-light);
  border-radius: 999px;
  padding: 4px 12px;
  margin-bottom: 16px;
}

.work-card .tag-live {
  background: #e3f5d9;
  color: #2e6b2e;
}

.card-links {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: 16px;
}

.card-links a {
  font-size: 0.85rem;
  font-weight: 600;
  text-decoration: none;
}

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

/* Arrow links: the arrow nudges right on hover. */
.arrow {
  display: inline-block;
  margin-left: 0.4em;
  transition: transform 0.25s var(--ease-out-quint);
}

@media (hover: hover) and (pointer: fine) {
  .card-links a:hover .arrow,
  .arrow-link:hover .arrow {
    transform: translateX(4px);
  }
}

.card-ghost {
  background: transparent;
  border-style: dashed;
}

.card-ghost .tag {
  background: transparent;
  border: 1px solid var(--sky);
}

/* ============ Process steps (timeline) ============ */
/* A connecting line threads through four nodes — horizontal on desktop,
   vertical on mobile. The line and node markers use the brand palette
   (--sky line, --green-mid nodes). The node row sits at a fixed offset
   from the top of each step so the line passes cleanly through every dot. */
:root {
  --node: 16px;          /* node diameter */
  --node-row: 26px;      /* distance from a step's top to its node centre */
}

.steps {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  list-style: none;
  margin: 48px 0 0;
  padding: 0;
}

.steps li {
  position: relative;
  /* Clear the node + number that sit on the line. */
  padding-top: calc(var(--node-row) + 26px);
}

/* The node marker for each step, centred on the line. */
.steps li::before {
  content: "";
  position: absolute;
  top: var(--node-row);
  left: 0;
  width: var(--node);
  height: var(--node);
  margin-top: calc(var(--node) / -2);
  border-radius: 999px;
  background: var(--green-mid);
  /* A soft ring lifts the node off the line without a hard glow. */
  box-shadow: 0 0 0 4px var(--bg), 0 0 0 6px var(--sky-light);
  transition:
    background-color 0.3s ease,
    box-shadow 0.3s var(--ease-out-quint);
}

/* The connecting line, drawn as a thin bar behind the nodes. */
.timeline-line {
  position: absolute;
  top: var(--node-row);
  left: 0;
  right: 0;
  height: 2px;
  margin-top: -1px;
  background: var(--sky);
  /* Sits behind the nodes; nodes paint over its ends. */
  z-index: 0;
}

.steps li,
.step-num,
.steps h3,
.steps p {
  position: relative;
  z-index: 1;
}

.step-num {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 600;
  color: var(--green-soft);
  display: block;
  margin-bottom: 8px;
  transition: color 0.25s ease;
}

/* Hovering a step wakes its stretch of the timeline: the node deepens and
   its ring swells, the numeral darkens to match. Color/ring only — no
   movement, in keeping with the calm editorial mood. */
@media (hover: hover) and (pointer: fine) {
  .steps li:hover::before {
    background: var(--green-deep);
    box-shadow: 0 0 0 4px var(--bg), 0 0 0 8px var(--sky);
  }

  .steps li:hover .step-num {
    color: var(--green-deep);
  }
}

.steps p {
  font-size: 0.92rem;
  color: var(--muted);
  margin-bottom: 0;
}

/* ---- Fluid draw (JS enhancement) ----
   The line grows along its length as the section enters view, then the
   steps + their nodes cascade in behind the advancing edge. The line is
   the lead element (--i 0); the four steps trail at --i 1..4 via the
   existing stagger wiring in main.js. Compositor-only: scaleX / opacity. */
/* Scoped under .steps so these win the cascade over the later, equal-specificity
   `.js .reveal` base rule (the line carries .reveal for the IntersectionObserver). */
.js .steps .timeline-line {
  opacity: 0;
  transform: scaleX(0);
  transform-origin: left center;
  /* The reveal base also sets blur/translate; override to a clean scale. */
  filter: none;
  transition:
    transform 1.1s var(--ease-out-expo),
    opacity 0.5s var(--ease-out-expo);
  transition-delay: calc(var(--i) * 70ms);
}

.js .steps .timeline-line.in {
  opacity: 1;
  transform: scaleX(1);
}

/* Nodes pop on after the line edge reaches them. Scale from a visible
   0.4 (never 0), settling with the same calm curve as the line. */
/* Per-property delays: the entrance stagger applies to transform/opacity
   only, while the hover channels (background, ring) stay at 0s so hover
   feedback is always immediate. */
.js .steps li::before {
  transform: scale(0.4);
  opacity: 0;
  transition:
    transform 0.55s var(--ease-out-expo) calc(var(--i) * 70ms + 220ms),
    opacity 0.55s var(--ease-out-expo) calc(var(--i) * 70ms + 220ms),
    background-color 0.3s ease 0s,
    box-shadow 0.3s var(--ease-out-quint) 0s;
}

.js .steps li.in::before {
  transform: scale(1);
  opacity: 1;
}

/* ============ About ============ */
.about-wrap {
  display: grid;
  grid-template-columns: 1fr 1.4fr;
  gap: 48px;
  align-items: start;
}

.about-copy p {
  font-size: 1.02rem;
}

/* ============ Contact ============ */
.contact-wrap {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: 48px;
  align-items: start;
}

.contact-intro p {
  color: var(--muted);
  max-width: 38ch;
}

.alt-contact {
  font-size: 0.92rem;
}

.copy-btn {
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--green-deep);
  background: transparent;
  border: 1px solid var(--sky);
  border-radius: 999px;
  padding: 3px 12px;
  margin-left: 8px;
  cursor: pointer;
  transition: background 0.2s ease;
}

.copy-btn:hover {
  background: var(--sky-light);
}

.copy-btn.copied {
  background: var(--green-deep);
  border-color: var(--green-deep);
  color: #fff;
}

.contact-form {
  display: grid;
  gap: 18px;
}

.field {
  display: grid;
  gap: 6px;
}

.field label {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--green-dark);
}

.field input,
.field select,
.field textarea {
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--ink);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 12px 14px;
  width: 100%;
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: 2px solid var(--green-soft);
  outline-offset: 1px;
  border-color: var(--green-soft);
}

.field textarea {
  resize: vertical;
}

.contact-form .btn {
  justify-self: start;
}

.hidden-field {
  display: none;
}

.form-status {
  font-size: 0.9rem;
  margin: 0;
  min-height: 1.2em;
}

.form-status.ok {
  color: var(--green-deep);
}

.form-status.err {
  color: #a04040;
}

/* ============ Service pages ============ */
.service-page .site-header,
.service-page.js .site-header {
  background: rgba(255, 255, 255, 0.96);
  backdrop-filter: blur(8px);
  border-bottom-color: var(--line);
}

.service-hero {
  padding-block: 112px 88px;
  background:
    radial-gradient(circle at 82% 24%, rgba(191, 230, 224, 0.75), transparent 26%),
    var(--bg-tint);
}

.service-hero-grid {
  display: grid;
  grid-template-columns: 1.35fr 0.65fr;
  gap: 64px;
  align-items: end;
}

.service-hero h1 {
  max-width: 14ch;
}

.service-hero .lede {
  max-width: 60ch;
  color: var(--muted);
  font-size: 1.12rem;
  margin-bottom: 2em;
}

.service-summary {
  border-left: 2px solid var(--sky);
  padding-left: 24px;
}

.service-summary h2 {
  font-family: var(--font-body);
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  margin-bottom: 18px;
}

.service-summary ul,
.check-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.service-summary li,
.check-list li {
  position: relative;
  padding-left: 22px;
  margin-bottom: 10px;
}

.service-summary li::before,
.check-list li::before {
  content: "";
  position: absolute;
  top: 0.72em;
  left: 0;
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--green-soft);
}

.service-split {
  display: grid;
  grid-template-columns: 0.8fr 1.2fr;
  gap: 64px;
  align-items: start;
}

.service-split .section-copy {
  max-width: 62ch;
}

.service-split .section-copy > p {
  font-size: 1.02rem;
}

.service-split .check-list {
  margin-top: 28px;
  columns: 2;
  column-gap: 32px;
}

.service-split .check-list li {
  break-inside: avoid;
  margin-bottom: 14px;
}

.service-card-link {
  display: inline-block;
  margin-top: 18px;
  font-size: 0.84rem;
  font-weight: 600;
  text-decoration: none;
}

.service-cta {
  padding-block: 88px;
  text-align: center;
  background: var(--green-dark);
  color: #fff;
}

.service-cta h2,
.service-cta .kicker {
  color: #fff;
}

.service-cta p {
  max-width: 58ch;
  margin: 0 auto 28px;
  color: var(--sky-light);
}

.service-cta .btn {
  color: var(--green-dark);
  background: #fff;
}

/* ============ Footer ============ */
.site-footer {
  border-top: 1px solid var(--line);
  padding-block: 48px 28px;
  background: var(--bg-tint);
}

.footer-cols {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  gap: 32px;
  padding-bottom: 36px;
  margin-bottom: 24px;
  border-bottom: 1px solid var(--line);
}

.footer-brand p {
  font-size: 0.88rem;
  color: var(--muted);
  max-width: 36ch;
  margin: 0;
}

.footer-brand .wordmark {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--green-deep);
  margin-bottom: 10px;
}

.footer-col {
  display: grid;
  align-content: start;
  gap: 8px;
}

.footer-col h4 {
  font-family: var(--font-body);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green-dark);
  margin: 0 0 6px;
}

.footer-col a {
  font-size: 0.88rem;
  color: var(--muted);
  text-decoration: none;
}

.footer-col a:hover {
  color: var(--green-deep);
}

.footer-row {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}

.footer-row p {
  margin: 0;
  font-size: 0.88rem;
  color: var(--muted);
}

/* ============ Scroll reveal (JS enhancement) ============ */
/* A softer, more fluid entrance: more travel, a whisper of scale, and a
   brief blur that sharpens as it settles. --i is set per-child in JS so
   grid/step children cascade; it defaults to 0 for standalone reveals. */
.js .reveal {
  --i: 0;
  opacity: 0;
  transform: translateY(22px) scale(0.985);
  filter: blur(6px);
  transition:
    opacity 0.85s var(--ease-out-quint),
    transform 0.85s var(--ease-out-quint),
    filter 0.85s var(--ease-out-quint);
  transition-delay: calc(var(--i) * 70ms);
}

.js .reveal.in {
  opacity: 1;
  transform: none;
  filter: blur(0);
}

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

  /* Reveals, hero load-in, and the illustration entrance all settle
     instantly with no movement or blur. */
  .js .reveal,
  .js .hero .hero-load,
  .js .hero .hero-art,
  .js .hero .scroll-cue,
  .js .hero .hl::after {
    opacity: 1;
    transform: none;
    filter: none;
    transition: none;
    transition-delay: 0s;
  }

  /* Timeline: the line shows full, nodes show in place, no draw or pop. */
  .js .steps .timeline-line,
  .js .steps .timeline-line.in {
    opacity: 1;
    transform: scaleX(1);
    transition: none;
    transition-delay: 0s;
  }

  .js .steps li::before,
  .js .steps li.in::before {
    transform: scale(1);
    opacity: 1;
    transition: none;
    transition-delay: 0s;
  }

  /* Kill all ambient/looping motion. */
  .scroll-cue .scroll-dot {
    animation: none;
  }

  /* No hover lift / arrow nudge / press travel. */
  .card,
  .btn,
  .arrow,
  .site-nav a:not(.btn)::after {
    transition: none;
  }
}

/* ============ Responsive ============ */
@media (max-width: 900px) {
  .grid-4 {
    grid-template-columns: repeat(2, 1fr);
  }

  .grid-3 {
    grid-template-columns: 1fr;
  }

  /* Timeline goes vertical: line down the left gutter, nodes stacked on it,
     content indented to the right. One continuous line, not 2x2 fragments. */
  .steps {
    grid-template-columns: 1fr;
    gap: 28px;
    --node-row: 12px;       /* node centre measured from each step's top */
    --rail: 9px;            /* line x-position from the step's left edge */
  }

  .steps li {
    padding-top: 0;
    padding-left: 40px;
  }

  .steps li::before {
    top: var(--node-row);
    left: var(--rail);
    margin-top: 0;
    margin-left: calc(var(--node) / -2);
  }

  .timeline-line {
    top: var(--node-row);
    bottom: var(--node-row);
    left: var(--rail);
    right: auto;
    width: 2px;
    height: auto;
    margin-top: 0;
    margin-left: -1px;
  }

  /* Vertical draw: grow downward from the first node. */
  .js .steps .timeline-line {
    transform: scaleY(0);
    transform-origin: top center;
  }

  .js .steps .timeline-line.in {
    transform: scaleY(1);
  }

  .about-wrap,
  .contact-wrap,
  .service-hero-grid,
  .service-split {
    grid-template-columns: 1fr;
    gap: 24px;
  }

  .service-hero {
    padding-block: 80px 64px;
  }

  .footer-cols {
    grid-template-columns: repeat(2, 1fr);
  }

  .footer-brand {
    grid-column: 1 / -1;
  }

  /* Keep the mobile hero as one composed panel: copy sits above the
     illustration instead of pushing it into a separate row. */
  .hero {
    min-height: 100svh;
    align-items: center;
  }

  .hero-grid {
    grid-template-columns: 1fr;
    padding-block: 0;
  }

  .hero-copy {
    position: relative;
    z-index: 1;
    width: 100%;
    text-align: center;
    max-width: 430px;
    margin-inline: auto;
    padding: 28px 20px 30px;
    background: rgba(255, 255, 255, 0.88);
    border: 1px solid rgba(227, 236, 232, 0.9);
    border-radius: 24px;
    box-shadow: 0 20px 50px -30px rgba(15, 61, 51, 0.35);
    backdrop-filter: blur(10px);
  }

  .hero-copy h1 {
    font-weight: 700;
    text-shadow: 0 1px 0 #fff;
  }

  .hero-copy .lede {
    color: var(--ink);
    font-weight: 500;
    margin-inline: auto;
  }

  .hero-art {
    position: absolute;
    inset: 0;
    width: 100%;
  }

  .hero-art img {
    width: 100%;
    height: 100%;
    margin-top: 0;
    opacity: 0.34;
    object-fit: cover;
    object-position: center;
  }

  .scroll-cue {
    display: none;
  }
}

@media (max-width: 640px) {
  .hero-copy {
    padding-inline: 16px;
  }

  .hero-copy h1 {
    font-size: clamp(2.25rem, 11vw, 2.6rem);
  }

  .hero-copy .lede {
    font-size: 0.96rem;
  }

  .section {
    padding-block: 64px;
  }

  .grid-4 {
    grid-template-columns: 1fr;
  }

  .service-split .check-list {
    columns: 1;
  }

  .nav-toggle {
    display: flex;
  }

  /* Mobile nav is always in the DOM and absolutely positioned, so the
     open/close transition never reflows the page. It eases down from the
     header instead of snapping on. */
  .site-nav {
    display: flex;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 18px;
    background: #fff;
    border-bottom: 1px solid var(--line);
    padding: 20px 24px 24px;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition:
      opacity 0.26s var(--ease-out-quint),
      transform 0.26s var(--ease-out-quint),
      visibility 0s linear 0.26s;
  }

  .site-nav.open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    transition:
      opacity 0.26s var(--ease-out-quint),
      transform 0.26s var(--ease-out-quint),
      visibility 0s;
  }

  /* The hamburger morphs to an X when open. */
  .nav-toggle span {
    transition:
      transform 0.26s var(--ease-out-quint),
      opacity 0.2s ease;
    transform-origin: center;
  }

  .nav-toggle[aria-expanded="true"] span:nth-child(1) {
    transform: translateY(7px) rotate(45deg);
  }

  .nav-toggle[aria-expanded="true"] span:nth-child(2) {
    opacity: 0;
  }

  .nav-toggle[aria-expanded="true"] span:nth-child(3) {
    transform: translateY(-7px) rotate(-45deg);
  }
}
