/* ==========================================================================
   Neucreation — home page
   Colours and geometry are eyedropped from home.png at a 1440px design width.
   ========================================================================== */

/* Self-hosted fonts (Latin subset, from Google Fonts). Serving them from the
   site avoids two extra connections and a render-blocking stylesheet. The
   pages preload the ones visible first. */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 300 500; /* one variable file covers every weight used */
  font-display: swap;
  src: url("src/fonts/inter-latin-var.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Inria Serif";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("src/fonts/inria-serif-latin-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Inria Serif";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("src/fonts/inria-serif-latin-400-italic.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Cormorant Garamond";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("src/fonts/cormorant-garamond-latin-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --color-cream: #fffcf1;
  --color-teal: #106b60;
  --color-teal-deep: #0c534b;
  --color-ink: #1e1e1a;
  --color-muted: rgba(30, 30, 26, 0.68); /* 5.7:1 on cream — readable small grey text */
  --color-hairline: rgba(30, 30, 26, 0.28);
  --color-on-teal: rgba(255, 252, 241, 0.82);
  --color-hairline-on-teal: rgba(255, 252, 241, 0.45);

  --font-serif: "Inria Serif", serif;
  --font-display: Garamond, "Cormorant Garamond", "EB Garamond", serif;
  --font-sans: "Inter", sans-serif;

  /* Shared easing vocabulary — mirrored in GSAP (power3.out / power3.inOut).
     Nothing elastic, nothing bouncy. */
  --ease-out: cubic-bezier(0.19, 1, 0.22, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);

  /* 78px at the 1440 design width. */
  --gutter: clamp(1.25rem, 5.42vw, 78px);
}

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

html {
  scrollbar-gutter: stable;
}

/* Native smooth scroll only while Lenis is NOT driving — the two fight each
   other and the result reads as stuttering, snagging scroll — and only once
   the page has finished landing on any #fragment it was opened at. An animated
   jump on load is still in flight while ScrollTrigger measures the page, which
   leaves every heading above the landing point hidden for good (js/deep-link.js). */
html.is-scroll-ready:not(.lenis) {
  scroll-behavior: smooth;
}

/* Required by Lenis. */
html.lenis,
html.lenis body {
  height: auto;
}

.lenis.lenis-smooth {
  scroll-behavior: auto !important;
}

.lenis.lenis-smooth [data-lenis-prevent] {
  overscroll-behavior: contain;
}

.lenis.lenis-stopped {
  overflow: hidden;
}

.lenis.lenis-scrolling iframe {
  pointer-events: none;
}

body {
  background-color: var(--color-cream);
  color: var(--color-ink);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

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

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

html.is-locked,
html.is-locked body {
  overflow: hidden;
}

:focus-visible {
  outline: 2px solid var(--color-teal);
  outline-offset: 3px;
  border-radius: 2px;
}

.magicians :focus-visible,
.build :focus-visible,
.site-footer :focus-visible {
  outline-color: var(--color-cream);
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  border-radius: 999px;
  font-family: var(--font-sans);
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 0.35s var(--ease-in-out),
              color 0.35s var(--ease-in-out),
              border-color 0.35s var(--ease-in-out);
}

.btn-solid {
  height: 45px;
  padding: 0 1.5rem;
  background-color: var(--color-teal);
  color: var(--color-cream);
}

.btn-solid:hover {
  background-color: var(--color-teal-deep);
}

.btn-white {
  height: 48px;
  padding: 0 0.4rem 0 1.75rem;
  background-color: var(--color-cream);
  color: var(--color-teal);
  font-size: 0.9375rem;
  letter-spacing: 0.06em;
}

.btn-white .btn-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background-color: var(--color-teal);
  color: var(--color-cream);
  transition: transform 0.4s var(--ease-out);
}

.btn-white:hover .btn-arrow {
  transform: translateX(3px);
}

.btn-outline {
  height: 42px;
  padding: 0 2rem;
  border: 1px solid var(--color-teal);
  color: var(--color-teal);
  font-size: 0.9375rem;
}

.btn-outline:hover {
  background-color: var(--color-teal);
  color: var(--color-cream);
}

/* ==========================================================================
   Shared type
   ========================================================================== */

.eyebrow {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.13em;
  line-height: 1.4;
  text-transform: uppercase;
  color: var(--color-ink);
}

.tag {
  display: inline-flex;
  align-items: center;
  height: 27px;
  padding: 0 0.95rem;
  border: 1px solid var(--color-hairline-on-teal);
  border-radius: 999px;
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--color-cream);
}

.tag-teal {
  border-color: var(--color-teal);
  color: var(--color-teal);
}

.h-italic {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  line-height: 1.1;
  color: var(--color-cream);
}

/* ==========================================================================
   Preloader
   Same cream ground as the hero, so the panel can fade out unnoticed —
   only its own dots and caption ever visibly leave.
   ========================================================================== */

.preloader {
  position: fixed;
  inset: 0;
  z-index: 9000;
  background-color: var(--color-cream);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
  opacity: 1;
  transition: opacity 0.7s var(--ease-in-out);
}

.preloader.is-gone {
  opacity: 0;
  pointer-events: none;
}

.preloader-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.pre-mark-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  /* Matches .pre-word-wrap: both halves of the lockup leave on the same curve
     and over the same time, so they read as one thing folding together. */
  transition: transform 0.95s var(--ease-in-out);
  will-change: transform;
}

.pre-mark-drift {
  /* Sized to the logo icon's own box (33.62 x 33.4 in the header artwork), so
     the mark and the tile overlay exactly and the whole wrapper can be flown
     straight onto the icon in the header logo. */
  position: relative;
  width: clamp(92px, 11.5vw, 138px);
  aspect-ratio: 33.62 / 33.4;
  /* Hovering, not pinned. A slow rise and fall on its own rhythm, kept on its
     own element so it never fights the wing beat's transform. */
  animation: neu-mark-drift 4.3s var(--ease-in-out) 1.2s infinite;
}

.pre-mark,
.pre-mark-tile {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.pre-mark {
  /* The beat is a fold in depth, not a flat squash: rotating about the body's
     axis under perspective foreshortens the near wing exactly the way a real
     one does. The origin is the butterfly's own centre within the icon box. */
  transform-origin: 50% 53%;
  animation: neu-mark-flap 1.4s var(--ease-in-out) 1.45s infinite;
}

/* The icon exactly as the header logo draws it: the butterfly knocked out of a
   solid tile. Hidden while the butterfly is the thing being watched, it takes
   over as the mark leaves, so what lands in the header is already the logo. */
.pre-mark-tile {
  fill: var(--color-teal);
  opacity: 0;
}

/* Two copies of the same path: the outline draws itself, then the solid one
   inks in underneath it and the outline fades out. */
.pre-mark-fill {
  fill: var(--color-teal);
  opacity: 0;
  animation: neu-mark-ink 0.48s var(--ease-in-out) 0.52s forwards;
}

.pre-mark-line {
  fill: none;
  stroke: var(--color-teal);
  stroke-width: 0.34;
  stroke-linecap: round;
  stroke-linejoin: round;
  /* pathLength="1" on the element, so the dash maths is independent of the
     path's real length. */
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: neu-mark-draw 0.7s var(--ease-out) forwards,
             neu-mark-undraw 0.42s var(--ease-in-out) 0.64s forwards;
}

@keyframes neu-mark-draw {
  to { stroke-dashoffset: 0; }
}

@keyframes neu-mark-ink {
  to { opacity: 1; }
}

@keyframes neu-mark-undraw {
  to { stroke-opacity: 0; }
}

/* Asymmetric on purpose: the downstroke is quick and the recovery is slower,
   which is what stops a repeating beat reading as a metronome. */
@keyframes neu-mark-flap {
  0%       { transform: perspective(260px) rotateY(0deg); }
  34%      { transform: perspective(260px) rotateY(64deg); }
  100%     { transform: perspective(260px) rotateY(0deg); }
}

@keyframes neu-mark-drift {
  0%,
  100%     { transform: translateY(0.34rem); }
  50%      { transform: translateY(-0.34rem); }
}

/* The studio name is written, not uncovered. Eleven reveal rects inside one
   mask open the letters in turn: each takes as long as a nib would need to
   cross it, and between them the pen lifts for a beat. That rhythm — discrete
   letters, uneven gaps — is the whole difference between writing and a wipe,
   which is what this was before.

   A nib rides the leading edge, dipping through each letter and lifting over
   each gap, so the hard edge of the wipe is never what you look at. The i's
   tittle is held out of the line and tapped in once the word is finished: the
   order a hand writes in, and the beat that says the word is done.

   The geometry is the artwork's own. Each rect is the box of the letter it
   opens, measured off the lettering path, and every duration below is that
   letter's width at one constant pen speed (5.65ms per unit of the 212-wide
   logo). To retime the line, scale the delays and durations together — pulling
   one letter on its own is what makes a hand look mechanical.

   Still no letter-by-letter *rise*: that is what the LIMITLESS handoff does a
   moment later, and doing it twice reads as a stutter. */
.pre-word-wrap {
  position: relative;
  width: clamp(138px, 19vw, 210px);
  margin-top: clamp(1.1rem, 2.2vw, 1.75rem);
  /* Set by js/preloader.js at handoff: the name travels to the header logo's
     lettering, which is this same artwork. It must land before the panel
     begins to fade at t.reveal — the fade is what dissolves one into the
     other, and because they are identical and co-located, nothing is seen to
     happen at all. Eased in and out: something crossing the screen should
     gather speed and shed it, not leave at full tilt. */
  transform-origin: 50% 50%;
  transition: transform 0.95s var(--ease-in-out);
  will-change: transform;
}

.pre-word {
  display: block;
  width: 100%;
  height: auto;
  fill: var(--color-teal);
}

/* Each rect is drawn open from its own left edge, so its right edge traces
   exactly the nib's path across that letter. Opening from zero width rather
   than sliding a full-size rect in from the left is what keeps a letter from
   ever reaching over its neighbour: a mask only adds, so a rect parked on the
   letter before it would write that letter early with no way to undo it.

   fill-box puts the origin on the rect's own left edge — without it the
   origin is the SVG viewport and every letter would open from x=0.

   Linear, because a pen crossing a letter does not accelerate: the rhythm
   lives in the gaps between letters, not inside the stroke. */
.pw-ink {
  fill: #fff;
  transform-box: fill-box;
  transform-origin: left center;
  transform: scaleX(0);
  animation-name: neu-word-write;
  animation-timing-function: linear;
  animation-fill-mode: forwards;
}

@keyframes neu-word-write {
  to { transform: scaleX(1); }
}

/* Letter boxes and pen speed, generated from the lettering path. */
.pw-1 { animation-duration: 97ms; animation-delay: 600ms; } /* N */
.pw-2 { animation-duration: 80ms; animation-delay: 729ms; } /* e */
.pw-3 { animation-duration: 75ms; animation-delay: 838ms; } /* u */
.pw-4 { animation-duration: 79ms; animation-delay: 944ms; } /* c */
.pw-5 { animation-duration: 46ms; animation-delay: 1053ms; } /* r */
.pw-6 { animation-duration: 80ms; animation-delay: 1123ms; } /* e */
.pw-7 { animation-duration: 78ms; animation-delay: 1230ms; } /* a */
.pw-8 { animation-duration: 53ms; animation-delay: 1334ms; } /* t */
.pw-9 { animation-duration: 11ms; animation-delay: 1417ms; } /* i */
.pw-10 { animation-duration: 87ms; animation-delay: 1458ms; } /* o */
.pw-11 { animation-duration: 75ms; animation-delay: 1575ms; } /* n */

/* The nib. Teal on teal, so where it crosses finished letters it disappears
   into them and only the half over bare cream reads — which is what the wet
   end of a stroke looks like. ease-in-out per segment, so it settles into each
   turn instead of cornering. */
.pre-word-nib {
  animation: neu-word-nib 1050ms ease-in-out 600ms both;
}

.pre-word-nib-dot {
  fill: var(--color-teal);
  opacity: 0;
  animation: neu-word-nib-fade 1170ms var(--ease-out) 600ms forwards;
}

@keyframes neu-word-nib-fade {
  0%   { opacity: 0; transform: scale(0.4); }
  5%   { opacity: 1; transform: scale(1); }
  88%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(0.4); }
}

/* Held back until the line is written, then dropped in. 1700ms is 50ms after
   the last letter closes; it lands at 1850ms, inside the preloader's own floor
   (TIMELINE.minDuration in js/preloader.js) with room to be seen. */
.pre-word-tittle {
  opacity: 0;
  transform: translateY(-2.4px);
  animation: neu-word-tittle 150ms var(--ease-out) 1700ms forwards;
}

@keyframes neu-word-tittle {
  to { opacity: 1; transform: translateY(0); }
}

/* The nib's path: down through each letter, lifted over each gap. Positions
   are user units in the lettering's own coordinate system. */
@keyframes neu-word-nib {
  0% { transform: translate(45.44px, 32.2px); }
  4.63% { transform: translate(54.04px, 19.2px); }
  9.25% { transform: translate(62.64px, 32.2px); }
  10.77% { transform: translate(64.55px, 15.4px); }
  12.29% { transform: translate(66.47px, 32.2px); }
  16.1% { transform: translate(73.55px, 19.2px); }
  19.9% { transform: translate(80.63px, 32.2px); }
  21.3% { transform: translate(82.14px, 15.4px); }
  22.7% { transform: translate(83.66px, 32.2px); }
  26.28% { transform: translate(90.3px, 19.2px); }
  29.85% { transform: translate(96.94px, 32.2px); }
  31.29% { transform: translate(98.6px, 15.4px); }
  32.73% { transform: translate(100.26px, 32.2px); }
  36.49% { transform: translate(107.25px, 19.2px); }
  40.25% { transform: translate(114.24px, 32.2px); }
  41.7% { transform: translate(115.9px, 15.4px); }
  43.14% { transform: translate(117.56px, 32.2px); }
  45.35% { transform: translate(121.67px, 19.2px); }
  47.56% { transform: translate(125.78px, 32.2px); }
  48.68% { transform: translate(126.36px, 15.4px); }
  49.81% { transform: translate(126.94px, 32.2px); }
  53.61% { transform: translate(134.02px, 19.2px); }
  57.42% { transform: translate(141.1px, 32.2px); }
  58.7% { transform: translate(142.21px, 15.4px); }
  59.98% { transform: translate(143.31px, 32.2px); }
  63.71% { transform: translate(150.24px, 19.2px); }
  67.43% { transform: translate(157.16px, 32.2px); }
  68.69% { transform: translate(158.19px, 15.4px); }
  69.94% { transform: translate(159.21px, 32.2px); }
  72.47% { transform: translate(163.92px, 19.2px); }
  75% { transform: translate(168.62px, 32.2px); }
  76.39% { transform: translate(170.09px, 15.4px); }
  77.77% { transform: translate(171.55px, 32.2px); }
  78.28% { transform: translate(172.5px, 19.2px); }
  78.79% { transform: translate(173.45px, 32.2px); }
  80.27% { transform: translate(175.22px, 15.4px); }
  81.74% { transform: translate(176.98px, 32.2px); }
  85.87% { transform: translate(184.65px, 19.2px); }
  89.99% { transform: translate(192.31px, 32.2px); }
  91.43% { transform: translate(193.95px, 15.4px); }
  92.86% { transform: translate(195.59px, 32.2px); }
  96.43% { transform: translate(202.23px, 19.2px); }
  100% { transform: translate(208.86px, 32.2px); }
}

.pre-caption {
  margin-top: clamp(2rem, 4vw, 3rem);
  max-width: 24rem;
  text-align: center;
  font-size: 0.875rem;
  line-height: 1.65;
  color: var(--color-muted);
}

.preloader.is-exiting .pre-caption {
  opacity: 0;
  transform: translateY(0.75rem);
  transition: opacity 0.5s var(--ease-in-out), transform 0.65s var(--ease-out);
}

/* The mark leaves for the header logo, where this icon already sits in front
   of the name. js/preloader.js sets the destination; the transform here is the
   fallback for when the logo cannot be measured. The butterfly hands over to
   the tile on the way, so what arrives is the logo icon itself and the panel's
   fade has nothing left to dissolve. */
.preloader.is-exiting .pre-mark-wrap {
  transform: translate(0.85rem, -2.4rem) scale(0.4);
}

.preloader.is-exiting .pre-mark {
  opacity: 0;
  transition: opacity 0.42s var(--ease-in-out) 0.1s;
}

.preloader.is-exiting .pre-mark-tile {
  opacity: 1;
  transition: opacity 0.42s var(--ease-in-out) 0.1s;
}

.preloader.is-exiting .pre-caption {
  transition-delay: 0.05s;
}

/* ==========================================================================
   Header
   ========================================================================== */

.site-header {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 100;
  padding: 39px 72px 0 48px;
  transition: opacity 0.9s var(--ease-in-out) 0.18s,
              transform 1.1s var(--ease-out) 0.18s;
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
}

.logo img {
  width: 212px;
  height: 47px;
}

.nav-cluster {
  display: flex;
  align-items: center;
  gap: 2.35rem;
  height: 53px;
  padding: 0 4px 0 2.2rem;
  background-color: #ffffff;
  border-radius: 999px;
}

.main-nav ul {
  display: flex;
  align-items: center;
  gap: 2.4rem;
  list-style: none;
}

.main-nav a {
  font-size: 0.9375rem;
  font-weight: 400;
  color: var(--color-ink);
  text-decoration: none;
  transition: color 0.3s ease;
}

.main-nav a:hover {
  color: var(--color-teal);
}

/* ==========================================================================
   Hero
   ========================================================================== */

.hero {
  position: relative;
  padding-top: 268px;
  padding-bottom: 132px;
}

.hero-type {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.wordmark-wrap {
  position: relative;
  display: inline-block;
}

.wordmark {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(3.75rem, 17.43vw, 251px);
  line-height: 0.72;
  letter-spacing: 0;
  color: var(--color-teal);
  text-transform: uppercase;
  white-space: nowrap;
}

/* Per-letter masks, built by main.js. Without JS the wordmark is plain text. */
.wordmark .letter {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
}

.wordmark .letter-inner {
  display: inline-block;
  transform: translateY(0);
  transition: transform 1.15s var(--ease-out);
  transition-delay: calc(var(--i) * 0.055s);
  will-change: transform;
}

/* Only the <h1> blurs. Animating a filter is by far the most expensive thing
   in the entrance — the glyph has to be re-rendered and re-blurred every frame
   at up to 251px — and it lands at the handoff, when the panel is also flying
   two elements and about to fade. The reflection sits at opacity 0 through the
   handoff and 0.3 after it, so its blur was paid for and never seen. */
.wordmark:not(.reflection) .letter-inner {
  filter: blur(0);
  transition: transform 1.15s var(--ease-out), filter 0.55s var(--ease-out);
  will-change: transform, filter;
}

.wordmark.reflection {
  position: absolute;
  /* scaleY(-1) mirrors about the element's centre, so the copy lands directly
     below; the nudge lines its mirrored baseline up with the real one. */
  top: calc(100% - 0.101em);
  left: 0;
  width: 100%;
  transform: scaleY(-1);
  opacity: 0.18;
  filter: blur(2px);
  pointer-events: none;
  /* Local bottom becomes the visual top once flipped, so the gradient runs
     the opposite way to how it reads on screen. */
  mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 100%);
  -webkit-mask-image: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 1) 100%);
  transition: opacity 1s var(--ease-in-out) 0.5s;
}

.butterfly {
  position: absolute;
  top: -103px;
  left: 86.5%;
  width: 96px;
  height: 89px;
  aspect-ratio: 96 / 89; /* keeps a size where the height is set to auto */
  transition: opacity 0.9s var(--ease-in-out) 0.42s,
              transform 1.2s var(--ease-out) 0.42s;
}

/* The 3D butterfly (js/butterfly3d.js) flies on a canvas over the whole hero.
   The empty .butterfly span above only marks its perch. */
.butterfly-stage {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s var(--ease-in-out);
}

.has-butterfly-3d .butterfly-stage {
  opacity: 1;
}

.scroll-cue {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  margin-top: 190px;
  color: var(--color-teal);
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0.11em;
  text-decoration: none;
}

.hero-sub {
  margin-top: 0.25rem;
  max-width: 350px;
  text-align: center;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--color-muted);
}

.hero-figure {
  position: relative;
  margin: 140px var(--gutter) 0;
}

/* .hero-video only: the cursor glow (js/image-glow.js) adds its own canvas to
   this figure, and must not get a second border. */
.hero-figure .hero-video {
  display: block;
  border: 4px solid rgb(0, 128, 98);
  width: 100%;
  height: auto;
  aspect-ratio: 1285 / 581;
  object-fit: cover;
  border-radius: 10px;
}

.hero-video-text{
  margin-top: 0.75rem;
 font-family: var(--font-serif);
  color: rgb(0, 128, 98);
  font-size: 1.2rem;
  font-weight: 500;
  text-align: center;
}
/* Cursor light over photos (js/image-glow.js). Sized and placed over its
   photo from JS; above stacked service images (z-index 1–2), and never in
   the way of the pointer. */
.img-glow {
  position: absolute;
  z-index: 3;
  pointer-events: none;
}

/* ==========================================================================
   Marquee
   ========================================================================== */

.marquee {
  height: 91px;
  display: flex;
  align-items: center;
  overflow: hidden;
  background-color: var(--color-teal);
}

.marquee-track {
  display: flex;
  width: max-content;
  /* Scale the duration with the length of one run, or a longer phrase
     scrolls faster. */
  animation: neu-marquee 100s linear infinite;
}

.marquee-run {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: 40px;
  line-height: 1;
  letter-spacing: 0.02em;
  color: var(--color-cream);
  white-space: nowrap;
  padding-right: 0;
}

.marquee-run i {
  font-style: normal;
  font-size: 0.78em;
  vertical-align: 0.08em;
  padding: 0 0.15em;
}

@keyframes neu-marquee {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

/* ==========================================================================
   Manifesto
   ========================================================================== */

.manifesto {
  position: relative;
  isolation: isolate; /* keeps the scroll bands (js/animations.js) behind the content */
  height: 1078px;
}

/* The frame is what is placed and moved; it clips the photo, which is free
   to zoom inside it. */
.float-img {
  position: absolute;
  overflow: hidden;
  border-radius: 14px;
}

.float-img img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.float-1 { left: 166px;  top: 61px;  width: 157px; height: 212px; }
.float-2 { left: 863px;  top: 57px;  width: 156px; height: 200px; }
.float-3 { left: 268px;  top: 724px; width: 156px; height: 200px; }
.float-4 { left: 734px;  top: 726px; width: 158px; height: 198px; }
.float-5 { left: 1224px; top: 634px; width: 156px; height: 199px; }

.manifesto-copy {
  position: absolute;
  top: 322px;
  left: 50%;
  transform: translateX(-50%);
  width: min(1140px, calc(100% - 2 * var(--gutter)));
  text-align: center;
}

.pull-quote {
  margin-top: 1.5rem;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
   font-size: clamp(1.6rem, 2.78vw, 40px);
  line-height: 1.36;
  color: var(--color-teal);
}

/* Manifesto scroll scene, built by js/animations.js only when motion is
   allowed: colour bands sweep in behind the section and the copy reads itself
   in out of a blur. Without it the section is unchanged. */
.manifesto-bands {
  position: absolute;
  inset: 0;
  z-index: -1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  pointer-events: none;
}

.manifesto-band {
  flex: 1 1 0;
  margin-bottom: -1px; /* no hairline seams between bands */
  transform: scaleX(0);
  will-change: transform;
}

/* Words of the scroll reveal: a box of their own so blur applies in every browser. */
.reveal-word {
  display: inline-block;
}

/* ==========================================================================
   Magicians of the Pixel
   ========================================================================== */

.magicians {
  display: grid;
  grid-template-columns: 604px 1fr;
  column-gap: 84px;
  align-items: start;
  padding: 135px 20px 125px 91px;
  background-color: var(--color-teal);
}

.magicians-figure img {
  width: 604px;
  height: 624px;
  object-fit: cover;
}

.magicians-copy {
  padding-top: 103px;
  max-width: 640px;
}

.magicians-copy .h-italic {
  margin-top: 1.35rem;
  font-size: clamp(2rem, 4.05vw, 58px);
}

.body-on-teal {
  margin-top: 1.6rem;
  max-width: 533px;
  font-size: 0.875rem;
  line-height: 1.72;
  letter-spacing: 0.005em;
  color: var(--color-on-teal);
}

.magicians-copy .btn-white {
  margin-top: 2.5rem;
}

/* ==========================================================================
   Services
   ========================================================================== */

.services {
  padding: 182px 0 208px;
}

.services-head {
  display: flex;
  align-items: flex-start;
  gap: 79px;
  padding: 0 var(--gutter) 0 104px;
}

.services-head .tag {
  margin-top: 18px;
  flex: none;
}

.services-title {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(2rem, 4.6vw, 66px);
  line-height: 1.18;
  color: var(--color-teal);
}

.services-title em {
  font-style: italic;
}

.services-body {
  display: grid;
  grid-template-columns: 706px 1fr;
  column-gap: 66px;
  align-items: start;
  margin-top: 97px;
}

/* The dashed rules deliberately bleed off the left edge of the viewport. */
.accordion {
  list-style: none;
  border-top: 1px dashed var(--color-hairline);
}

.acc-item {
  position: relative;
  border-bottom: 1px dashed var(--color-hairline);
}

/* A solid teal rule draws across the open row's dashed line, and retracts
   towards the right when the row closes. */
.acc-item::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 1px;
  background-color: var(--color-teal);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.7s var(--ease-in-out);
}

.acc-item.is-open::after {
  transform: scaleX(1);
  transform-origin: left;
  transition-duration: 1s;
}

.acc-head {
  display: grid;
  grid-template-columns: 31px 1fr 35px;
  align-items: center;
  gap: 0;
  width: 100%;
  padding: 26px 38px 26px 73px;
  background: none;
  border: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

.acc-num {
  align-self: center;
  font-size: 0.75rem;
  font-weight: 400;
  color: var(--color-teal);
}

.acc-title {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.5rem, 2.4vw, 34px);
  line-height: 1.24;
  color: var(--color-teal);
  transition: transform 0.6s var(--ease-out);
}

.acc-item.is-open .acc-title {
  transform: translateX(10px);
}

.acc-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 35px;
  height: 35px;
  border: 1px solid var(--color-teal);
  border-radius: 50%;
  color: var(--color-teal);
  transform: rotate(45deg);
  transition: transform 0.6s var(--ease-out),
              background-color 0.35s var(--ease-in-out),
              color 0.35s var(--ease-in-out);
}

.acc-item.is-open .acc-icon {
  transform: rotate(0deg);
}

@media (hover: hover) {
  .acc-head:hover .acc-title {
    transform: translateX(10px);
  }

  .acc-head:hover .acc-icon {
    background-color: var(--color-teal);
    color: var(--color-cream);
  }
}

.acc-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.65s var(--ease-in-out);
}

.acc-item.is-open .acc-panel {
  grid-template-rows: 1fr;
}

/* Only horizontal padding here: vertical padding cannot shrink to zero, so
   the space under an open row comes from the button's bottom margin instead,
   and the row closes in one smooth movement. */
.acc-body {
  overflow: hidden;
  min-height: 0;
  padding: 0 30px 0 115px;
}

/* The description and its button fade up one after the other as the row
   opens, and drop away quickly, together, as it closes. */
.acc-body > * {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.25s var(--ease-in-out),
              transform 0.25s var(--ease-in-out);
}

.acc-item.is-open .acc-body > * {
  opacity: 1;
  transform: none;
  transition: opacity 0.6s var(--ease-out) 0.2s,
              transform 0.9s var(--ease-out) 0.2s;
}

.acc-body > p {
  margin: 0;
  font-size: 0.8125rem;
  line-height: 1.85;
  color: var(--color-muted);
}

.acc-more {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  height: 34px;
  margin: 16px 0 26px;
  padding: 0 1rem;
  border: 1px solid var(--color-teal);
  border-radius: 999px;
  color: var(--color-teal);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  text-decoration: none;
  white-space: nowrap;
}

/* Written out in full so the hover colours keep their transition alongside
   the reveal (a shorter selector would replace the whole list). */
.acc-body > .acc-more {
  transition: background-color 0.35s var(--ease-in-out),
              color 0.35s var(--ease-in-out),
              opacity 0.25s var(--ease-in-out),
              transform 0.25s var(--ease-in-out);
}

.acc-item.is-open .acc-body > .acc-more {
  transition: background-color 0.35s var(--ease-in-out),
              color 0.35s var(--ease-in-out),
              opacity 0.6s var(--ease-out) 0.32s,
              transform 0.9s var(--ease-out) 0.32s;
}

.acc-more svg {
  transition: transform 0.4s var(--ease-out);
}

.acc-more:hover {
  background-color: var(--color-teal);
  color: var(--color-cream);
}

.acc-more:hover svg {
  transform: translateX(3px);
}

/* Row 04 wraps to two lines and carries more air in the reference. */
.acc-item--tall .acc-head {
  padding-top: 42px;
  padding-bottom: 42px;
}

/* The frame clips the images, so they can zoom during a swap without
   spilling out. It hugs the fixed-size image here and fills its column once
   the images go fluid (see the scaled layouts below). */
.services-figure {
  position: relative;
  justify-self: start;
  margin-top: -13px;
  overflow: hidden;
}

.services-figure img {
  display: block;
  width: 604px;
  height: 624px;
  object-fit: cover;
}

/* The other service images sit on top of the first, hidden until their row
   opens (js/accordion.js wipes the incoming one in over the current one). */
.services-figure .service-img + .service-img {
  position: absolute;
  top: 0;
  left: 0;
}

/* Relative, not static: the first image stays in the flow to size the frame,
   but it still needs z-index to work, or it is drawn beneath the others when
   it is the one wiping in. */
.service-img {
  position: relative;
  visibility: hidden;
  transform-origin: center;
}

.service-img.is-active {
  visibility: visible;
}

@media (prefers-reduced-motion: reduce) {
  .acc-item::after,
  .acc-title,
  .acc-panel {
    transition: none;
  }

  .acc-body > *,
  .acc-item.is-open .acc-body > * {
    transform: none;
  }
}

/* ==========================================================================
   The Build Phase
   ========================================================================== */

.build {
  position: relative;
  height: 1315px; /* matches the serpentine's viewBox height in index.html */
  background-color: var(--color-teal);
  overflow: hidden;
}

.build-title {
  position: absolute;
  top: 18px;
  left: 0;
  right: 0;
  z-index: 2;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2rem, 3.9vw, 56px);
  line-height: 1.1;
  color: var(--color-cream);
  text-align: center;
}

.build-stage {
  position: absolute;
  inset: 0;
}

.build-path {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.build-line-bg,
.build-line {
  fill: none;
  stroke: var(--color-cream);
  stroke-width: 27;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.build-line-bg {
  opacity: 0.14;
}

.build-marker {
  position: absolute;
  left: 379px;
  top: 206px;
  width: 54px;
  height: 54px;
  margin: -27px 0 0 -27px;
  border-radius: 50%;
  background-color: rgba(255, 252, 241, 0.35);
}

.build-steps {
  position: absolute;
  inset: 0;
  list-style: none;
}

.build-step {
  position: absolute;
  width: 420px;
}

.build-step--right { left: 512px; }
.build-step--left  { left: 327px; }

.build-step:nth-child(1) { top: 187px; }
.build-step:nth-child(2) { top: 387px; }
.build-step:nth-child(3) { top: 619px; }
.build-step:nth-child(4) { top: 885px; }
.build-step:nth-child(5) { top: 1148px; }

.step-num {
  font-family: var(--font-sans);
  font-weight: 300;
  font-size: 32px;
  line-height: 1;
  color: rgba(255, 252, 241, 0.75);
}

.build-step--right .step-num,
.build-step--right .step-title {
  display: inline-block;
  vertical-align: middle;
}

.build-step--left .step-num,
.build-step--left .step-title {
  display: inline-block;
  vertical-align: middle;
}

.step-title {
  margin-left: 22px;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  font-size: 32px;
  line-height: 1;
  color: var(--color-cream);
}

.step-copy {
  margin-top: 14px;
  max-width: 430px;
  font-size: 0.8125rem;
  line-height: 1.55;
  color: rgba(255, 252, 241, 0.86); /* above 4.5:1 on the teal */
}

.build-step--right .step-copy { margin-left: 68px; }

/* ==========================================================================
   CTA
   ========================================================================== */

.cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 205px var(--gutter) 201px;
}

.cta-title {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.75rem, 3.1vw, 44px);
  line-height: 1.1;
  color: var(--color-teal);
}

.cta-sub {
  margin-top: 1.9rem;
  max-width: 550px;
  font-size: 0.8125rem;
  line-height: 1.65;
  color: var(--color-teal);
}

.cta .btn-outline {
  margin-top: 19px;
}

/* ==========================================================================
   Footer
   ========================================================================== */

.site-footer {
  padding: 62px 0 0px;
  background-color: var(--color-teal);
  border-radius: 40px 40px 0 0;
}

.footer-top {
  padding: 0 131px 0 116px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
}

.footer-copy {
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  color: var(--color-cream);
}

.footer-nav ul {
  display: flex;
  align-items: center;
  gap: 1.9rem;
  list-style: none;
}

.footer-nav a {
  font-size: 0.875rem;
  color: var(--color-cream);
  text-decoration: none;
  transition: opacity 0.3s ease;
}

.footer-nav a:hover {
  opacity: 0.7;
}

/* The copyright with the LinkedIn icon beside it. The link is a comfortable
   44px to tap, pulled back in with negative margins so the icon keeps a
   small, even gap from the text. */
.footer-brand {
  display: flex;
  align-items: center;
  gap: 1.5rem;
}

.footer-social {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin: -12px;
  color: var(--color-cream);
  transition: opacity 0.3s ease;
}

.footer-social:hover {
  opacity: 0.7;
}

.footer-social svg {
  display: block;
}

.footer-rule {
  margin: 23px 112px 0 110px;
  border-top: 1px dashed var(--color-hairline-on-teal);
}

.footer-wordmark {
  width: 1222px;
  height: 271px;
  max-width: none;
  margin: 30px 0 0 62px;
}

/* --- The footer lockup signs the page off (js/footer-mark.js) -------------
   The same gesture the loading screen opens with: the butterfly draws itself,
   then the name writes in behind it. Only reached once the <img> has been
   swapped for inline SVG, so none of this touches the plain artwork. */

/* The SVG keeps its default overflow: hidden, which is what clips the wipe
   panel to the artwork's own box as it travels off to the right. */
svg.footer-wordmark {
  display: block;
}

.footer-mark-line {
  /* pathLength="1" on the element, so the dash maths is independent of the
     path's real length (as in the preloader's mark). */
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}

/* The wipe is the footer's own teal, so the lettering does not appear from
   under a cover: it arrives as the cover leaves. */
.footer-word-wipe {
  transform: translateX(0);
}

/* An S-curve, not the site's usual --ease-out: a line that is drawing itself
   has to be seen doing it, and --ease-out is so front-loaded that the stroke
   is all but finished in the first tenth of a second. */
.is-drawn .footer-mark-line {
  animation: neu-footer-draw 1.1s var(--ease-in-out) calc(var(--i) * 0.16s) forwards;
}

/* Starts while the second leaf is still drawing, so the lockup reads as one
   movement rather than two. On the same even curve as the draw: --ease-out
   would put the name on screen before the eye has followed the sweep. */
.is-drawn .footer-word-wipe {
  animation: neu-footer-write 1.1s var(--ease-in-out) 0.8s forwards;
}

@keyframes neu-footer-draw {
  to { stroke-dashoffset: 0; }
}

@keyframes neu-footer-write {
  to { transform: translateX(var(--travel)); }
}

/* ==========================================================================
   About page (about.html)
   Measured from the about-page reference at the same 1440px design width.
   ========================================================================== */

/* Body copy here sits on cream at small sizes, so it uses a darker grey than
   --color-muted to keep 4.5:1 contrast. */
.page-about {
  --color-copy: rgba(30, 30, 26, 0.7);
}

.about-intro {
  padding: clamp(7.5rem, 16vw, 230px) var(--gutter) 0 clamp(1.25rem, 7.2vw, 104px);
}

.about-title {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(2.4rem, 5.1vw, 74px);
  line-height: 1.1;
  color: var(--color-teal);
}

.about-title em {
  font-style: italic;
}

.about-lead {
  margin-top: 1.25rem;
  max-width: 460px;
  font-size: 0.875rem;
  line-height: 1.8;
  color: var(--color-copy);
}

.about-story {
  display: grid;
  grid-template-columns: minmax(0, 595fr) minmax(0, 590fr);
  column-gap: clamp(2rem, 4.3vw, 62px);
  align-items: center;
  padding: clamp(3rem, 5.3vw, 76px) clamp(1.25rem, 6.1vw, 88px) clamp(3rem, 4.9vw, 70px) clamp(1.25rem, 7.2vw, 104px);
}

.about-story-figure img {
  width: 100%;
  height: auto;
  aspect-ratio: 595 / 480;
  object-fit: cover;
  border-radius: 14px;
}

.about-story-copy p {
  max-width: 590px;
  font-size: 0.875rem;
  line-height: 1.85;
  letter-spacing: 0.01em;
  color: var(--color-copy);
}

.about-work {
  padding: clamp(4rem, 9.4vw, 135px) clamp(1.25rem, 7.2vw, 104px) clamp(3.5rem, 6vw, 86px);
  background-color: var(--color-teal);
  border-radius: 60px 60px 0 0;
  text-align: center;
}

.about-work-title {
  font-size: clamp(2.1rem, 4.2vw, 60px);
}

.about-work-lead {
  max-width: 660px;
  margin: 2rem auto 0;
  font-size: 0.8125rem;
  line-height: 1.65;
  letter-spacing: 0.01em;
  color: var(--color-on-teal);
}

.about-work-eyebrow {
  margin-top: 3.25rem;
  font-weight: 400;
  color: var(--color-on-teal);
}

.about-cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 326px));
  justify-content: center;
  gap: clamp(1rem, 2.8vw, 40px);
  margin-top: clamp(2.5rem, 4.3vw, 62px);
  list-style: none;
  text-align: left;
}

.about-card {
  padding: 16px 16px 24px;
  background-color: var(--color-cream);
  border-radius: 14px;
}

.about-card img {
  width: 100%;
  height: auto;
  aspect-ratio: 294 / 238;
  object-fit: cover;
  border-radius: 6px;
}

.about-card-title {
  margin-top: 1rem;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.35rem, 1.85vw, 27px);
  line-height: 1.2;
  color: var(--color-teal);
}

.about-card p {
  margin-top: 0.6rem;
  font-size: 0.8125rem;
  line-height: 1.6;
  letter-spacing: 0.01em;
  color: var(--color-copy);
}

.about-why {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 520px);
  column-gap: clamp(2rem, 5.6vw, 82px);
  align-items: start;
  padding: clamp(4.5rem, 10.6vw, 152px) clamp(1.25rem, 6.1vw, 88px) 0 clamp(1.25rem, 7.2vw, 104px);
}

.about-why-title {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(2.1rem, 4.2vw, 60px);
  line-height: 1.1;
  color: var(--color-teal);
}

.about-why-copy {
  margin-top: 1.25rem;
  max-width: 590px;
  font-size: 0.875rem;
  line-height: 1.85;
  letter-spacing: 0.01em;
  color: var(--color-copy);
}

.about-why-wall {
  width: 100%;
  max-width: 643px;
  height: auto;
  aspect-ratio: 643 / 360;
  margin-top: clamp(2.5rem, 5.4vw, 78px);
  object-fit: cover;
  border-radius: 10px;
}

.about-why-side {
  width: 100%;
  height: auto;
  aspect-ratio: 520 / 515;
  margin-top: 18px;
  object-fit: cover;
  border-radius: 12px;
}

.about-cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: clamp(4.5rem, 9.7vw, 140px) clamp(1.25rem, 6.1vw, 88px) clamp(5rem, 11.8vw, 170px) clamp(1.25rem, 7.2vw, 104px);
  padding: clamp(4rem, 7.6vw, 110px) 1.5rem clamp(3.5rem, 6.9vw, 100px);
  border: 1.5px dashed var(--color-teal);
  border-radius: 16px;
  text-align: center;
}

.about-cta .cta-sub {
  margin-top: 1.5rem;
  max-width: 520px;
}

.about-cta .btn-outline {
  margin-top: 1.4rem;
  height: 44px;
  padding: 0 3.2rem;
}

@media (max-width: 900px) {
  .about-story,
  .about-why {
    grid-template-columns: 1fr;
    row-gap: 2rem;
  }

  .about-work {
    border-radius: 32px 32px 0 0;
  }

  .about-cards {
    grid-template-columns: minmax(0, 420px);
  }

  .about-why-wall {
    max-width: none;
  }

  .about-why-side {
    margin-top: 0;
  }
}

/* ==========================================================================
   Contact page (contact.html)
   Measured from the contact-page reference at the same 1440px design width.
   ========================================================================== */

.contact-intro {
  padding: clamp(7.5rem, 15.8vw, 228px) var(--gutter) clamp(5rem, 9vw, 130px);
  text-align: center;
}

.contact-title {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(2.3rem, 5.4vw, 78px);
  line-height: 1.12;
  color: var(--color-teal);
}

.contact-lead {
  max-width: 440px;
  margin: 1.5rem auto 0;
  font-size: 0.9375rem;
  line-height: 1.7;
  letter-spacing: 0.03em;
  color: rgba(30, 30, 26, 0.7);
}

.contact-form-section {
  padding: clamp(3.5rem, 6vw, 86px) var(--gutter) clamp(5rem, 11vw, 158px);
  background-color: var(--color-teal);
  border-radius: 72px 72px 0 0;
}

.contact-form-title {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(1.9rem, 2.7vw, 39px);
  line-height: 1.2;
  letter-spacing: 0.01em;
  color: var(--color-cream);
  text-align: center;
}

.contact-form {
  max-width: 934px;
  margin: clamp(1.5rem, 2.4vw, 34px) auto 0;
}

.contact-form :focus-visible {
  outline-color: var(--color-cream);
}

.contact-field + .contact-field {
  margin-top: clamp(1.5rem, 2.4vw, 34px);
}

.contact-field label {
  display: block;
  margin: 0 0 8px 11px;
  font-size: 1.0625rem;
  line-height: 1.4;
  letter-spacing: 0.01em;
  color: var(--color-cream);
}

.contact-field input,
.contact-field select,
.contact-field textarea {
  display: block;
  width: 100%;
  height: 47px;
  padding: 0 1rem;
  border: 0;
  border-radius: 10px;
  background-color: var(--color-cream);
  font: inherit;
  font-size: 1rem;
  color: var(--color-ink);
}

.contact-field textarea {
  height: 155px;
  padding: 0.85rem 1rem;
  line-height: 1.6;
  resize: vertical;
}

/* A plain field like the others, with a small teal chevron. */
.contact-field select {
  appearance: none;
  padding-right: 2.75rem;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23106b60' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1.1rem center;
  cursor: pointer;
}

.contact-honeypot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.contact-submit {
  margin-top: clamp(1.5rem, 2.2vw, 31px);
  height: 50px;
  padding: 0 0.45rem 0 1.9rem;
  border: 0;
  font-size: 0.9375rem;
  letter-spacing: 0.1em;
  cursor: pointer;
}

.contact-submit .btn-arrow {
  width: 24px;
  height: 24px;
  margin-left: 0.5rem;
  margin-right: 0.35rem;
}

.contact-submit:disabled {
  opacity: 0.65;
  cursor: progress;
}

.contact-status {
  min-height: 1.6em;
  margin-top: 1rem;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--color-cream);
}

.contact-status[data-state="error"]::before {
  content: "⚠ ";
}

.contact-ways {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 402px));
  justify-content: center;
  gap: clamp(1rem, 2.8vw, 40px);
  padding: clamp(4rem, 8.5vw, 122px) var(--gutter) clamp(5rem, 8.7vw, 125px);
}

.contact-card {
  padding: 26px 22px 24px;
  border: 1.5px dashed var(--color-teal);
  border-radius: 12px;
}

.contact-card-title {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(1.4rem, 1.85vw, 27px);
  line-height: 1.2;
  color: var(--color-teal);
}

.contact-card-note {
  margin-top: 0.25rem;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--color-teal);
}

.contact-card-value {
  display: inline-block;
  margin-top: 1rem;
  font-size: clamp(1.1rem, 1.45vw, 21px);
  line-height: 1.3;
  color: var(--color-ink);
  text-decoration: none;
  overflow-wrap: anywhere;
}

.contact-card-value:hover {
  color: var(--color-teal);
  text-decoration: underline;
  text-underline-offset: 3px;
}

@media (max-width: 900px) {
  .contact-form-section {
    border-radius: 32px 32px 0 0;
  }

  .contact-ways {
    grid-template-columns: minmax(0, 460px);
  }
}

/* ==========================================================================
   Services page (services.html)
   Measured from the services-page reference at the same 1440px design width.
   The closing call-to-action reuses the about page's .about-cta box.
   ========================================================================== */

.svc-intro {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 370px);
  column-gap: clamp(2rem, 6vw, 90px);
  align-items: start;
  padding: clamp(7.5rem, 15.3vw, 220px) clamp(1.25rem, 6.1vw, 88px) 0 clamp(1.25rem, 7.4vw, 106px);
}

.svc-title {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(2.3rem, 5.4vw, 78px);
  line-height: 1.2;
  color: var(--color-teal);
}

.svc-lead {
  margin-top: clamp(0.5rem, 1.4vw, 20px);
  font-size: 0.875rem;
  line-height: 1.8;
  letter-spacing: 0.06em;
  color: rgba(30, 30, 26, 0.7);
}

/* Three photos; the middle one sits a little higher than its neighbours. */
.svc-gallery {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1rem, 2.2vw, 32px);
  align-items: start;
  padding: clamp(3rem, 6.2vw, 90px) clamp(1.25rem, 6vw, 86px) 0 clamp(1.25rem, 3vw, 44px);
}

/* The frame clips the photo; the photo is taller than the frame (and pulled
   up by half the difference) so it has room to drift inside on scroll. */
.svc-gallery-item {
  position: relative;
  overflow: hidden;
  aspect-ratio: 416 / 478;
  border-radius: 14px;
  /* Keeps the rounded clip crisp while the frame itself is transformed. */
  isolation: isolate;
}

.svc-gallery-item img {
  position: relative;
  top: -10%;
  width: 100%;
  height: 120%;
  object-fit: cover;
}

.svc-gallery-item:not(:nth-child(2)) {
  margin-top: clamp(1rem, 2.2vw, 32px);
}

.svc-quote {
  margin-top: clamp(4rem, 12.8vw, 184px);
  padding: clamp(3rem, 5.6vw, 80px) var(--gutter) clamp(4rem, 10.4vw, 150px);
  background-color: var(--color-teal);
  border-radius: 60px 60px 0 0;
  text-align: center;
}

.svc-quote p {
  max-width: 1090px;
  margin: 0 auto;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.6rem, 3.35vw, 48px);
  line-height: 1.45;
  color: var(--color-cream);
}

.svc-list {
  display: grid;
  grid-template-columns: minmax(0, 470px) minmax(0, 760px);
  justify-content: space-between;
  column-gap: clamp(2rem, 5vw, 80px);
  align-items: start;
  padding: clamp(4rem, 8.4vw, 120px) clamp(1.25rem, 6vw, 86px) clamp(4rem, 12vw, 172px) clamp(1.25rem, 5.9vw, 85px);
}

/* Follows the reader down the list of services. */
.svc-nav {
  position: sticky;
  top: 7.5rem;
}

.svc-nav ul {
  margin-top: 1.1rem;
  list-style: none;
}

/* The other services sit back — smaller and fainter — and the one on screen
   grows to full size and full colour as it takes over. */
.svc-nav a {
  display: inline-block;
  padding: 0.3rem 0;
  font-family: var(--font-serif);
  font-weight: 400;
  /* 28px minimum: even scaled down to 86% it stays above 24px, so it still
     counts as large text for contrast. */
  font-size: clamp(1.75rem, 2.3vw, 33px);
  line-height: 1.25;
  /* 66% teal: just above 3:1 on cream, the floor for large text. */
  color: rgba(16, 107, 96, 0.345);
  text-decoration: none;
  transform: scale(0.86);
  transform-origin: left center;
  transition: color 0.5s var(--ease-in-out),
              transform 0.7s var(--ease-out);
}

.svc-nav a:hover {
  color: var(--color-teal);
}

.svc-nav a[aria-current] {
  color: var(--color-teal);
  transform: scale(1);
}

@media (prefers-reduced-motion: reduce) {
  .svc-nav a {
    transition: color 0.3s var(--ease-in-out);
  }
}

.svc-item {
  padding-top: 1.75rem;
  border-top: 2px dashed var(--color-teal);
  scroll-margin-top: 2rem;
}

.svc-item + .svc-item {
  margin-top: clamp(4rem, 8.4vw, 120px);
}

.svc-item h2 {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(1.6rem, 2.45vw, 35px);
  line-height: 1.2;
  color: var(--color-teal);
}

.svc-item p {
  max-width: 640px;
  margin-top: 0.6rem;
  font-size: 0.875rem;
  line-height: 1.5;
  letter-spacing: 0.03em;
  color: rgba(30, 30, 26, 0.8);
}

.svc-tags {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 192px));
  gap: 10px 20px;
  margin-top: 1.6rem;
  list-style: none;
}

.svc-tags li {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 30px;
  padding: 0.2rem 0.6rem;
  border: 1px solid var(--color-teal);
  border-radius: 999px;
  font-size: 0.8125rem;
  line-height: 1.2;
  color: var(--color-teal);
  text-align: center;
  white-space: nowrap;
}

.svc-item img {
  width: 100%;
  max-width: 673px;
  height: auto;
  aspect-ratio: 673 / 296;
  margin-top: 1.9rem;
  object-fit: cover;
  border-radius: 12px;
}

.svc-faq {
  padding: clamp(4rem, 7.5vw, 108px) var(--gutter) clamp(4rem, 8.4vw, 120px);
  background-color: var(--color-teal);
}

.svc-faq :focus-visible {
  outline-color: var(--color-cream);
}

.svc-faq-title {
  font-size: clamp(2.1rem, 4.3vw, 62px);
  text-align: center;
}

.faq-list {
  max-width: 934px;
  margin: clamp(2.5rem, 5vw, 72px) auto 0;
}

.faq-item {
  background-color: var(--color-cream);
  border-radius: 8px;
}

.faq-item + .faq-item {
  margin-top: 30px;
}

.faq-item summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 54px;
  padding: 0.85rem 1.4rem;
  font-size: 1rem;
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: 0.04em;
  color: var(--color-teal);
  list-style: none;
  cursor: pointer;
}

.faq-item summary::-webkit-details-marker {
  display: none;
}

.faq-item summary::after {
  content: "";
  flex: none;
  width: 16px;
  height: 16px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23106b60' stroke-width='2.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform 0.4s var(--ease-out);
}

.faq-item[open] summary::after {
  transform: rotate(180deg);
}

.faq-item p {
  padding: 0 1.4rem 1.25rem;
  font-size: 0.9375rem;
  line-height: 1.75;
  color: rgba(30, 30, 26, 0.75);
}

@media (max-width: 900px) {
  .svc-intro,
  .svc-list {
    grid-template-columns: 1fr;
    row-gap: 1.5rem;
  }

  .svc-quote {
    border-radius: 32px 32px 0 0;
  }

  /* The side list becomes a short jump menu above the services. */
  .svc-nav {
    position: static;
    margin-bottom: 1.5rem;
  }

  .svc-tags {
    display: flex;
    flex-wrap: wrap;
  }

  .svc-item img {
    max-width: none;
  }
}

@media (max-width: 560px) {
  .svc-gallery {
    grid-template-columns: 1fr;
  }

  .svc-gallery-item {
    aspect-ratio: 4 / 3;
  }

  /* Phones show only the middle photo, full width. */
  .svc-gallery-item:not(:nth-child(2)) {
    display: none;
  }
}

/* ==========================================================================
   Mobile & tablet menu (js/menu.js) — 900px and below
   Three panels after GreenSock's clear()-and-rebuild pen, in the site's
   colours: cream links, a teal call to action, dark contact details.
   ========================================================================== */

.menu-toggle,
.menu {
  display: none;
}

html.menu-open,
html.menu-open body {
  overflow: hidden;
}

@media (max-width: 900px) {
  /* Leave room at the right of the header for the floating toggle. */
  .nav-cluster {
    margin-right: 56px;
  }

  .menu-toggle {
    position: fixed;
    top: calc(1.5rem - 2px);
    right: 1.25rem;
    z-index: 9450;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 1px solid rgba(255, 252, 241, 0.35);
    border-radius: 50%;
    background-color: var(--color-teal);
    cursor: pointer;
    transition: opacity 0.9s var(--ease-in-out) 0.18s;
  }

  .is-loading .menu-toggle {
    opacity: 0;
    pointer-events: none;
  }

  .menu-bar {
    stroke: var(--color-cream);
    stroke-width: 1.5;
    stroke-linecap: round;
  }

  .menu {
    position: fixed;
    inset: 0;
    z-index: 9400;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.5rem;
    padding: 0.75rem;
    visibility: hidden;
    pointer-events: none;
  }
}

.menu-bg {
  position: absolute;
  inset: 0;
  background-color: rgba(30, 30, 26, 0.45);
}

.menu-panel {
  position: relative;
  width: 100%;
  max-width: 700px;
  border: 2px solid;
  border-radius: 14px;
}

.menu-top {
  z-index: 3;
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
  padding: 4.5rem 1.75rem 1.5rem;
  overflow-y: auto;
  background-color: var(--color-cream);
  border-color: var(--color-teal);
}

.menu-list {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  list-style: none;
}

.menu-link {
  display: block;
  padding: 0.35rem 0;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2rem, 8vw, 3rem);
  line-height: 1.15;
  color: var(--color-teal);
  text-decoration: none;
}

.menu-link[aria-current="page"]::after {
  content: "";
  display: inline-block;
  width: 8px;
  height: 8px;
  margin-left: 0.6rem;
  border-radius: 50%;
  background-color: var(--color-teal);
  vertical-align: middle;
}

.menu-meta {
  margin-top: auto;
  padding-top: 1.25rem;
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  color: rgba(30, 30, 26, 0.7);
}

.menu-meta a {
  color: inherit;
}

.menu-middle {
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  min-height: 150px;
  padding: 1.4rem 1.75rem;
  background-color: var(--color-teal);
  border-color: var(--color-teal-deep);
  color: var(--color-cream);
}

.menu-eyebrow {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--color-on-teal);
}

.menu-title {
  margin: 0.4rem 0 1rem;
  font-family: var(--font-serif);
  font-style: italic;
  font-size: clamp(1.4rem, 5vw, 1.9rem);
  line-height: 1.2;
}

.menu-cta {
  display: inline-flex;
  align-items: center;
  height: 40px;
  padding: 0 1.4rem;
  border-radius: 999px;
  background-color: var(--color-cream);
  font-size: 0.875rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--color-teal);
  text-decoration: none;
}

.menu-bottom {
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 1rem;
  min-height: 96px;
  padding: 1.2rem 1.75rem;
  background-color: var(--color-ink);
  border-color: rgba(255, 252, 241, 0.18);
  color: rgba(255, 252, 241, 0.72);
}

.menu-contact {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
  list-style: none;
  font-size: 0.875rem;
}

.menu-contact a {
  color: var(--color-cream);
  text-decoration: none;
}

.menu-mark {
  flex: none;
  margin-left: auto;
  border-radius: 10px;
}

.menu-middle :focus-visible,
.menu-bottom :focus-visible {
  outline-color: var(--color-cream);
}

/* ==========================================================================
   Portfolio page (portfolio.html) — a "coming soon" page in the site's style
   until there is real work to show. The call to action reuses .about-cta.
   ========================================================================== */

.pf-intro {
  padding: clamp(7.5rem, 15.3vw, 220px) var(--gutter) clamp(4rem, 8vw, 116px) clamp(1.25rem, 7.4vw, 106px);
}

.pf-title {
  max-width: 980px;
  margin-top: 1.5rem;
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(2.4rem, 5.6vw, 80px);
  line-height: 1.1;
  color: var(--color-teal);
}

.pf-title em {
  font-style: italic;
}

.pf-lead {
  max-width: 560px;
  margin-top: 1.5rem;
  font-size: 0.9375rem;
  line-height: 1.8;
  letter-spacing: 0.02em;
  color: rgba(30, 30, 26, 0.72);
}

.pf-preview {
  padding: clamp(4rem, 8vw, 116px) var(--gutter) clamp(4rem, 8.4vw, 120px);
  background-color: var(--color-teal);
  border-radius: 60px 60px 0 0;
  text-align: center;
}

.pf-preview-title {
  font-size: clamp(2.1rem, 4.2vw, 60px);
}

.pf-preview-lead {
  max-width: 560px;
  margin: 1.5rem auto 0;
  font-size: 0.875rem;
  line-height: 1.7;
  color: var(--color-on-teal);
}

.pf-cards {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(1rem, 2vw, 28px);
  max-width: 1260px;
  margin: clamp(2.5rem, 4.5vw, 64px) auto 0;
  list-style: none;
  text-align: left;
}

.pf-card {
  padding: 14px 14px 22px;
  background-color: var(--color-cream);
  border-radius: 14px;
}

/* The work itself is not ready, so the photo stays a soft, teal-tinted hint. */
.pf-card-frame {
  position: relative;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  border-radius: 8px;
  background-color: var(--color-teal-deep);
}

.pf-card-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1) blur(3px) brightness(0.9);
  mix-blend-mode: luminosity;
  opacity: 0.55;
  transform: scale(1.08);
}

/* A slow light sweep across the frame, like a page still loading. */
.pf-card-frame::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(105deg, transparent 35%, rgba(255, 252, 241, 0.22) 50%, transparent 65%);
  transform: translateX(-100%);
  animation: pf-shimmer 3.2s var(--ease-in-out) infinite;
}

.pf-card:nth-child(2) .pf-card-frame::after { animation-delay: 0.4s; }
.pf-card:nth-child(3) .pf-card-frame::after { animation-delay: 0.8s; }
.pf-card:nth-child(4) .pf-card-frame::after { animation-delay: 1.2s; }

@keyframes pf-shimmer {
  0%       { transform: translateX(-100%); }
  60%, 100% { transform: translateX(100%); }
}

.pf-badge {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 1;
  padding: 0.4rem 0.95rem;
  border: 1px solid rgba(255, 252, 241, 0.6);
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--color-cream);
  transform: translate(-50%, -50%);
}

.pf-card-title {
  margin-top: 1rem;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.3rem, 1.7vw, 24px);
  line-height: 1.2;
  color: var(--color-teal);
}

.pf-card p {
  margin-top: 0.45rem;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: rgba(30, 30, 26, 0.72);
}

.pf-cta-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 1rem 1.75rem;
}

.pf-cta-actions .btn-outline {
  margin-top: 1.4rem;
}

.pf-cta-link {
  margin-top: 1.4rem;
  font-size: 0.9375rem;
  color: var(--color-teal);
  text-underline-offset: 4px;
}

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

@media (max-width: 900px) {
  .pf-preview {
    border-radius: 32px 32px 0 0;
  }
}

@media (max-width: 560px) {
  .pf-cards {
    grid-template-columns: 1fr;
  }
}

@media (prefers-reduced-motion: reduce) {
  .pf-card-frame::after {
    animation: none;
  }
}

/* ==========================================================================
   Scroll-reveal base states (added by main.js only when GSAP is available)
   ========================================================================== */

.has-anim [data-rise] {
  opacity: 0;
  transform: translateY(24px);
}

/* Heading line reveal (js/animations.js): each line slides up from behind its
   own mask. The padding and matching negative margin leave room for italic
   overhangs and descenders without moving the lines. */
.line-wrapper {
  overflow: hidden;
  padding: 0.08em 0.12em 0.16em;
  margin: -0.08em -0.12em -0.16em;
}

/* Hero headings (the h1 on the inner pages) are on screen from the first
   paint, but the line reveal only starts once GSAP and SplitType have loaded.
   Hold them hidden until they are split, so they do not flash, vanish and
   then slide in. If the scripts never arrive, they appear after 3 seconds
   anyway; with motion reduced (no reveal runs) they are never held. */
@media (scripting: enabled) and (prefers-reduced-motion: no-preference) {
  h1[data-text-reveal]:not(.is-split) {
    animation: text-reveal-fallback 0.01s 3s both;
  }
}

@keyframes text-reveal-fallback {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ==========================================================================
   Loading state — the hero holds its entrance until the preloader hands over.
   Keyed off .is-loading, which only exists when JS is running.
   ========================================================================== */

/* While loading, the hero's supporting pieces only wait out of place: the
   opaque preloader panel already hides them, so they need not start
   invisible. They rise into position as the panel fades, and are never
   caught half-transparent (which reads as low contrast).

   The header is the exception: it does not move at all. The preloader's name
   flies into its logo, so the logo has to be a stationary target — if the
   header were still sliding down, the name would land and then watch the logo
   arrive underneath it. Standing still also reads better here: the header was
   always there, and the panel lifted off it. */

.is-loading .scroll-cue,
.is-loading .hero-sub {
  transform: translateY(1.5rem);
}

/* The hero photo only rises: the opaque preloader panel already hides it, so
   keeping it fully opaque lets it decode and paint straight away — it is the
   largest thing on the page — and it is ready the moment the panel fades. */
.is-loading .hero-figure {
  transform: translateY(1.5rem);
}

.scroll-cue,
.hero-sub,
.hero-figure {
  transition: opacity 0.9s var(--ease-in-out), transform 1.1s var(--ease-out);
}

.scroll-cue { transition-delay: 0.3s; }
.hero-sub   { transition-delay: 0.4s; }
.hero-figure { transition-delay: 0.5s; }

.is-loading .wordmark.reflection {
  opacity: 0;
}

.is-loading .butterfly {
  opacity: 0;
  transform: translateY(-0.75rem) rotate(-8deg);
}

.is-loading .wordmark {
  opacity: 0;
}

.is-loading .wordmark .letter-inner {
  transform: translateY(120%);
}

.is-loading .wordmark:not(.reflection) .letter-inner {
  filter: blur(5px);
}

/* The handoff: the real <h1> rises above the preloader panel and then stays
   perfectly still while the panel fades away underneath it. */
.is-handoff .wordmark-wrap {
  z-index: 9500;
}

/* Only the <h1> is lifted — the reflection stays down and fades to its own
   0.3 once the panel is gone. */
.is-loading.is-handoff .wordmark:not(.reflection) {
  opacity: 1;
}

.is-loading.is-handoff .wordmark .letter-inner {
  transform: translateY(0);
}

.is-loading.is-handoff .wordmark:not(.reflection) .letter-inner {
  filter: blur(0);
}

/* ==========================================================================
   Reduced motion
   ========================================================================== */

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

  .preloader,
  .pre-mark-wrap,
  .pre-word-wrap,
  .pre-caption,
  .site-header,
  .scroll-cue,
  .hero-sub,
  .hero-figure,
  .wordmark .letter-inner,
  .wordmark.reflection,
  .butterfly {
    transition-duration: 0.25s !important;
    transition-delay: 0s !important;
  }

  /* No draw, no wing beat — the mark is simply present, inked and still. */
  .pre-mark,
  .pre-mark-drift,
  .pre-mark-line,
  .pre-mark-fill,
  .pre-mark-tile {
    animation: none;
    transform: none;
  }

  .pre-mark-fill {
    opacity: 1;
  }

  .pre-mark-line {
    stroke-opacity: 0;
  }

  /* Nothing is written — the name is simply there, and the pen never shows. */
  .pw-ink,
  .pre-word-tittle,
  .pre-word-nib,
  .pre-word-nib-dot {
    animation: none;
  }

  .pw-ink {
    transform: scaleX(1);
  }

  .pre-word-tittle {
    opacity: 1;
    transform: none;
  }

  .pre-word-nib-dot {
    opacity: 0;
  }

  .footer-mark-line,
  .footer-word-wipe {
    animation: none;
  }

  .footer-mark-line {
    stroke-dashoffset: 0;
  }

  .footer-word-wipe {
    transform: translateX(var(--travel));
  }

  .marquee-track {
    animation: none;
  }

  .is-loading .scroll-cue,
  .is-loading .hero-sub,
  .is-loading .hero-figure,
  .is-loading .butterfly,
  .is-loading .wordmark .letter-inner {
    transform: none;
  }

  .butterfly {
    transform: none;
  }

  .has-anim [data-rise] {
    opacity: 1;
    transform: none;
    filter: none;
  }

  /* Must match the specificity of the blur rule above, which gained a
     :not(.reflection) — a plainer selector would now lose to it. */
  .is-loading .wordmark:not(.reflection) .letter-inner {
    filter: none;
  }
}

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 1399px) {
  /* Below the design width everything scales from the same proportions. */
  .site-header { padding: 2.7vw 5vw 0 3.33vw; }
  .logo img { width: 14.7vw; height: auto; }
  .nav-cluster { height: 3.7vw; padding: 0 0.28vw 0 1.21vw; gap: 1.04vw; }
  .main-nav ul { gap: 1.21vw; }
  .main-nav a { font-size: 1.04vw; }
  .btn-solid { height: 3.13vw; padding: 0 1.04vw; font-size: 0.97vw; }

  .hero { padding-top: 18.6vw; padding-bottom: 9.2vw; }
  .scroll-cue { margin-top: 16.7vw; }
  .hero-figure { margin-top: 10.6vw; }

  .manifesto { height: 74.9vw; }
  .float-1 { left: 11.5vw;  top: 4.2vw;  width: 10.9vw; height: 14.7vw; }
  .float-2 { left: 59.9vw;  top: 4vw;    width: 10.8vw; height: 13.9vw; }
  .float-3 { left: 18.6vw;  top: 50.3vw; width: 10.8vw; height: 13.9vw; }
  .float-4 { left: 51vw;    top: 50.4vw; width: 11vw;   height: 13.8vw; }
  .float-5 { left: 85vw;    top: 44vw;   width: 10.8vw; height: 13.8vw; }
  .manifesto-copy { top: 22.4vw; }

  .magicians {
    grid-template-columns: 42vw 1fr;
    column-gap: 5.8vw;
    padding: 9.4vw 5.4vw 8.7vw 6.3vw;
  }
  .magicians-figure img { width: 100%; height: 43.3vw; }
  .magicians-copy { padding-top: 7.2vw; max-width: 37vw; }

  .services { padding: 12.6vw 0 13.8vw; }
  .services-head { gap: 5.5vw; padding-left: 7.2vw; }
  .services-body { grid-template-columns: 49vw 1fr; column-gap: 4.6vw; margin-top: 8vw; }
  .acc-head { padding: 1.8vw 2.6vw 1.8vw 5.1vw; grid-template-columns: 2.2vw 1fr 2.43vw; }
  .acc-body { padding-left: 8vw; padding-right: 2.6vw; }
  .services-figure { justify-self: stretch; }
  .services-figure img { width: 100%; height: 43.3vw; }

  .build { height: 91.3vw; }
  .build-marker { left: 26.3vw; top: 14.3vw; width: 3.75vw; height: 3.75vw; margin: -1.87vw 0 0 -1.87vw; }
  .build-step { width: 29vw; }
  .build-step--right { left: 35.6vw; }
  .build-step--left  { left: 22.7vw; }
  .build-step:nth-child(1) { top: 11.7vw; }
  .build-step:nth-child(2) { top: 25.6vw; }
  .build-step:nth-child(3) { top: 41.7vw; }
  .build-step:nth-child(4) { top: 60.1vw; }
  .build-step:nth-child(5) { top: 78.4vw; }
  /* Scaled with the path, but never below a readable size (iPad landscape, small laptops). */
  .step-num, .step-title { font-size: max(1.35rem, 2.22vw); }
  .step-copy { font-size: max(0.8125rem, 0.9vw); max-width: 30vw; }
  .build-step--right .step-copy { margin-left: 4.7vw; }

  .cta { padding-top: 14.2vw; padding-bottom: 13.9vw; }

  /* The footer's own padding does the insetting here, so the desktop px
     padding and margins on its rows are dropped. */
  .site-footer { padding: 4.3vw 9.1vw 4.9vw 8.1vw; }
  .footer-top { padding: 0; }
  .footer-rule { margin: 2.3vw 0 0; }
  .footer-wordmark { width: 84.9vw; height: auto; margin: 3.4vw 0 0 -3.8vw; }
  .marquee { height: 6.3vw; }
  .marquee-run { font-size: 2.78vw; }
}

/* --- Tablet ---------------------------------------------------------------- */

@media (max-width: 900px) {
  .site-header { padding: 1.5rem 1.25rem 0; }
  .logo img { width: 150px; }
  .nav-cluster { height: auto; padding: 0; background: none; gap: 0; }
  .main-nav { display: none; }
  .btn-solid { height: 40px; padding: 0 1.1rem; font-size: 0.8125rem; }

  .hero { padding-top: 34vw; padding-bottom: 4rem; }
  .wordmark { font-size: 15.5vw; }
  .butterfly { width: 12vw; height: auto; top: -8vw; }
  .scroll-cue { margin-top: 12vw; font-size: 0.9375rem; }
  .hero-figure { margin-top: 3.5rem; }

  /* The scattered collage collapses to a readable stack. */
  .manifesto { height: auto; padding: 4rem var(--gutter) 5rem; }
  .manifesto-copy { position: static; transform: none; width: 100%; top: auto; }
  .float-img {
    position: static;
    justify-self: center;
    width: 100%;
    max-width: 260px; /* keeps tablets from blowing the photos up */
    height: auto;
    aspect-ratio: 4 / 5;
  }
  /* A small collage echoing the desktop one: two photos above the quote,
     three below, with the middle of each row set a little lower. */
  .manifesto {
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    align-items: start;
    gap: 1rem;
  }
  .float-1 { grid-column: 1 / 4; }
  .float-2 { grid-column: 4 / 7; margin-top: 2.5rem; }
  .float-3 { grid-column: 1 / 3; }
  .float-4 { grid-column: 3 / 5; margin-top: 2rem; }
  .float-5 { grid-column: 5 / 7; }
  .manifesto-copy { grid-column: 1 / -1; margin: 1.5rem 0 2.5rem; }
  .pull-quote { font-size: clamp(1.4rem, 5.2vw, 2.2rem); }

  .magicians {
    grid-template-columns: 1fr;
    row-gap: 2.5rem;
    padding: 4rem var(--gutter) 4.5rem;
  }
  .magicians-figure img { width: 100%; height: auto; aspect-ratio: 604 / 624; }
  .magicians-copy { padding-top: 0; max-width: none; }
  .magicians-copy .h-italic { font-size: clamp(1.9rem, 6.4vw, 2.6rem); }

  .services { padding: 4rem 0 4.5rem; }
  .services-head { flex-direction: column; gap: 1.25rem; padding: 0 var(--gutter); }
  .services-head .tag { margin-top: 0; }
  .services-title { font-size: clamp(1.9rem, 6.2vw, 2.6rem); }
  .services-body { grid-template-columns: 1fr; row-gap: 2.5rem; margin-top: 3rem; }
  .acc-head { grid-template-columns: 28px 1fr 32px; padding: 1.15rem var(--gutter); }
  .acc-title { font-size: clamp(1.25rem, 4.6vw, 1.75rem); }
  .acc-body { padding: 0 var(--gutter) 0 calc(var(--gutter) + 28px); }
  .acc-more { margin: 0.875rem 0 1.5rem; }
  .acc-item.is-open .acc-title { transform: translateX(6px); }
  .services-figure { margin: 0 var(--gutter); }
  .services-figure img { width: 100%; height: auto; aspect-ratio: 604 / 624; }

  /* The serpentine becomes a single spine so nothing overlaps. */
  /* The serpentine becomes a vertical timeline: the section grows with its
     content, the heading sits above it, and each step gets a dot on the line. */
  .build { height: auto; padding: 3.5rem 0 0; }
  .build-title { position: static; padding: 0 var(--gutter); }
  .build-stage { position: static; height: auto; margin-top: 2.5rem; padding: 0 var(--gutter) 4rem; }
  .build-path, .build-marker { display: none; }
  .build-steps {
    position: static;
    display: grid;
    row-gap: 2.5rem;
    margin-left: 6px;
    padding-left: 1.75rem;
    border-left: 2px solid rgba(255, 252, 241, 0.25);
  }
  .build-steps > .build-step { position: relative; top: auto; left: auto; width: auto; }
  .build-step::before {
    content: "";
    position: absolute;
    top: 5px;
    left: calc(-1.75rem - 8px);
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background-color: var(--color-cream);
    box-shadow: 0 0 0 5px rgba(255, 252, 241, 0.2);
  }
  .step-num, .step-title { font-size: 1.5rem; }
  .step-title { margin-left: 14px; }
  .step-copy { font-size: 0.9375rem; max-width: 38rem; }
  .build-step--right .step-copy { margin-left: 0; }

  .cta { padding: 4.5rem var(--gutter) 5rem; }

  /* The desktop footer insets its rows with fixed px padding and margins;
     here the footer's own gutter does that job. */
  .site-footer { padding: 2.5rem var(--gutter) 2.5rem; border-radius: 24px 24px 0 0; }
  .footer-top { flex-wrap: wrap; gap: 1.25rem; padding: 0; }
  .footer-nav ul { flex-wrap: wrap; gap: 1rem 1.25rem; }
  .footer-rule { margin: 1.5rem 0 0; }
  /* Full width here, so drop the desktop left offset or it overflows the screen. */
  .footer-wordmark { width: 100%; height: auto; margin: 2.5rem 0 0; }

  .marquee { height: 60px; }
  .marquee-run { font-size: 26px; }
}

@media (max-width: 560px) {
  .pre-caption { max-width: 18rem; }
  .footer-top { flex-direction: column; align-items: flex-start; }
  /* Phones show the manifesto as text only: the collage photos are hidden
     (and, being lazy, never downloaded). */
  .manifesto .float-img { display: none; }
  .manifesto-copy { margin: 0; }
  .marquee { height: 48px; }
  .marquee-run { font-size: 20px; }
}

/* ==========================================================================
   Section spacing on tablets and phones
   One value for the space above and below every section, on every page, so
   the page breathes evenly. Last in the file so it wins over the per-section
   mobile paddings above. The top of each page's first section is left alone:
   that space clears the header.
   ========================================================================== */

@media (max-width: 900px) {
  :root {
    --section-space: 6.5rem;
  }

  /* Home */
  .hero { padding-bottom: var(--section-space); }
  .manifesto,
  .magicians,
  .services,
  .cta { padding-top: var(--section-space); padding-bottom: var(--section-space); }
  .build { padding-top: var(--section-space); }
  .build-stage { padding-bottom: var(--section-space); }

  /* About */
  .about-intro { padding-bottom: calc(var(--section-space) * 0.5); }
  .about-story,
  .about-work { padding-top: var(--section-space); padding-bottom: var(--section-space); }
  .about-why { padding-top: var(--section-space); }

  /* Services */
  .svc-quote { margin-top: var(--section-space); padding-top: var(--section-space); padding-bottom: var(--section-space); }
  .svc-list,
  .svc-faq { padding-top: var(--section-space); padding-bottom: var(--section-space); }

  /* Contact */
  .contact-intro { padding-bottom: var(--section-space); }
  .contact-form-section,
  .contact-ways { padding-top: var(--section-space); padding-bottom: var(--section-space); }

  /* Portfolio */
  .pf-intro { padding-bottom: var(--section-space); }
  .pf-preview { padding-top: var(--section-space); padding-bottom: var(--section-space); }

  /* The dashed "Let's talk" box used on About, Services and Portfolio. */
  .about-cta { margin-top: var(--section-space); margin-bottom: var(--section-space); }
}

@media (max-width: 560px) {
  :root {
    --section-space: 5.5rem;
  }
}

/* ==========================================================================
   404
   ========================================================================== */

.nf {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 150px var(--gutter) 130px;
  text-align: center;
  /* Scattered dots never widen the page, and a finger can still scroll it. */
  overflow: hidden;
  touch-action: pan-y;
}

.nf > * {
  position: relative;
  z-index: 1;
}

/* Dots for the big number (js/not-found.js). Behind the copy, and never in
   the way of a click. */
.nf .nf-canvas {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.nf-stage {
  position: relative;
  margin: 3.25rem 0 7.5rem;
}

.nf-number {
  font-size: clamp(8rem, 31vw, 400px);
}

/* Once the dots are drawn they stand in for the text. */
.nf.is-live .nf-number {
  visibility: hidden;
}

.nf-title {
  max-width: 15ch;
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(2rem, 4.2vw, 60px);
  line-height: 1.12;
  color: var(--color-teal);
}

.nf-lead {
  max-width: 440px;
  margin-top: 1.4rem;
  font-size: 0.9375rem;
  line-height: 1.7;
  letter-spacing: 0.03em;
  color: rgba(30, 30, 26, 0.7);
}

.nf-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.9rem 1.5rem;
  margin-top: 2.25rem;
}

@media (max-width: 560px) {
  .nf {
    padding: 120px var(--gutter) 90px;
  }

  .nf-stage {
    margin: 2.5rem 0 4.25rem;
  }
}
