/* ==========================================================================
   SELF-HOSTED TYPE

   These four faces replace the render-blocking fonts.googleapis.com
   stylesheet. They are the same files Google was serving, fetched from the
   same origin as the site, so the families resolve exactly as before — the
   declared weight, stretch and unicode-range values below are copied from
   the Google stylesheet verbatim rather than narrowed.

   Archivo is variable and carries the full 62–125% width and 100–900 weight
   axes. The site only uses 88–118% and 400–700, but Google serves one file
   for every requested axis range, and there is no subsetting toolchain on
   this machine, so narrowing was not possible. Declaring the full range is
   also the safer choice: nothing can fall outside it.

   The latin-ext face exists for one character. ₹ (U+20B9) is the only
   glyph the site renders that falls outside the latin subset, and it appears
   only in .plan-price on pricing.html. Because it is scoped by unicode-range
   it is fetched by that page alone, exactly as it was under Google.

   Instrument Serif ships a real italic, which the site leans on heavily.
   Archivo does not, and never did here — its italics were always synthesised
   by the browser, and still are.
   ========================================================================== */

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url(../assets/fonts/archivo-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-display: swap;
  src: url(../assets/fonts/archivo-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: 'Instrument Serif';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(../assets/fonts/instrument-serif.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: 'Instrument Serif';
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url(../assets/fonts/instrument-serif-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;
}

/* ==========================================================================
   VYOMATRICS DIGITAL
   Design system & stylesheet

   00  Reset & base
   01  Tokens
   02  Typography system
   03  Layout system
   04  Atmosphere (cosmic field, grid, stars, brand form, grain, lens)
   05  Buttons & links
   06  Header & navigation
   07  Hero
   08  Marquee
   09  Pull quote
   10  Capability
   11  Work
   12  Project screens
   13  Process
   14  Position
   15  Principles
   16  Contact & form
   17  Footer
   18  About page
   19  Services page
   20  Home, Process, Work & Contact pages
   21  Motion & reveal
   22  Responsive
   23  Reduced motion & print
   24  Pricing page
   ========================================================================== */


/* ==========================================================================
   00  RESET & BASE
   ========================================================================== */

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

* { margin: 0; padding: 0; }

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: 120px;
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

body {
  /* The floor of the cosmos. Everything dimensional — haze, glow, stars, the
     brand form — is painted by the fixed .atmos layer in §04 on top of this,
     so the flat colour is only ever seen through them. */
  background: var(--cosmic-black);
  color: var(--fg);
  font-family: var(--f-sans);
  font-size: var(--fs-body);
  font-weight: 400;
  font-stretch: 100%;
  line-height: 1.62;
  letter-spacing: -0.002em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  text-rendering: optimizeLegibility;
}

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

/* Component display values must not out-specify the hidden attribute. */
[hidden] { display: none !important; }

ul, ol { list-style: none; }

a { color: inherit; text-decoration: none; }

button, input, select, textarea {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
}

button { cursor: pointer; }

::selection { background: var(--brand); color: #fff; }

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

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

.skip-link {
  position: fixed;
  top: 12px; left: 12px;
  z-index: 200;
  transform: translateY(-160%);
  padding: 12px 20px;
  background: var(--fg);
  color: var(--ink-0);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  transition: transform 0.24s var(--ease);
}
.skip-link:focus { transform: none; }


/* ==========================================================================
   01  TOKENS
   ========================================================================== */

:root {
  /* --- cosmic ground -----------------------------------------------------
     The site sits inside one continuous dark cosmos, so the ground is a
     single family rather than a per-section choice: a near-black carrying a
     slight blue bias, then surfaces and atmospheres lifted out of it.

     --cosmic-black is the floor and the one value everything resolves to.
     It is published as RGB components as well, because every banner scrim
     has to fade to *exactly* this colour to leave no seam where the artwork
     meets the page — see the note above the hero scrim in §07. Writing it as
     a literal is what created the seam this system exists to remove. */
  --cosmic-black:     #05070B;
  --cosmic-black-rgb: 5, 7, 11;
  --cosmic-deep:      #06080D;

  /* Surfaces — cards and panels lifted just clear of the floor. */
  --cosmic-surface:   #080C13;
  --cosmic-surface-2: #0A0F17;

  /* Atmosphere — the blue in the dark. Used for haze, glows and the tint
     under major sections, never for a solid fill behind text. */
  --cosmic-blue-deep: #071426;
  --cosmic-blue-atmos:#081A30;
  --cosmic-glow:      rgba(61, 123, 255, 0.09);
  --cosmic-border:    rgba(122, 162, 255, 0.10);

  /* --- surface ------------------------------------------------------------
     The same ramp the site has always used, re-seated on the cosmic floor and
     given a blue bias so panels read as cosmic surfaces rather than as grey.
     Darkening the floor only raises contrast against the ink scale below, so
     every measured ratio in §01 holds or improves. */
  --ink-0: var(--cosmic-black);
  --ink-1: var(--cosmic-deep);
  --ink-2: var(--cosmic-surface);
  --ink-3: var(--cosmic-surface-2);
  --ink-4: #101725;
  --ink-5: #182133;

  /* --- ink -------------------------------------------------------------- */
  /* Every tone here is used for real text, so each clears WCAG AA (4.5:1)
     against the darkest surface. --fg-4 was the floor at ~4.7:1 on the old
     #08090B ground and measures ~4.9:1 on the cosmic floor beneath it —
     dropping the ground darkens the backdrop, which can only raise a ratio
     against light text, so nothing here needed re-picking. */
  --fg:   #F5F5F5;
  --fg-2: #BCC1C9;
  --fg-3: #8B9199;
  --fg-4: #757C87;

  /* --- rules ------------------------------------------------------------ */
  --line:   rgba(245, 245, 245, 0.09);
  --line-2: rgba(245, 245, 245, 0.17);
  --line-3: rgba(245, 245, 245, 0.045);

  /* --- accent -----------------------------------------------------------
     --brand is the blue exactly as drawn in the logotype (#0038B0). At 2.1:1
     on near-black it is far too dark for type, so it is reserved for solid
     fills and graphics. --blue is the accessible tint of the same hue (221°)
     and carries every piece of text, link, numeral and hairline accent. */
  --brand:      #0038B0;
  --brand-rgb:  0, 56, 176;
  --blue:       #3D7BFF;   /* 5.2:1 on --ink-0 */
  --blue-lift:  #709DFF;   /* 7.6:1 — hover / emphasis */
  --blue-rgb:   61, 123, 255;
  --blue-deep:  #001E6B;
  --navy:       #06122E;
  --blue-veil:  rgba(61, 123, 255, 0.13);

  /* The cosmic system's accent names, aliased onto the blues already proven
     against this background rather than introducing a second, unmeasured
     blue alongside them. */
  --cosmic-blue:      var(--blue);
  --cosmic-blue-lift: var(--blue-lift);

  /* --- type ------------------------------------------------------------- */
  --f-sans: "Archivo", ui-sans-serif, system-ui, "Segoe UI", sans-serif;
  --f-serif: "Instrument Serif", "Iowan Old Style", "Palatino Linotype", Georgia, serif;

  /* Capped at 7.4rem, not larger: past ~1450px the shell stops widening but a
     vw-based size would not, so the hero's authored lines began to break. */
  --fs-display: clamp(2.85rem, 8.3vw, 7.4rem);
  --fs-h2:      clamp(2.05rem, 4.9vw, 4.35rem);
  --fs-h3:      clamp(1.5rem, 2.7vw, 2.35rem);
  --fs-h4:      clamp(1.16rem, 1.5vw, 1.45rem);
  --fs-lede:    clamp(1.02rem, 1.32vw, 1.28rem);
  --fs-body:    clamp(0.955rem, 0.94vw, 1.05rem);
  --fs-small:   clamp(0.86rem, 0.8vw, 0.92rem);
  --fs-meta:    clamp(0.66rem, 0.68vw, 0.735rem);

  /* --- space ------------------------------------------------------------ */
  --shell-max: 1440px;
  --gutter: clamp(20px, 4.2vw, 72px);
  --sec-pad: clamp(86px, 10.5vw, 176px);
  --stack-1: clamp(10px, 1vw, 14px);
  --stack-2: clamp(18px, 1.8vw, 26px);
  --stack-3: clamp(30px, 3.2vw, 48px);
  --stack-4: clamp(48px, 5.5vw, 88px);

  /* --- motion ----------------------------------------------------------- */
  --ease:     cubic-bezier(0.16, 0.84, 0.44, 1);
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --dur:      0.42s;

  --head-h: 78px;
}


/* ==========================================================================
   02  TYPOGRAPHY SYSTEM
   ========================================================================== */

/* Display / headings -------------------------------------------------------
   Archivo carries the voice: expanded width, heavy weight, tight tracking.
   Instrument Serif italic is reserved for emphasis only. */

.hero-title,
.h2, .h3, .h4 {
  font-family: var(--f-sans);
  font-weight: 700;
  font-stretch: 112%;
  line-height: 0.98;
  letter-spacing: -0.034em;
  color: var(--fg);
  text-wrap: balance;
}

.hero-title {
  font-size: var(--fs-display);
  font-weight: 700;
  line-height: 0.925;
  letter-spacing: -0.042em;
}

.h2 { font-size: var(--fs-h2); line-height: 0.99; letter-spacing: -0.036em; }
.h3 { font-size: var(--fs-h3); line-height: 1.03; letter-spacing: -0.03em; }
.h4 {
  font-size: var(--fs-h4);
  line-height: 1.18;
  letter-spacing: -0.022em;
  font-stretch: 104%;
  font-weight: 600;
}

/* Serif emphasis. Every emphasised word in a heading carries the accent, so the
   device reads the same on every page. */
.hero-title em,
.h2 em, .h3 em, .pull em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  font-stretch: 100%;
  font-size: 1.05em;
  letter-spacing: -0.012em;
  color: var(--blue-lift);
}

/* Eyebrow / metadata ------------------------------------------------------- */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 0.7em;
  font-size: var(--fs-meta);
  font-weight: 500;
  font-stretch: 92%;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fg-3);
  line-height: 1;
}

.eyebrow-tick {
  width: 26px; height: 1px;
  background: var(--blue);
  flex: none;
}

.sec-num {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 1.5em;
  letter-spacing: 0;
  color: var(--fg);
  line-height: 0.8;
  position: relative;
  top: 0.04em;
  padding-right: 0.15em;
}

/* Body --------------------------------------------------------------------- */
/* Art-directed line breaks. Below the tablet breakpoint the headings are
   allowed to find their own measure instead of inheriting desktop breaks. */
@media (max-width: 720px) {
  br.br-lg { display: none; }
}

.lede {
  font-size: var(--fs-lede);
  line-height: 1.5;
  color: var(--fg-2);
  letter-spacing: -0.012em;
  font-weight: 400;
}

p { color: var(--fg-3); }
p strong { color: var(--fg); font-weight: 600; }


/* ==========================================================================
   03  LAYOUT SYSTEM
   ========================================================================== */

.shell {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: var(--shell-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section {
  position: relative;
  z-index: 2;
  padding-block: var(--sec-pad);
}

/* Tonal depth between sections. Translucent so both the column grid and the
   cosmic field in §04 read continuously through them — these tints are the
   only thing that varies as you scroll, since the sky behind them is fixed.

   They were neutral white washes, which on the cosmic ground read as grey
   fog sitting on top of the atmosphere rather than as part of it. Each is now
   a blue at the same weight, so the rhythm between sections is unchanged and
   only its temperature moves. Every one still ends at `transparent`, so no
   section owns a hard edge. */
.capability  { background: linear-gradient(180deg, rgba(var(--blue-rgb), 0.030), rgba(var(--blue-rgb), 0.010) 55%, transparent); }
.work        { background: linear-gradient(180deg, transparent, rgba(8, 26, 48, 0.44) 45%, transparent); }
.process     { background: linear-gradient(180deg, rgba(var(--blue-rgb), 0.026), transparent 70%); }
.principles  { background: linear-gradient(180deg, rgba(var(--blue-rgb), 0.016), rgba(7, 20, 38, 0.38)); }

.section + .section::before {
  content: "";
  position: absolute;
  inset-inline: var(--gutter);
  top: 0;
  height: 1px;
  background: var(--line-3);
  max-width: calc(var(--shell-max) - var(--gutter) * 2);
  margin-inline: auto;
}

/* Section heads ------------------------------------------------------------ */
.section-head { margin-bottom: var(--stack-4); }
.section-head .eyebrow { margin-bottom: var(--stack-2); }
.section-lede { max-width: 46ch; margin-top: var(--stack-2); }

.section-head--split {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: var(--stack-3) clamp(32px, 6vw, 100px);
  align-items: end;
}

.section-head-aside {
  padding-left: clamp(0px, 2vw, 28px);
  border-left: 1px solid var(--line);
  padding-block: 4px;
}
.section-head-aside p { max-width: 42ch; }
.section-head-hint {
  margin-top: var(--stack-2);
  font-size: var(--fs-meta);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--fg-4);
}


/* ==========================================================================
   04  ATMOSPHERE
   ========================================================================== */

/* The whole cosmic environment is painted here, on one fixed layer that every
   page already carries, rather than section by section. Two things follow from
   that, and they are the reason the system works:

   - Because the layer is *fixed*, it does not scroll. There is no seam between
     one section and the next because there is no edge to seam — the same sky
     sits behind the entire document. Section-level depth comes from the
     translucent tints in §03 sliding over it.
   - Because it is one layer with `overflow: hidden` and `pointer-events: none`,
     nothing here can push the page wide or intercept a click, at any width.

   Everything is static: gradients and one rasterised SVG. No animation, no
   video, no image request beyond what the banners already load. */
.atmos {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

/* The brand form ----------------------------------------------------------
   The logotype's leading V, drawn oversized, blurred inside the SVG (so no
   CSS filter is paid for at paint time) and held at an opacity where it reads
   as a shift in the dark rather than as a letter. It is the one element on
   this layer that is recognisably Vyomatrics; it should be felt before it is
   seen, which is why it sits at 0.05 and never over the type column. */
.atmos::before {
  content: "";
  position: absolute;
  top: 8vh;
  right: -6vw;
  width: min(72vw, 880px);
  aspect-ratio: 1;
  opacity: 0.05;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 600'%3E%3Cdefs%3E%3Cfilter id='b' x='-30%25' y='-30%25' width='160%25' height='160%25'%3E%3CfeGaussianBlur stdDeviation='24'/%3E%3C/filter%3E%3ClinearGradient id='g' x1='0' y1='0' x2='0.35' y2='1'%3E%3Cstop offset='0' stop-color='%233D7BFF' stop-opacity='0.95'/%3E%3Cstop offset='1' stop-color='%230038B0' stop-opacity='0.18'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath d='M116 96 L300 476 L484 96 L410 96 L300 334 L190 96 Z' fill='url(%23g)' filter='url(%23b)'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Depth seat --------------------------------------------------------------
   A vignette that pulls the corners down into the dark, so the haze below
   reads as depth rather than as a gradient someone applied to a rectangle. */
.atmos::after {
  content: "";
  position: absolute;
  inset: 0;
  background: radial-gradient(120% 100% at 50% 42%, transparent 42%, rgba(var(--cosmic-black-rgb), 0.55) 100%);
}

/* Persistent hairline column grid — the structural signature of the site.
   The hero repeats it locally so the rules still read over the banner. */
.atmos-grid,
.hero-media-grid {
  position: absolute;
  inset: 0;
  display: flex;
  justify-content: space-between;
  width: min(calc(var(--shell-max) - var(--gutter) * 2), calc(100% - var(--gutter) * 2));
  margin-inline: auto;
}
.atmos-grid i,
.hero-media-grid i {
  width: 1px;
  background: linear-gradient(180deg, transparent, var(--line-3) 8%, var(--line-3) 92%, transparent);
}
.hero-media-grid i {
  background: linear-gradient(180deg, transparent, rgba(245, 245, 245, 0.07) 10%, rgba(245, 245, 245, 0.07) 88%, transparent);
}

/* Nebula and haze ---------------------------------------------------------
   Was a 90vh band pinned to the top of the viewport, which is why the page
   went flat as soon as you scrolled past the hero. It now covers the whole
   viewport and carries the atmosphere for the entire site.

   The first two layers are the original top wash at its original coordinates,
   kept deliberately: every hero on the site was tuned against that light, and
   moving it would have re-lit six pages nobody asked me to touch. Everything
   below it is new, and all of it is far enough down in alpha to read as
   depth rather than as weather. */
.atmos-wash {
  position: absolute;
  inset: 0;
  background:
    /* — the original top wash, unchanged in position and strength — */
    radial-gradient(62% 46% at 78% 8%, rgba(var(--blue-rgb), 0.10), transparent 68%),
    radial-gradient(52% 38% at 12% 0%, rgba(184, 206, 245, 0.040), transparent 70%),
    /* — the counterweight: a deep atmospheric mass low and left — */
    radial-gradient(58% 46% at 6% 78%, rgba(8, 26, 48, 0.58), transparent 72%),
    /* — a faint haze crossing the middle right, so the centre is not empty — */
    radial-gradient(72% 32% at 94% 52%, rgba(var(--blue-rgb), 0.042), transparent 74%),
    /* — and the ground itself, turning very slightly blue toward the foot — */
    linear-gradient(180deg, transparent 38%, rgba(7, 20, 38, 0.46) 100%);
}

/* Stars -------------------------------------------------------------------
   Two tiled layers of soft points at different densities, which is what gives
   the field depth without any parallax work. Each point is a sub-2px radial
   gradient, so the whole sky is one paint of one element and costs no image
   request and no animation frame.

   The tiles are deliberately large and the positions inside them irregular —
   a small tile or an even spread reads immediately as a repeat, which is the
   tell that separates a night sky from a texture. Roughly forty points are
   visible on a 1440-wide screen. */
.atmos-wash::before,
.atmos-wash::after {
  content: "";
  position: absolute;
  inset: 0;
  background-repeat: repeat;
}

/* Nearer layer — slightly brighter, slightly larger, denser tile. */
.atmos-wash::before {
  background-image:
    radial-gradient(1.4px 1.4px at 7% 12%,  rgba(206, 224, 255, 0.50), transparent),
    radial-gradient(1px 1px     at 23% 34%, rgba(180, 205, 255, 0.34), transparent),
    radial-gradient(1.2px 1.2px at 38% 8%,  rgba(214, 230, 255, 0.42), transparent),
    radial-gradient(0.9px 0.9px at 52% 47%, rgba(170, 198, 255, 0.28), transparent),
    radial-gradient(1.3px 1.3px at 61% 19%, rgba(200, 220, 255, 0.46), transparent),
    radial-gradient(1px 1px     at 74% 63%, rgba(176, 202, 255, 0.30), transparent),
    radial-gradient(1.5px 1.5px at 88% 27%, rgba(210, 228, 255, 0.52), transparent),
    radial-gradient(0.9px 0.9px at 94% 71%, rgba(168, 196, 255, 0.26), transparent),
    radial-gradient(1.1px 1.1px at 16% 71%, rgba(192, 214, 255, 0.36), transparent),
    radial-gradient(1px 1px     at 31% 88%, rgba(178, 204, 255, 0.30), transparent),
    radial-gradient(1.2px 1.2px at 45% 66%, rgba(198, 219, 255, 0.38), transparent),
    radial-gradient(0.9px 0.9px at 58% 92%, rgba(166, 194, 255, 0.24), transparent),
    radial-gradient(1.3px 1.3px at 69% 41%, rgba(204, 223, 255, 0.44), transparent),
    radial-gradient(1px 1px     at 81% 84%, rgba(182, 207, 255, 0.28), transparent),
    radial-gradient(1.1px 1.1px at 12% 52%, rgba(190, 213, 255, 0.34), transparent);
  background-size: 820px 640px;
}

/* Further layer — fainter, on a larger tile so it reads as more distant. */
.atmos-wash::after {
  background-image:
    radial-gradient(1px 1px     at 11% 27%, rgba(172, 199, 255, 0.26), transparent),
    radial-gradient(0.8px 0.8px at 29% 61%, rgba(160, 190, 255, 0.20), transparent),
    radial-gradient(1.1px 1.1px at 43% 15%, rgba(184, 208, 255, 0.28), transparent),
    radial-gradient(0.8px 0.8px at 57% 79%, rgba(158, 188, 255, 0.18), transparent),
    radial-gradient(1px 1px     at 66% 36%, rgba(176, 202, 255, 0.24), transparent),
    radial-gradient(1.2px 1.2px at 78% 8%,  rgba(190, 212, 255, 0.30), transparent),
    radial-gradient(0.9px 0.9px at 86% 55%, rgba(164, 192, 255, 0.20), transparent),
    radial-gradient(1px 1px     at 95% 88%, rgba(174, 200, 255, 0.22), transparent),
    radial-gradient(0.8px 0.8px at 20% 91%, rgba(158, 188, 255, 0.18), transparent),
    radial-gradient(1.1px 1.1px at 36% 44%, rgba(182, 206, 255, 0.26), transparent),
    radial-gradient(0.9px 0.9px at 50% 5%,  rgba(168, 196, 255, 0.22), transparent),
    radial-gradient(1px 1px     at 72% 68%, rgba(178, 204, 255, 0.24), transparent),
    radial-gradient(0.8px 0.8px at 91% 21%, rgba(162, 190, 255, 0.18), transparent);
  background-size: 1240px 980px;
}

.atmos-lens {
  position: absolute;
  top: 0; left: 0;
  width: 620px; height: 620px;
  margin: -310px 0 0 -310px;
  background: radial-gradient(circle, rgba(var(--blue-rgb), 0.075), transparent 62%);
  opacity: 0;
  transition: opacity 0.7s var(--ease);
  will-change: transform;
}
.atmos-lens.is-on { opacity: 1; }

.atmos-grain {
  position: absolute;
  inset: 0;
  opacity: 0.05;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* Scroll progress ---------------------------------------------------------- */
.scroll-rail {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 2px;
  z-index: 120;
  pointer-events: none;
}
.scroll-rail span {
  display: block;
  height: 100%;
  width: 100%;
  transform: scaleX(0);
  transform-origin: left;
  background: linear-gradient(90deg, var(--brand), var(--blue));
}


/* ==========================================================================
   05  BUTTONS & LINKS
   ========================================================================== */

.btn {
  --btn-fg: var(--ink-0);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.7em;
  padding: 1.05em 1.7em;
  font-size: var(--fs-small);
  font-weight: 600;
  font-stretch: 96%;
  letter-spacing: 0.02em;
  line-height: 1;
  white-space: nowrap;
  /* Kept for label containment, not for the hover: a nowrap label that
     outgrows its box is clipped rather than allowed to break the layout —
     see the note above .plan-cta in §24. `isolation: isolate` used to sit
     here to trap the wipe's `z-index: -1` inside the button; the wipe is
     gone, so the stacking context it needed went with it. */
  overflow: hidden;

  /* The resting state of the glow, declared rather than left as `none`.
     Interpolating from `none` makes the browser synthesise a zero-state for a
     three-layer shadow on the first frame; declaring the same three layers at
     zero alpha means the hover is a plain per-layer fade with nothing to work
     out, and the geometry never moves. */
  box-shadow:
    0 0 0 1px rgba(var(--blue-rgb), 0),
    0 2px 12px rgba(var(--blue-rgb), 0),
    0 6px 34px rgba(var(--blue-rgb), 0);

  /* No `transform` here on purpose — see the glow note below. */
  transition:
    color 0.32s var(--ease),
    border-color 0.32s var(--ease),
    box-shadow 0.42s var(--ease);
}

/* The electric glow -------------------------------------------------------
   Every call to action lights up in the same blue, so the device means one
   thing wherever it appears.

   --blue rather than --brand: #0038B0 is the logotype colour but it measures
   2.1:1 on near-black, so it has almost no luminance to throw and reads as a
   dark smear. #3D7BFF is the same hue at a brightness that reads as light.

   Three stacked shadows rather than one large blur. The 1px ring defines the
   edge, the mid halo gives it body, and the wide pool is what actually reads
   as glow — a single soft shadow at this button size looks like a smudge, and
   a ring on its own just looks like a second border. The downward offsets on
   the outer two are what stop it reading as a flat sticker.

   This is now the *only* hover treatment a button carries. It used to share
   the job with a wipe that flooded the primary button with --brand from the
   bottom edge up; that has been removed, so every call to action on the site
   answers the pointer the same way — it lights up, it does not change colour.

   THERE IS NO transform HERE, AND THERE MUST NOT BE. A `translateY(-1px)`
   lift used to sit on this rule and it made the hover jitter. The reason is
   worth keeping written down, because the fix looks like a style choice and
   is not: a transform on the hovered element moves that element's own hit
   area. Lifting the button 1px pulls its bottom edge up by 1px, so a pointer
   resting anywhere in that bottom 1px band falls outside, :hover drops, the
   button returns, :hover matches again — a feedback loop that oscillates for
   as long as the pointer sits in the band. Anything that changes the button's
   geometry on hover reintroduces it; colour, shadow and border do not, which
   is why all three are safe and the lift was not.

   The glow itself was measured before being blamed: transitioning these three
   shadows costs a 6.9ms median frame against 7.0ms for an equivalent
   composited opacity fade, with no frame over 20ms in either. Animating
   box-shadow here is not the bottleneck, so it stays on the element rather
   than being moved onto an overlay — which `overflow: hidden` would clip.

   overflow: hidden above clips descendants, not the element's own shadow, so
   the glow escapes the button freely. */
.btn:hover,
.btn:focus-visible {
  box-shadow:
    0 0 0 1px rgba(var(--blue-rgb), 0.45),
    0 2px 12px rgba(var(--blue-rgb), 0.32),
    0 6px 34px rgba(var(--blue-rgb), 0.26);
}

.btn-arrow { transition: transform 0.38s var(--ease-out); flex: none; }
.btn:hover .btn-arrow { transform: translateX(4px); }

/* Primary — solid paper on ink, and it stays that way.
   The label keeps its dark ink on hover: the old rule flipped it to #fff,
   which only worked because the wipe had put a dark blue behind it. Without
   the wipe that same rule would have painted white text onto a white button
   and erased the label, so it goes with it. */
.btn--primary { background: var(--fg); color: var(--ink-0); }

/* Ghost — hairline box. The hairline goes electric on hover so the border and
   the glow's 1px ring read as one edge rather than two concentric lines; that
   is the same blue as the glow, so it is part of the one effect, not a second
   one. The fill that used to grow up from the bottom edge is removed. */
.btn--ghost {
  color: var(--fg);
  border: 1px solid var(--line-2);
}
.btn--ghost:hover,
.btn--ghost:focus-visible { border-color: rgba(var(--blue-rgb), 0.75); }

.btn--sm { padding: 1.1em 1.5em; font-size: var(--fs-meta); letter-spacing: 0.09em; text-transform: uppercase; font-stretch: 92%; }
.btn--block { width: 100%; }

/* Arrow link --------------------------------------------------------------- */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.6em;
  font-size: var(--fs-small);
  font-weight: 600;
  font-stretch: 96%;
  color: var(--fg);
  padding-top: 6px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--line-2);
  transition: color 0.3s var(--ease), border-color 0.3s var(--ease);
}
.link-arrow svg { transition: transform 0.38s var(--ease-out); }
.link-arrow:hover { color: var(--blue-lift); border-color: var(--blue); }
.link-arrow:hover svg { transform: translateX(4px); }


/* ==========================================================================
   06  HEADER & NAVIGATION
   ========================================================================== */

.site-head {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  transition: background 0.4s var(--ease), backdrop-filter 0.4s var(--ease), border-color 0.4s var(--ease);
  border-bottom: 1px solid transparent;
}

/* The header belongs to the environment rather than sitting on top of it: a
   translucent pour of the cosmic ground with a faint blue lift, blurred so
   the sky and the stars behind it stay legible as they pass underneath. */
.site-head.is-stuck {
  background:
    linear-gradient(180deg, rgba(var(--blue-rgb), 0.030), transparent),
    rgba(var(--cosmic-black-rgb), 0.72);
  backdrop-filter: saturate(150%) blur(16px);
  -webkit-backdrop-filter: saturate(150%) blur(16px);
  border-bottom-color: var(--line);
}

.head-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(16px, 3vw, 48px);
  height: var(--head-h);
  transition: height 0.4s var(--ease);
}
.site-head.is-stuck .head-inner { height: 64px; }

/* Brand -------------------------------------------------------------------- */
/* Brand lockup — the logotype as supplied, with the descriptor set beneath in
   the interface face and tracked out to the wordmark's width.
   Small text links carry vertical padding purely to keep their hit area at or
   above the 24px minimum without changing how they look. */
.brand {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  flex: none;
  padding-block: 5px;
}
.brand-logo {
  display: block;
  width: auto;
  height: 17px;
  transition: height 0.4s var(--ease), opacity 0.35s var(--ease), transform 0.5s var(--ease-out);
}
.site-head.is-stuck .brand-logo { height: 15px; }
.brand:hover .brand-logo { opacity: 0.82; transform: translateY(-1px); }

.brand-sub {
  font-size: 0.56rem;
  font-weight: 500;
  font-stretch: 88%;
  letter-spacing: 0.4em;
  text-indent: 0.4em;
  text-transform: uppercase;
  color: var(--fg-3);
  line-height: 1;
  transition: color 0.35s var(--ease);
}
.brand:hover .brand-sub { color: var(--fg-2); }

/* Desktop nav -------------------------------------------------------------- */
.nav-desktop ul {
  display: flex;
  align-items: center;
  gap: clamp(20px, 2.4vw, 38px);
}
.nav-desktop a {
  position: relative;
  display: block;
  padding: 6px 0;
  font-size: var(--fs-meta);
  font-weight: 500;
  font-stretch: 92%;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-3);
  transition: color 0.28s var(--ease);
}
.nav-desktop a::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--blue);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 0.4s var(--ease-out);
}
.nav-desktop a:hover { color: var(--fg); }
.nav-desktop a:hover::after { transform: none; transform-origin: left; }

.head-actions { display: flex; align-items: center; gap: 14px; flex: none; }

/* Toggle ------------------------------------------------------------------- */
.nav-toggle {
  display: none;
  align-items: center;
  gap: 10px;
  padding: 10px 0 10px 4px;
  color: var(--fg);
}
.nav-toggle-box { position: relative; width: 24px; height: 12px; display: block; }
.nav-toggle-box i {
  position: absolute;
  left: 0;
  width: 100%; height: 1.5px;
  background: currentColor;
  transition: transform 0.4s var(--ease-out), width 0.4s var(--ease-out);
}
.nav-toggle-box i:first-child { top: 0; }
.nav-toggle-box i:last-child { bottom: 0; width: 62%; }
.nav-toggle[aria-expanded="true"] .nav-toggle-box i:first-child { transform: translateY(5.25px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-box i:last-child { width: 100%; transform: translateY(-5.25px) rotate(-45deg); }
.nav-toggle-label {
  font-size: var(--fs-meta);
  font-weight: 500;
  font-stretch: 92%;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

/* Mobile panel ------------------------------------------------------------- */
/* The panel is opaque and covers the fixed .atmos layer entirely, so it would
   otherwise be the one full-screen surface on the site with no atmosphere in
   it. It carries its own quiet version instead: the same top-right blue the
   sky uses, over the cosmic ground. */
.mobile-nav {
  position: fixed;
  inset: 0;
  z-index: 95;
  background:
    radial-gradient(78% 52% at 82% 6%, rgba(var(--blue-rgb), 0.10), transparent 70%),
    radial-gradient(64% 44% at 8% 92%, rgba(8, 26, 48, 0.62), transparent 74%),
    var(--cosmic-deep);
  visibility: hidden;
  opacity: 0;
  transition: opacity 0.4s var(--ease), visibility 0s linear 0.4s;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.mobile-nav.is-open {
  visibility: visible;
  opacity: 1;
  transition: opacity 0.4s var(--ease), visibility 0s;
}
.mobile-nav-inner {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  padding: calc(var(--head-h) + 34px) var(--gutter) 40px;
}
.mobile-nav-eyebrow { margin-bottom: 26px; }

.mobile-nav-list { border-top: 1px solid var(--line); }
.mobile-nav-list li { border-bottom: 1px solid var(--line); }
.mobile-nav-list a {
  display: flex;
  align-items: baseline;
  gap: 16px;
  padding: 20px 0;
  font-size: clamp(1.75rem, 8vw, 2.5rem);
  font-weight: 700;
  font-stretch: 108%;
  letter-spacing: -0.032em;
  line-height: 1;
  opacity: 0;
  transform: translateY(14px);
}
.mobile-nav.is-open .mobile-nav-list a {
  opacity: 1;
  transform: none;
  transition: opacity 0.5s var(--ease) var(--d, 0ms), transform 0.5s var(--ease-out) var(--d, 0ms);
}
.mn-idx {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  font-size: 0.85rem;
  letter-spacing: 0;
  color: var(--fg-4);
}
.mobile-nav-list a:hover { color: var(--blue-lift); }

.mobile-nav-foot { margin-top: auto; padding-top: 44px; }
.mobile-nav-mail {
  display: block;
  margin-top: 22px;
  font-size: var(--fs-small);
  color: var(--fg-2);
  border-bottom: 1px solid var(--line-2);
  padding-top: 5px;
  padding-bottom: 4px;
  width: fit-content;
}
.mobile-nav-social {
  display: flex;
  gap: 22px;
  margin-top: 22px;
  font-size: var(--fs-meta);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--fg-3);
}
.mobile-nav-social a { display: inline-block; padding-block: 7px; }
.mobile-nav-social a:hover { color: var(--fg); }

body.is-locked { overflow: hidden; }


/* ==========================================================================
   07  HERO
   ========================================================================== */

.hero {
  position: relative;
  z-index: 2;
  padding-top: calc(var(--head-h) + clamp(48px, 6.4vw, 88px));
  padding-bottom: clamp(22px, 2.6vw, 34px);
  min-height: min(100svh, 1000px);
  display: flex;
  flex-direction: column;
  justify-content: center;
}

/* Banner layer ------------------------------------------------------------
   The artwork runs unmirrored, as drawn: planet and limb-glow at the left,
   circuit tracery at the right. An earlier version flipped it horizontally to
   move the planet off the headline, which also buried the tracery under the
   darkest part of the scrim - the scrim does that job on its own.

   Two scrims sit over it. The horizontal one protects the type column and so
   stays heavy on the left, then falls away to near-clear by the right edge so
   the tracery reads instead of being flattened to black. The vertical one
   fades the image into the page above and below. */
.hero-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
.hero-media img {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  opacity: 0.92;
}
.hero-media::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(97deg, rgba(var(--cosmic-black-rgb), 0.94) 12%, rgba(var(--cosmic-black-rgb), 0.78) 38%, rgba(var(--cosmic-black-rgb), 0.34) 66%, rgba(var(--cosmic-black-rgb), 0.40) 78%, rgba(var(--cosmic-black-rgb), 0.62) 100%),
    linear-gradient(180deg, rgba(var(--cosmic-black-rgb), 0.9) 0%, rgba(var(--cosmic-black-rgb), 0.16) 26%, rgba(var(--cosmic-black-rgb), 0.18) 58%, var(--ink-0) 97%);
}
.hero-media-grid { z-index: 2; }

.hero-shell {
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(200px, 19vw, 268px);
  gap: clamp(32px, 5vw, 84px);
  align-items: start;
  flex: 1;
  align-content: center;
}

.hero-eyebrow { margin-bottom: clamp(20px, 2.3vw, 32px); }

.hero-title { margin-bottom: clamp(26px, 2.8vw, 42px); }
/* The mask needs overflow:hidden for the entrance animation, which means the
   clip box must clear the deepest ink in the line — not the deepest layout
   box. Those are different numbers, and the gap between them is what shows.

   Measured with canvas actualBoundingBoxDescent against an inline baseline
   probe, at the rendered display size: the serif italic descenders (g j y J Q)
   drop 0.2195em of their own size, and the <em> runs at 1.05em, so 0.2305em of
   the line's size. Roughly 0.10em of that falls past the content box.

   0.14em covered that arithmetically and still clipped. It left 3.6px of real
   clearance on 87px type — 0.04em on home's "beyond.", 0.059em on work's
   "possible." At that margin the padding box rounds to a device pixel and the
   antialiased edge of a thin italic tail lands outside it, which is how the
   'y' of "beyond." lost its tail in Chrome while measuring as clear. 0.26em
   leaves ~0.16em, which survives rounding at any zoom or DPR.

   The same applies horizontally: overflow:hidden clips at the padding box, so
   any glyph whose ink starts left of its own origin loses that sliver. Worst
   is the 'p' of work's "possible." at 0.1195em, which 0.18em cleared by only
   0.069em. 0.26em gives it the headroom the descender now has, and stays well
   inside --gutter at every width (11px against a 20px gutter at 375, 30px
   against 72px at 1920), so nothing can reach the viewport edge.

   Both negative margins cancel their padding in effect — bottom keeps the same
   +0.04em residual the line rhythm already had, left cancels outright — so no
   type moves a pixel. Only the clip box grows. Width is unaffected: with auto
   width the two cancel, so the authored line breaks are untouched. */
.hero-title .line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.26em;
  margin-bottom: -0.22em;
  padding-left: 0.26em;
  margin-left: -0.26em;
}
.hero-title .line-in { display: block; }

.hero-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(22px, 2.4vw, 32px);
  max-width: 62ch;
}
.hero-body .lede { max-width: 44ch; }

.hero-actions { display: flex; flex-wrap: wrap; gap: 12px; }

/* Index column ------------------------------------------------------------- */
.hero-index {
  border-top: 1px solid var(--line-2);
  padding-top: 16px;
}
.hero-index .eyebrow { margin-bottom: 18px; }
.hero-index-list { display: grid; gap: 1px; }
.hero-index-list li {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line-3);
  font-size: var(--fs-small);
  font-weight: 500;
}
.hero-index-list span {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 0.8rem;
  color: var(--blue);
  min-width: 1.4em;
}
.hero-index-list a { display: inline-block; padding-block: 2px; color: var(--fg-2); transition: color 0.26s var(--ease); }
.hero-index-list a:hover { color: var(--fg); }
.hero-index-note {
  margin-top: 20px;
  font-size: var(--fs-meta);
  line-height: 1.62;
  letter-spacing: 0.01em;
  text-transform: none;
  /* Lifted twice now. It sits at 77-95% of the hero, directly over the
     brightest tracery in the artwork, where measurement put --fg-3 at 4.38:1
     against the composited backdrop. --fg-2 restores it to 7.69:1 without
     darkening the scrim over the tracery itself. */
  color: var(--fg-2);
}

/* Hero foot ---------------------------------------------------------------- */
.hero-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
  padding-top: clamp(20px, 2.2vw, 30px);
  margin-top: clamp(22px, 2.4vw, 34px);
  border-top: 1px solid var(--line);
}
.hero-foot p,
.hero-foot a {
  font-size: var(--fs-meta);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--fg-4);
  line-height: 1;
}
.hero-foot-mail a {
  display: inline-block;
  padding-block: 7px;
  color: var(--fg-3);
  transition: color 0.26s var(--ease);
}
.hero-foot-mail a:hover { color: var(--blue-lift); }

.scroll-cue {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding-block: 8px;
  color: var(--fg-3);
}
.scroll-cue-line {
  position: relative;
  width: 44px; height: 1px;
  background: var(--line-2);
  overflow: hidden;
  flex: none;
}
.scroll-cue-line::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--blue);
  transform-origin: left;
  animation: cue 2.6s var(--ease) infinite;
}
@keyframes cue {
  0%   { transform: scaleX(0); transform-origin: left; }
  45%  { transform: scaleX(1); transform-origin: left; }
  55%  { transform: scaleX(1); transform-origin: right; }
  100% { transform: scaleX(0); transform-origin: right; }
}
.scroll-cue:hover { color: var(--fg); }


/* ==========================================================================
   08  MARQUEE
   ========================================================================== */

.marquee {
  position: relative;
  z-index: 2;
  overflow: hidden;
  border-block: 1px solid var(--line);
  padding-block: clamp(14px, 1.6vw, 22px);
  background: rgba(var(--blue-rgb), 0.024);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
/* Shift by one of the three sets so the loop is seamless and the remaining
   two always overflow the viewport, however wide the display is. */
.marquee-track { display: flex; width: max-content; animation: slide 69s linear infinite; }
.marquee-set { display: flex; align-items: center; flex: none; }
.marquee-set span {
  padding-inline: clamp(16px, 2vw, 30px);
  font-size: var(--fs-meta);
  font-weight: 500;
  font-stretch: 92%;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fg-3);
  white-space: nowrap;
}
.marquee-set i { width: 3px; height: 3px; background: var(--blue); flex: none; }
@keyframes slide { to { transform: translateX(-33.3333%); } }
.marquee:hover .marquee-track { animation-play-state: paused; }


/* ==========================================================================
   09  PULL QUOTE
   ========================================================================== */

/* The .premise-* grid that opened this section was removed: it belonged to the
   single-page build and no markup has used it since the site became six pages.
   .pull below is still used on About and Services. */
.pull {
  margin-top: var(--stack-4);
  padding: clamp(30px, 4vw, 56px) 0 0;
  border-top: 1px solid var(--line);
}
.pull p {
  font-family: var(--f-sans);
  font-weight: 600;
  font-stretch: 108%;
  font-size: clamp(1.4rem, 3.1vw, 2.6rem);
  line-height: 1.16;
  letter-spacing: -0.03em;
  color: var(--fg);
  max-width: 26ch;
  text-wrap: balance;
}


/* ==========================================================================
   10  CAPABILITY
   ========================================================================== */

.cap { display: grid; gap: clamp(44px, 5vw, 76px); }

.cap-group-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  padding-bottom: 16px;
  margin-bottom: 4px;
}
.cap-group-title {
  font-size: clamp(1.02rem, 1.15vw, 1.16rem);
  font-weight: 600;
  font-stretch: 100%;
  letter-spacing: -0.012em;
  color: var(--fg);
}
.cap-group-note {
  font-size: var(--fs-meta);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--fg-4);
}

.cap-list { border-top: 1px solid var(--line-2); }
.cap-item { border-bottom: 1px solid var(--line); }
.cap-heading { font: inherit; margin: 0; }

.cap-trigger {
  position: relative;
  display: grid;
  grid-template-columns: clamp(46px, 5vw, 74px) minmax(0, 1fr) minmax(0, 0.85fr) 28px;
  align-items: center;
  gap: 16px;
  width: 100%;
  padding: clamp(18px, 2vw, 26px) 0;
  text-align: left;
  color: var(--fg);
  transition: color 0.3s var(--ease);
}
.cap-trigger::before {
  content: "";
  position: absolute;
  inset: 0 -16px;
  background: rgba(var(--blue-rgb), 0.040);
  opacity: 0;
  transition: opacity 0.34s var(--ease);
  z-index: -1;
}
.cap-trigger:hover::before,
.cap-trigger[aria-expanded="true"]::before { opacity: 1; }

.cap-num {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 0.95rem;
  color: var(--fg-4);
  transition: color 0.3s var(--ease), transform 0.5s var(--ease-out);
}
.cap-trigger:hover .cap-num,
.cap-trigger[aria-expanded="true"] .cap-num { color: var(--blue); }

.cap-name {
  font-size: clamp(1.16rem, 2.05vw, 1.85rem);
  font-weight: 600;
  font-stretch: 106%;
  letter-spacing: -0.028em;
  line-height: 1.1;
  transition: transform 0.5s var(--ease-out);
}
.cap-trigger:hover .cap-name { transform: translateX(8px); }

.cap-teaser {
  font-size: var(--fs-small);
  color: var(--fg-4);
  line-height: 1.4;
  transition: color 0.3s var(--ease);
}
.cap-trigger:hover .cap-teaser { color: var(--fg-3); }

.cap-icon {
  position: relative;
  justify-self: end;
  width: 13px; height: 13px;
  flex: none;
}
.cap-icon::before,
.cap-icon::after {
  content: "";
  position: absolute;
  background: currentColor;
  transition: transform 0.44s var(--ease-out), opacity 0.3s var(--ease);
}
.cap-icon::before { top: 6px; left: 0; width: 13px; height: 1px; }
.cap-icon::after  { left: 6px; top: 0; width: 1px; height: 13px; }
.cap-trigger[aria-expanded="true"] .cap-icon::after { transform: scaleY(0); }
.cap-trigger[aria-expanded="true"] .cap-icon { color: var(--blue); }

/* Panel.
   The collapsed state is scoped to `.js` so that without scripting every
   panel renders open and readable rather than clipped to zero height. */
.cap-panel { display: grid; grid-template-rows: auto; }
.cap-panel-in {
  overflow: hidden;
  padding-left: clamp(46px, 5vw, 74px);
  padding-bottom: clamp(22px, 2.4vw, 34px);
}
.cap-panel-in p { max-width: 58ch; }

.js .cap-panel {
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.5s var(--ease-out);
}
.js .cap-panel.is-open { grid-template-rows: 1fr; }
.js .cap-panel-in { padding-bottom: 0; }
.js .cap-panel.is-open .cap-panel-in { padding-bottom: clamp(22px, 2.4vw, 34px); }
.js .cap-panel-in > * {
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.4s var(--ease) 0.1s, transform 0.4s var(--ease-out) 0.1s;
}
.js .cap-panel.is-open .cap-panel-in > * { opacity: 1; transform: none; }

.cap-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 18px;
}
.cap-tags li {
  padding: 7px 13px;
  border: 1px solid var(--line);
  font-size: var(--fs-meta);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--fg-3);
}


/* ==========================================================================
   11  WORK
   ========================================================================== */

.w-meta {
  display: flex;
  align-items: baseline;
  gap: 12px;
  font-size: var(--fs-meta);
  font-weight: 500;
  font-stretch: 92%;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fg-3);
  margin-bottom: var(--stack-2);
}
.w-num {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 1.55em;
  letter-spacing: 0;
  color: var(--blue);
  text-transform: none;
}

.w-title { margin-bottom: var(--stack-2); }
.w-brief { max-width: 46ch; margin-bottom: var(--stack-2); }

/* .w-list was the old per-tile discipline list; the tiles have carried
   .w-disc alone since Work was rebuilt as case studies. */
.w-disc {
  font-size: var(--fs-meta);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--fg-4);
}

/* The grid ----------------------------------------------------------------
   One tile, repeated. Earlier this section ran four bespoke compositions —
   feature, pair, wide, band — which read as eight one-off layouts and made
   whichever project had the smallest capture set look like an apology. Every
   project now gets the same frame at the same ratio, in the same column, so
   the set reads as a considered body of work. */

.w-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(52px, 6vw, 96px) clamp(28px, 3.4vw, 60px);
}

/* The homepage runs its three previews across in one row — a strip, read at a
   glance, deliberately not the Work page's two-across reading grid. It drops
   straight to one column at 900 rather than 720, because three tiles never
   divide into two without orphaning one. */
.w-grid--preview { grid-template-columns: repeat(3, minmax(0, 1fr)); }

/* Frame on its own row, body filling the rest, so the two tiles in a row end
   on the same line however differently their copy runs. */
.w-tile { display: grid; grid-template-rows: auto 1fr; }

.w-body {
  padding-top: var(--stack-3);
  display: flex;
  flex-direction: column;
}
.w-body .w-meta { margin-bottom: 14px; }
.w-body .w-brief { max-width: none; }

.w-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px 20px;
  margin-top: auto;
  padding-top: var(--stack-2);
  border-top: 1px solid var(--line);
}
.w-foot .w-disc { text-align: right; }
.w-view { flex: none; }

/* Concept case studies ----------------------------------------------------
   The Work page presents each concept as a small case study rather than a
   tile: head, desktop preview, then the responsive preview alongside the
   design notes. The .w-tile grid above still serves the homepage preview.

   SHARPNESS IS THE CONSTRAINT HERE. The source captures top out at 1120px
   (desktop) and 760px (mobile), and each one is a composite of two full
   pages, so its detail is already dense. Both figures are therefore capped
   at their source width and never upscaled, and neither is cropped: the
   images run at natural aspect with width:100%/height:auto, which means no
   object-fit is involved at all and nothing can distort. On a display wider
   than the cap the surplus becomes margin — deliberate whitespace, not a
   stretched screenshot.

   No filters, tints, gradients or overlays touch the captures. The only
   treatment is a hairline border and a shadow that sits behind them. */

.cw-set { display: grid; gap: clamp(100px, 12vw, 200px); }

.cw { display: grid; gap: clamp(26px, 3vw, 44px); }

/* Head --------------------------------------------------------------------- */
.cw-head {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: var(--stack-2) clamp(32px, 6vw, 96px);
  align-items: end;
  border-top: 1px solid var(--line-2);
  padding-top: var(--stack-2);
}
.cw-idx {
  display: flex;
  align-items: baseline;
  gap: 14px;
  margin-bottom: 14px;
}
.cw-name {
  font-family: var(--f-sans);
  font-weight: 700;
  font-stretch: 110%;
  font-size: clamp(1.9rem, 3.6vw, 3.1rem);
  line-height: 1;
  letter-spacing: -0.034em;
  color: var(--fg);
}
.cw-sector {
  margin-top: 12px;
  font-size: var(--fs-meta);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--fg-4);
}
.cw-desc { max-width: 52ch; padding-bottom: 4px; }

/* The lead project carries the extra weight, so the set opens rather than
   simply starting. */
.cw--lead .cw-name { font-size: clamp(2.3rem, 4.6vw, 4rem); }
.cw--lead .cw-desc { font-size: var(--fs-lede); line-height: 1.5; color: var(--fg-2); letter-spacing: -0.012em; }
.cw--lead .cw-head { border-top-color: var(--blue); }

/* Figures ------------------------------------------------------------------ */
.cw-fig { margin: 0; display: grid; gap: 14px; }

.cw-cap {
  display: flex;
  align-items: center;
  gap: 0.7em;
  font-size: var(--fs-meta);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--fg-3);
  line-height: 1;
}
.cw-cap::before {
  content: "";
  width: 22px; height: 1px;
  background: var(--blue);
  flex: none;
}

.cw-shot {
  border: 1px solid var(--line);
  background: var(--ink-2);
  box-shadow: 0 22px 56px rgba(0, 0, 0, 0.42);
  transition:
    transform 0.7s var(--ease-out),
    border-color 0.5s var(--ease),
    box-shadow 0.7s var(--ease);
}
/* No object-fit, no fixed ratio box: the intrinsic size governs, so the
   capture cannot be cropped or stretched by the layout. */
.cw-shot img { display: block; width: 100%; height: auto; }

/* The composite is the desktop rendering; its two single-page halves sit
   beside it in the markup and stay out of the way until §11's phone block
   swaps them in.

   Scoped to .cw-shot rather than written as a bare .cw-part: the rule above
   is .cw-shot img at 0,1,1, which out-specifies a lone class and would leave
   both halves painted under the composite at every width. */
.cw-shot .cw-part { display: none; }

/* Movement only — scaling the image would crop it against the frame and
   soften it at the same time. */
.cw-fig:hover .cw-shot,
.cw-fig:focus-within .cw-shot {
  transform: translateY(-5px);
  border-color: var(--line-2);
  box-shadow: 0 34px 80px rgba(0, 0, 0, 0.55);
}

.cw-desktop { max-width: 1120px; }   /* = source width */
.cw-mobile  { max-width: 760px; }    /* = source width */

/* Lower row: the responsive preview reads beside the notes, so the phones
   are obviously the same site rather than a separate exhibit. */
.cw-lower {
  display: grid;
  grid-template-columns: minmax(0, 1.04fr) minmax(0, 0.96fr);
  gap: clamp(28px, 4vw, 68px);
  align-items: start;
}
/* Alternating sides stop eight projects reading as one repeated block. The
   ratios swap with the order so the responsive preview keeps the wider
   column either way — the position alternates, the image size does not. */
.cw--flip .cw-lower { grid-template-columns: minmax(0, 0.96fr) minmax(0, 1.04fr); }
.cw--flip .cw-mobile { order: 2; }
.cw--flip .cw-notes  { order: 1; }

/* Where only the desktop concept was captured, the notes take the width
   rather than leaving a hole beside them. */
.cw--solo .cw-lower { grid-template-columns: minmax(0, 1fr); }
.cw--solo .cw-notes { columns: 2; column-gap: clamp(28px, 4vw, 68px); }
.cw--solo .cw-note  { break-inside: avoid; }

/* Notes -------------------------------------------------------------------- */
.cw-notes { border-top: 1px solid var(--line); }
.cw-note {
  padding: clamp(13px, 1.5vw, 18px) 0;
  border-bottom: 1px solid var(--line-3);
}
.cw-note dt {
  font-size: var(--fs-meta);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--blue-lift);
  margin-bottom: 8px;
}
.cw-note dd { font-size: var(--fs-small); color: var(--fg-2); max-width: 52ch; }

.cw-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px 22px;
  margin-top: var(--stack-2);
}

/* Concept work: responsive ------------------------------------------------- */
@media (max-width: 1024px) {
  .cw-head { grid-template-columns: minmax(0, 1fr); align-items: start; }
  .cw-desc { max-width: 60ch; }
  /* Desktop preview first, responsive preview under it, both full width and
     both still capped at their source size.

     .cw--flip must be named here too: it sets its own two-column ratio at
     0,2,0 specificity, and a media query contributes none — so a bare
     .cw-lower rule loses to it and the flipped concepts would stay in two
     columns all the way down to 320. */
  .cw-lower,
  .cw--flip .cw-lower { grid-template-columns: minmax(0, 1fr); gap: clamp(26px, 4vw, 44px); }
  .cw--flip .cw-mobile { order: 0; }
  .cw--flip .cw-notes  { order: 0; }
  .cw--solo .cw-notes { columns: 2; }
}

@media (max-width: 720px) {
  /* The phones are the point of this figure, so it takes the full column
     rather than shrinking to sit politely in a grid. */
  .cw-mobile { max-width: none; }
  .cw--solo .cw-notes { columns: 1; }
  .cw-foot { flex-direction: column; align-items: stretch; }
  .cw-foot .btn { width: 100%; }
  .cw-shot { box-shadow: 0 14px 36px rgba(0, 0, 0, 0.4); }
}


/* --- The phone split -----------------------------------------------------
   Every capture is a composite: one JPEG holding two page designs side by
   side. That is baked into the pixels, so no grid, width, flex or overflow
   rule can separate them. Measured at 375px, the chain from <img> up through
   .cw-shot, .cw-fig, .cw and .cw-set to .shell is already a single column at
   every level — the page still reads as two columns because the *image* is
   two columns, and each design was landing at ~159px.

   So every composite also exists as two single-page files, cut at the gutter
   measured in the source, and below 768 the composite is swapped for the
   pair. Both sets are loading="lazy", and a display:none image never
   intersects the viewport, so it is never fetched: desktop pulls only
   composites, phones only halves. Nothing above 768 changes.

   Written as .cw-shot.cw-shot--split rather than .cw-shot--split, and placed
   after the 720 block above, for the reason .cw--flip documents further up:
   that block restates .cw-shot at 0,1,0 and would otherwise put the frame's
   shadow back around a wrapper that is no longer the frame. */

@media (max-width: 768px) {
  /* The wrapper stops being the frame and becomes the stack; each half
     carries the frame instead, so two previews read as two previews rather
     than as one box with a seam down the middle. */
  .cw-shot.cw-shot--split {
    display: grid;
    gap: clamp(14px, 3vw, 22px);
    border: 0;
    background: none;
    box-shadow: none;
  }
  .cw-shot--split .cw-full { display: none; }
  .cw-shot--split .cw-part {
    display: block;
    width: 100%;
    height: auto;
    max-width: 100%;
    border: 1px solid var(--line);
    background: var(--ink-2);
    box-shadow: 0 14px 36px rgba(0, 0, 0, 0.4);
  }
}


/* Outro -------------------------------------------------------------------- */
.work-outro {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 20px;
  margin-top: clamp(56px, 6vw, 96px);
  padding-top: var(--stack-3);
  border-top: 1px solid var(--line);
}
.work-outro p {
  font-size: var(--fs-lede);
  color: var(--fg-2);
  letter-spacing: -0.012em;
  max-width: 44ch;
}


/* ==========================================================================
   12  PROJECT FRAMES & THE BIGGER VIEW
   ========================================================================== */

/* The homepage preview sits each capture in a fixed 3:2 window and covers it
   in, so the three tiles align whatever the source ratio happens to be. Every
   desktop capture is currently exactly 3:2, so nothing is actually cropped —
   the cover is insurance against a future capture that is not. Anchoring to
   the top keeps a mockup's header in frame if one ever is.

   The Work page does not use this: there the captures run at natural aspect
   with no crop box at all. See §11. */

.w-frame {
  position: relative;
  overflow: hidden;
  aspect-ratio: 3 / 2;
  border: 1px solid var(--line);
  background: var(--ink-2);
  transition: border-color 0.6s var(--ease);
}
.w-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 0;
  /* Slow on purpose. A page of screenshots that all lurch on hover is noise;
     at 1.6s it reads as the image settling toward you. */
  transition: transform 1.6s cubic-bezier(0.16, 0.84, 0.44, 1);
}

/* A hairline sheen keeps bright screenshots from sitting flat on the dark page. */
.w-frame::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  box-shadow: inset 0 0 0 1px rgba(var(--cosmic-black-rgb), 0.45);
}

/* focus-within so the zoom also answers a keyboard user tabbing to the
   tile's View project button. */
.w-tile:hover .w-frame,
.w-tile:focus-within .w-frame { border-color: var(--line-2); }
.w-tile:hover .w-frame img,
.w-tile:focus-within .w-frame img { transform: scale(1.06); }


/* --- The bigger view -----------------------------------------------------
   One overlay per page, filled from whichever button opened it, so eight
   projects cost one dialog rather than eight hidden copies of the markup. */

.lb {
  position: fixed;
  inset: 0;
  z-index: 130;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(10px, 3vw, 40px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.4s var(--ease), visibility 0s linear 0.4s;
}
.lb.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.4s var(--ease), visibility 0s;
}

.lb-scrim {
  position: absolute;
  inset: 0;
  width: 100%;
  background: rgba(var(--cosmic-black-rgb), 0.93);
  backdrop-filter: blur(7px);
  -webkit-backdrop-filter: blur(7px);
  cursor: zoom-out;
}

.lb-panel {
  position: relative;
  z-index: 1;
  width: min(1180px, 100%);
  max-height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--ink-1);
  border: 1px solid var(--line-2);
  transform: translateY(16px) scale(0.992);
  transition: transform 0.5s var(--ease-out);
}
.lb.is-open .lb-panel { transform: none; }

.lb-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  flex: none;
  padding: clamp(18px, 2.2vw, 28px) clamp(18px, 2.4vw, 32px);
  border-bottom: 1px solid var(--line);
}
.lb-meta { margin-bottom: 11px; }

.lb-close {
  width: 42px; height: 42px;
  flex: none;
  display: grid;
  place-items: center;
  border: 1px solid var(--line-2);
  color: var(--fg-2);
  transition: color 0.3s var(--ease), border-color 0.3s var(--ease);
}
.lb-close:hover { color: var(--fg); border-color: var(--blue); }

.lb-body {
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: clamp(18px, 2.4vw, 32px);
}
.lb-shots {
  display: grid;
  grid-template-columns: minmax(0, 1.62fr) minmax(0, 1fr);
  gap: clamp(14px, 1.8vw, 26px);
  align-items: start;
}
/* A concept captured on desktop only runs full width rather than leaving a
   hole where a phone would have been. */
.lb-shots--single { grid-template-columns: minmax(0, 1fr); }

.lb-shot {
  position: relative;
  border: 1px solid var(--line);
  background: var(--ink-2);
}
.lb-shot img { display: block; width: 100%; height: auto; }
.lb-cap {
  margin-top: 11px;
  font-size: var(--fs-meta);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--fg-4);
}

.lb-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex: none;
  padding: clamp(14px, 1.8vw, 22px) clamp(18px, 2.4vw, 32px);
  border-top: 1px solid var(--line);
}
.lb-count {
  font-size: var(--fs-meta);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--fg-4);
}
.lb-nav { border-bottom-color: var(--line); }
.lb-nav svg { flex: none; }
.lb-nav--prev svg { transform: scaleX(-1); }
.lb-nav--prev:hover svg { transform: scaleX(-1) translateX(4px); }


/* ==========================================================================
   13  PROCESS
   ========================================================================== */

.proc { position: relative; padding-left: clamp(0px, 3vw, 44px); }

.proc-rail {
  position: absolute;
  left: 0; top: 6px; bottom: 6px;
  width: 1px;
  background: var(--line);
}
.proc-progress {
  display: block;
  width: 100%;
  height: 0;
  background: linear-gradient(180deg, var(--blue), var(--brand));
  transition: height 0.15s linear;
}

.proc-list { display: grid; }

.proc-step {
  display: grid;
  grid-template-columns: clamp(72px, 9vw, 150px) minmax(0, 1fr);
  gap: clamp(18px, 3vw, 56px);
  padding-block: clamp(28px, 3.4vw, 48px);
  border-bottom: 1px solid var(--line);
  position: relative;
}
.proc-step:first-child { border-top: 1px solid var(--line-2); }

.proc-num {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.4rem, 5.2vw, 4.6rem);
  line-height: 0.85;
  color: var(--fg-4);
  letter-spacing: -0.01em;
  transition: color 0.5s var(--ease);
}
.proc-step.is-active .proc-num { color: var(--blue); }

.proc-body { max-width: 62ch; }
.proc-body .h4 { margin-bottom: 12px; }
.proc-body p + p { margin-top: 14px; }

.proc-out {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
  font-size: var(--fs-meta);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--fg-4);
}
.proc-out span {
  padding: 4px 9px;
  border: 1px solid var(--line);
  color: var(--fg-3);
  letter-spacing: 0.18em;
}


/* ==========================================================================
   14  POSITION
   ========================================================================== */

/* .pos-top / .pos-lead / .pos-copy were removed with the single-page build.
   Everything below is still in use on About. */
.pos-belief {
  margin-top: var(--stack-4);
  border-top: 1px solid var(--line-2);
  padding-top: var(--stack-3);
}
.pos-belief-label { margin-bottom: var(--stack-2); }
.pos-belief-lead { max-width: 62ch; margin-bottom: var(--stack-3); }

.belief-list { display: grid; }
.belief-list li {
  display: grid;
  grid-template-columns: 56px minmax(0, 0.6fr) minmax(0, 1.4fr);
  gap: clamp(14px, 2.4vw, 40px);
  align-items: baseline;
  padding: clamp(15px, 1.7vw, 22px) 0;
  border-bottom: 1px solid var(--line-3);
  transition: background 0.35s var(--ease);
}
.belief-list li:hover { background: rgba(var(--blue-rgb), 0.032); }

.belief-num {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 0.95rem;
  color: var(--blue);
}
.belief-name {
  font-size: clamp(1.02rem, 1.5vw, 1.35rem);
  font-weight: 600;
  font-stretch: 106%;
  letter-spacing: -0.022em;
  color: var(--fg);
}
.belief-txt { font-size: var(--fs-small); color: var(--fg-3); }


/* ==========================================================================
   15  PRINCIPLES
   ========================================================================== */

.pr {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 1.18fr);
  gap: clamp(28px, 4.5vw, 84px);
  align-items: start;
}

.pr-list { display: grid; border-top: 1px solid var(--line-2); }

.pr-tab {
  position: relative;
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  gap: 10px;
  align-items: baseline;
  width: 100%;
  padding: clamp(16px, 1.8vw, 22px) 0;
  border-bottom: 1px solid var(--line);
  text-align: left;
  color: var(--fg-3);
  transition: color 0.3s var(--ease);
}
.pr-tab::after {
  content: "";
  position: absolute;
  left: 0; bottom: -1px;
  width: 100%; height: 1px;
  background: var(--blue);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.5s var(--ease-out);
}
.pr-tab:hover { color: var(--fg-2); }
.pr-tab[aria-selected="true"] { color: var(--fg); }
.pr-tab[aria-selected="true"]::after { transform: none; }

.pr-tab-num {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 0.9rem;
  color: var(--fg-4);
  transition: color 0.3s var(--ease);
}
.pr-tab[aria-selected="true"] .pr-tab-num { color: var(--blue); }

.pr-tab-name {
  font-size: clamp(1rem, 1.5vw, 1.32rem);
  font-weight: 600;
  font-stretch: 104%;
  letter-spacing: -0.024em;
  line-height: 1.14;
}

.pr-stage {
  position: relative;
  border: 1px solid var(--line);
  background:
    radial-gradient(90% 120% at 100% 0%, rgba(var(--blue-rgb), 0.09), transparent 62%),
    linear-gradient(160deg, rgba(245,245,245,0.03), rgba(245,245,245,0.005));
  padding: clamp(26px, 3.6vw, 56px);
  min-height: clamp(300px, 32vw, 400px);
  display: flex;
  align-items: center;
}

.pr-panel { max-width: 46ch; }
.pr-panel:focus-visible { outline-offset: 8px; }
.pr-panel-num {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: clamp(2.2rem, 4vw, 3.4rem);
  line-height: 0.85;
  color: var(--blue);
  margin-bottom: clamp(16px, 2vw, 26px);
}
.pr-panel .h3 { margin-bottom: 16px; }
.pr-panel p + p { margin-top: 14px; }
.pr-panel-note {
  margin-top: 22px !important;
  padding-top: 18px;
  border-top: 1px solid var(--line);
  font-size: var(--fs-small);
  color: var(--fg-4);
}
.pr-panel.is-in { animation: panelIn 0.5s var(--ease-out) both; }
@keyframes panelIn {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: none; }
}


/* ==========================================================================
   16  CONTACT & FORM
   ========================================================================== */

/* A quiet reprise of the hero banner so the closing section bookends the
   opening one. It lives on its own element rather than on .contact::before,
   because the `.section + .section::before` divider rule out-specifies any
   pseudo-element rule written against a single section class. */
.contact { position: relative; isolation: isolate; }
.contact-media {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(93deg, rgba(var(--cosmic-black-rgb), 0.98) 14%, rgba(var(--cosmic-black-rgb), 0.92) 46%, rgba(var(--cosmic-black-rgb), 0.87) 100%),
    url("../assets/images/hero-banner-640.jpg");
  background-size: cover, cover;
  background-position: center, 62% 34%;
  background-repeat: no-repeat, no-repeat;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 30%, #000 70%, transparent);
  mask-image: linear-gradient(180deg, transparent, #000 30%, #000 70%, transparent);
}

.contact-head { margin-bottom: var(--stack-4); }
.contact-head .eyebrow { margin-bottom: var(--stack-2); }
.contact-title-em { display: block; margin-top: 0.14em; }
.contact-title-em em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  font-stretch: 100%;
  font-size: 1.05em;
  letter-spacing: -0.012em;
  color: var(--blue-lift);
}

.contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
  gap: clamp(36px, 5vw, 92px);
  align-items: start;
}

.contact-intro {
  max-width: 50ch;
  margin-bottom: var(--stack-3);
  padding-bottom: var(--stack-3);
  border-bottom: 1px solid var(--line);
  color: var(--fg-2);
}

/* Form --------------------------------------------------------------------- */
.cform { display: grid; gap: clamp(18px, 2vw, 26px); }
.cform-row {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 26px);
}

.field { display: grid; gap: 8px; }
.field label {
  font-size: var(--fs-meta);
  font-weight: 500;
  font-stretch: 92%;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.field label span { color: var(--blue); }

.field input,
.field textarea,
.field select {
  width: 100%;
  padding: 13px 0;
  border-bottom: 1px solid var(--line-2);
  background: transparent;
  color: var(--fg);
  font-size: var(--fs-body);
  transition: border-color 0.3s var(--ease);
}
.field textarea { resize: vertical; min-height: 120px; line-height: 1.55; }
.field input::placeholder,
.field textarea::placeholder { color: var(--fg-4); }
.field input:hover,
.field textarea:hover,
.field select:hover { border-bottom-color: rgba(245, 245, 245, 0.28); }
.field input:focus,
.field textarea:focus,
.field select:focus {
  outline: none;
  border-bottom-color: var(--blue);
}
.field input:focus-visible,
.field textarea:focus-visible,
.field select:focus-visible { outline: none; }

.select-wrap { position: relative; display: block; }
.select-wrap select {
  appearance: none;
  -webkit-appearance: none;
  padding-right: 28px;
  cursor: pointer;
}
/* The dropdown itself is drawn by the OS, so this is as far as it can be
   taken — but without it the popup falls back to a white system list, which
   on this site reads as a hole. The optgroup rule is here because the plan
   select on contact.html is the only grouped select on the site; without it
   the two group labels render on the system default rather than with their
   options. */
.select-wrap select option { background: var(--ink-3); color: var(--fg); }
.select-wrap select optgroup {
  background: var(--ink-2);
  color: var(--fg-3);
  font-style: normal;
  font-weight: 600;
}
.select-wrap svg {
  position: absolute;
  right: 2px; top: 50%;
  transform: translateY(-50%);
  color: var(--fg-3);
  pointer-events: none;
}

.field.has-error input,
.field.has-error textarea { border-bottom-color: #FF6B6B; }
.field-err {
  font-size: var(--fs-meta);
  letter-spacing: 0.06em;
  color: #FF8080;
  min-height: 0;
}
.field-err:empty { display: none; }

/* The legal link sits under the Connect column rather than in the page list:
   it is not part of the site's navigation, it is the footnote every site
   carries. Divided off with the same hairline the footer already uses. */
.foot-legal {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}

/* --- Privacy policy ------------------------------------------------------
   A document, so it is set as one: a single measured column, headings that
   step down from the section rather than competing with it, and no new
   colour, typeface or component. .h3 and .svc-caps are the page's own. */
.legal { max-width: 68ch; }
.legal .h3 {
  margin-top: var(--stack-4);
  margin-bottom: var(--stack-2);
  padding-top: var(--stack-3);
  border-top: 1px solid var(--line);
  font-size: clamp(1.15rem, 1.9vw, 1.55rem);
}
.legal .h3:first-of-type { margin-top: var(--stack-3); }
.legal p { margin-bottom: 1.1em; }
.legal p:last-child { margin-bottom: 0; }
.legal .svc-caps { grid-template-columns: minmax(0, 1fr); margin-bottom: 1.1em; }

/* The standing caveat at the top. Built from .svc-soon's construction — a
   hairline box on a blue wash — so it belongs to the page without being a
   new component. */
.legal-note {
  margin-bottom: var(--stack-3);
  padding: clamp(18px, 2.2vw, 26px);
  border: 1px solid rgba(var(--blue-rgb), 0.35);
  background: linear-gradient(150deg, rgba(var(--blue-rgb), 0.07), rgba(245, 245, 245, 0.012));
  font-size: var(--fs-small);
  color: var(--fg-2);
}

/* Every fact only Vyomatrics holds. Deliberately loud: this page must not go
   live with a placeholder still in it, and a quiet marker would be missed.
   Delete the wrapper along with the bracketed text once each is filled. */
.legal-fill {
  padding: 1px 7px;
  border: 1px dashed rgba(var(--blue-rgb), 0.75);
  background: rgba(var(--blue-rgb), 0.12);
  color: var(--blue-lift);
  font-size: 0.94em;
  font-weight: 500;
}


/* --- Consent checkbox ----------------------------------------------------
   The native box is kept in the DOM and driven from the keyboard as normal;
   it is only visually replaced, so focus, Space, and the required attribute
   all keep working. The drawn box is a hairline square that fills with the
   accent blue — the same border and blue every other control on the form
   uses, rather than a new device invented for one field. */
.field--check { gap: 10px; }

.check {
  display: grid;
  grid-template-columns: 18px minmax(0, 1fr);
  gap: 12px;
  align-items: start;
  cursor: pointer;
  /* The whole label is the target, which clears the 24px minimum on its own
     even though the drawn box is 18px. */
  padding-block: 4px;
}
.check input {
  position: absolute;
  width: 18px; height: 18px;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.check-box {
  width: 18px; height: 18px;
  margin-top: 2px;
  border: 1px solid var(--line-2);
  background: rgba(var(--blue-rgb), 0.05);
  transition: border-color 0.25s var(--ease), background 0.25s var(--ease);
  position: relative;
  flex: none;
}
.check-box::after {
  content: "";
  position: absolute;
  left: 5px; top: 1px;
  width: 5px; height: 10px;
  border: solid var(--ink-0);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg) scale(0.4);
  opacity: 0;
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease-out);
}
.check:hover .check-box { border-color: rgba(var(--blue-rgb), 0.6); }
.check input:checked ~ .check-box {
  background: var(--blue);
  border-color: var(--blue);
}
.check input:checked ~ .check-box::after { opacity: 1; transform: rotate(45deg) scale(1); }
.check input:focus-visible ~ .check-box {
  outline: 2px solid var(--blue);
  outline-offset: 3px;
}
/* .field label is the tracked uppercase micro-label every other field uses,
   and .field label span is the blue required marker. Neither is right for a
   sentence of consent copy, so both are overridden here — by class weight
   rather than !important. */
.field--check label.check {
  font-size: var(--fs-small);
  font-weight: 400;
  font-stretch: 100%;
  letter-spacing: normal;
  text-transform: none;
  color: var(--fg-3);
}
.field--check .check-text {
  font-size: var(--fs-small);
  color: var(--fg-3);
  line-height: 1.55;
}
.field--check.has-error .check-box { border-color: #FF8A8A; }

.cform-foot {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 20px;
  margin-top: 6px;
}
.cform-note { font-size: var(--fs-small); color: var(--fg-4); }
.cform-note a {
  display: inline-block;
  padding-block: 5px 3px;
  color: var(--fg-2);
  border-bottom: 1px solid var(--line-2);
  transition: color 0.26s var(--ease), border-color 0.26s var(--ease);
}
.cform-note a:hover { color: var(--blue-lift); border-color: var(--blue); }

.cform-status {
  font-size: var(--fs-small);
  color: var(--fg-4);
}
.cform-status:empty { display: none; }

/* Success ------------------------------------------------------------------ */
.cform-success {
  border: 1px solid var(--line);
  background: linear-gradient(160deg, rgba(var(--blue-rgb), 0.09), rgba(245,245,245,0.012));
  padding: clamp(26px, 3.4vw, 46px);
  max-width: 54ch;
}
.cform-success-mark { color: var(--blue); margin-bottom: 20px; }
.cform-success .h4 { margin-bottom: 12px; }
.cform-success p { margin-bottom: 22px; }
.cform-success a {
  color: var(--fg-2);
  border-bottom: 1px solid var(--line-2);
}
.cform-success a:hover { color: var(--blue-lift); }

/* Aside -------------------------------------------------------------------- */
.contact-aside {
  display: grid;
  gap: clamp(24px, 2.6vw, 34px);
  border-left: 1px solid var(--line);
  padding-left: clamp(20px, 2.6vw, 40px);
}
.contact-block .eyebrow { margin-bottom: 14px; }

.contact-mail {
  font-size: clamp(1.05rem, 1.7vw, 1.42rem);
  font-weight: 600;
  font-stretch: 104%;
  letter-spacing: -0.024em;
  color: var(--fg);
  border-bottom: 1px solid var(--line-2);
  padding-bottom: 5px;
  display: inline-block;
  transition: color 0.28s var(--ease), border-color 0.28s var(--ease);
  word-break: break-word;
}
.contact-mail:hover { color: var(--blue-lift); border-color: var(--blue); }

.contact-social { display: grid; gap: 1px; }
.contact-social a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 11px 0;
  border-bottom: 1px solid var(--line-3);
  font-size: var(--fs-small);
  color: var(--fg-2);
  transition: color 0.28s var(--ease);
}
.contact-social a svg { color: var(--fg-4); transition: transform 0.38s var(--ease-out), color 0.28s var(--ease); }
.contact-social a:hover { color: var(--fg); }
.contact-social a:hover svg { color: var(--blue); transform: translate(2px, -2px); }

.contact-note { font-size: var(--fs-small); max-width: 32ch; }

.contact-checklist { display: grid; gap: 9px; }
.contact-checklist li {
  position: relative;
  padding-left: 18px;
  font-size: var(--fs-small);
  color: var(--fg-3);
}
.contact-checklist li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.8em;
  width: 7px; height: 1px;
  background: var(--fg-4);
}


/* ==========================================================================
   17  FOOTER
   ========================================================================== */

/* The page fades back into deep space here: the wash starts as a faint blue
   lift under the top border and falls away to nothing, so the last thing on
   screen is the cosmic ground itself rather than a panel sitting on it. */
.site-foot {
  position: relative;
  z-index: 2;
  isolation: isolate;
  border-top: 1px solid var(--line);
  padding-block: clamp(52px, 6vw, 88px) clamp(28px, 3vw, 40px);
  background: linear-gradient(180deg, rgba(var(--blue-rgb), 0.028), rgba(7, 20, 38, 0.30) 46%, transparent);
}

/* One restrained glow above the fold of the footer, centred and wide enough
   that it reads as horizon light rather than as a spotlight on the logo.
   Written as ::before on .site-foot — which is not a .section, so the
   `.section + .section::before` divider rule documented in §16 does not
   out-specify it here. */
.site-foot::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 320px;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(64% 100% at 50% 0%, rgba(var(--blue-rgb), 0.075), transparent 72%);
}

/* Two columns of links, not four. The footer repeats the page set and the
   contact channels — everything deeper belongs on the page itself. */
.foot-top {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr);
  gap: clamp(36px, 5vw, 80px);
  padding-bottom: clamp(40px, 5vw, 72px);
}

.brand--foot { align-items: flex-start; }
.brand--foot .brand-logo { height: 26px; }
.brand--foot .brand-sub { letter-spacing: 0.58em; text-indent: 0.58em; font-size: 0.6rem; }
.foot-statement {
  margin-top: 22px;
  font-size: var(--fs-small);
  color: var(--fg-3);
  line-height: 1.6;
}

/* Where the studio sits, and how far it works. It lives under the statement
   inside the brand column, so .foot-top's two columns are untouched. Keys and
   values share one grid so both labels align, and the rule above it answers
   the one over .foot-legal in the column opposite. */
.foot-where {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: minmax(0, auto) minmax(0, 1fr);
  align-items: baseline;
  column-gap: clamp(12px, 1.4vw, 20px);
  row-gap: 7px;
  max-width: 42ch;
  font-style: normal;
}
.foot-where-key {
  font-size: var(--fs-meta);
  font-weight: 500;
  font-stretch: 92%;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fg-4);
}
.foot-where-val {
  font-size: var(--fs-small);
  color: var(--fg-3);
  line-height: 1.6;
}

.foot-nav {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(22px, 3vw, 48px);
}
.foot-col .eyebrow { margin-bottom: 18px; }
.foot-col ul { display: grid; gap: 1px; }
.foot-col a {
  display: inline-block;
  padding-block: 5px;
  font-size: var(--fs-small);
  color: var(--fg-3);
  transition: color 0.26s var(--ease);
  word-break: break-word;
}
.foot-col a:hover { color: var(--fg); }

.foot-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px 28px;
  padding-top: clamp(22px, 2.4vw, 32px);
  border-top: 1px solid var(--line);
}
.foot-copy,
.foot-colophon,
.foot-top-link {
  font-size: var(--fs-meta);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--fg-4);
  line-height: 1.4;
}
.foot-top-link {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding-block: 7px;
  color: var(--fg-3);
  transition: color 0.26s var(--ease);
}
.foot-top-link svg { transition: transform 0.38s var(--ease-out); }
.foot-top-link:hover { color: var(--fg); }
.foot-top-link:hover svg { transform: translateY(-3px); }

/* ==========================================================================
   18  ABOUT PAGE
   ==========================================================================
   Everything here is scoped to the About page or to a --page modifier, so the
   homepage cascade is untouched. Tokens, typography, grid, buttons, reveals and
   the header/footer components are all reused as-is.

   The sky idea is carried by composition rather than imagery: a drawn horizon
   line under the hero type, ascending rules, a glow that sits low in the frame
   like light coming off an edge, and one section given far more vertical room
   than it needs. No clouds. */


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

.hero--page {
  min-height: min(94svh, 940px);
  padding-bottom: clamp(26px, 3vw, 42px);
}

/* The lexicon column takes ~300px, so this headline has less room than the
   homepage one. Sized — by measurement — so "Built for businesses" stays on a
   single line, including above 1440 where the shell stops widening. */
.hero-title--page {
  font-size: clamp(2.5rem, 6.3vw, 5.7rem);
  letter-spacing: -0.04em;
}

/* Aimed at open sky. The planet is deliberately out of frame here — this page
   is about the space, not the object in it. */
.hero-media--page img {
  object-position: 72% 8%;
  opacity: 0.78;
  transform: none;
}
.hero-media--page::after {
  background:
    linear-gradient(100deg, var(--ink-0) 10%, rgba(var(--cosmic-black-rgb), 0.8) 42%, rgba(var(--cosmic-black-rgb), 0.5) 78%, rgba(var(--cosmic-black-rgb), 0.62) 100%),
    linear-gradient(180deg, rgba(var(--cosmic-black-rgb), 0.88) 0%, rgba(var(--cosmic-black-rgb), 0.22) 26%, rgba(var(--cosmic-black-rgb), 0.44) 66%, var(--ink-0) 96%);
}

/* The horizon: a hairline with light pooling above it.
   It sits on the bottom edge of the banner, closing the section, rather than
   floating at a fraction of its height — at 22% it cut straight through
   whatever the hero's index column happened to land on, which on Services was
   the middle of "Digital". Anchored to the edge, it lands in the same place on
   every page regardless of how tall that page's hero is. */
.horizon {
  position: absolute;
  left: 0; right: 0;
  bottom: 0;
  z-index: 2;
  display: block;
  pointer-events: none;
}
.horizon i {
  display: block;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(var(--blue-rgb), 0.5) 22%, rgba(245, 245, 245, 0.32) 52%, rgba(var(--blue-rgb), 0.4) 78%, transparent);
}
.horizon::before {
  content: "";
  position: absolute;
  left: 8%; right: 8%;
  bottom: 0;
  height: 190px;
  background: linear-gradient(180deg, transparent, rgba(var(--blue-rgb), 0.1) 62%, rgba(var(--blue-rgb), 0.16));
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 30%, #000 70%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 30%, #000 70%, transparent);
}

.hero-shell--page { grid-template-columns: minmax(0, 1fr) clamp(210px, 21vw, 300px); }
.hero-title--page { margin-bottom: clamp(24px, 2.6vw, 38px); }

/* Dictionary entry for the name. */
.lexicon {
  border-top: 1px solid var(--line-2);
  padding-top: 18px;
}
.lexicon-word {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2rem, 3.4vw, 3rem);
  line-height: 1;
  color: var(--fg);
  margin-bottom: 8px;
}
.lexicon-gloss {
  font-size: var(--fs-meta);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--blue);
  margin-bottom: 14px;
}
.lexicon-gloss em { font-style: normal; }
.lexicon-def {
  font-size: var(--fs-small);
  line-height: 1.6;
  color: var(--fg-2);
  border-top: 1px solid var(--line-3);
  padding-top: 14px;
}

.hero-foot--page { align-items: flex-end; }

/* Two classes, because `.hero-foot p` sets the tracked-metadata treatment and
   would otherwise out-specify a single class here. */
.hero-foot--page .creed-line {
  font-family: var(--f-sans);
  font-weight: 600;
  font-stretch: 106%;
  font-size: clamp(1.02rem, 1.8vw, 1.5rem);
  line-height: 1.25;
  letter-spacing: -0.026em;
  color: var(--fg);
  text-transform: none;
  max-width: 30ch;
}
.hero-foot--page .creed-line em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  font-stretch: 100%;
  font-size: 1.06em;
  letter-spacing: -0.012em;
  color: var(--blue-lift);
}


/* --- 01 Origin ----------------------------------------------------------- */

.origin-body {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
  gap: clamp(30px, 5vw, 88px);
  align-items: start;
  border-top: 1px solid var(--line);
  padding-top: var(--stack-3);
}
.origin-copy { display: grid; gap: 1.15em; max-width: 60ch; }
.origin-lead {
  font-size: var(--fs-lede);
  line-height: 1.5;
  letter-spacing: -0.012em;
  color: var(--fg-2);
}

.origin-aside { border-left: 1px solid var(--line); padding-left: clamp(18px, 2.4vw, 36px); }
.pull-small {
  font-family: var(--f-sans);
  font-weight: 600;
  font-stretch: 106%;
  font-size: clamp(1.16rem, 1.9vw, 1.6rem);
  line-height: 1.24;
  letter-spacing: -0.028em;
  color: var(--fg);
  text-wrap: balance;
}

.weave {
  margin-top: var(--stack-4);
  border-top: 1px solid var(--line-2);
  padding-top: var(--stack-3);
}
.weave-label { margin-bottom: var(--stack-2); }
.weave-copy { max-width: 62ch; }
.weave-copy--end { margin-top: var(--stack-2); }

.weave-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: var(--stack-2);
}
.weave-list li {
  padding: 9px 16px;
  border: 1px solid var(--line);
  font-size: var(--fs-meta);
  letter-spacing: 0.13em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--fg-3);
  transition: border-color 0.4s var(--ease), color 0.4s var(--ease);
}
.weave:hover .weave-list li { border-color: var(--line-2); color: var(--fg-2); }


/* --- 02 Vyoma ------------------------------------------------------------ */

.vyoma {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: clamp(104px, 13vw, 210px);
}
.vyoma-glow {
  position: absolute;
  inset: auto -10% -40% -10%;
  height: 78%;
  z-index: -1;
  background:
    radial-gradient(58% 100% at 50% 100%, rgba(var(--blue-rgb), 0.16), transparent 68%),
    radial-gradient(90% 70% at 50% 100%, rgba(245, 245, 245, 0.035), transparent 72%);
}

/* The one place on the site where type is allowed to run this large. */
.vyoma-word {
  font-family: var(--f-sans);
  font-weight: 700;
  font-stretch: 118%;
  font-size: clamp(4.2rem, 19vw, 17rem);
  line-height: 0.82;
  letter-spacing: -0.05em;
  color: var(--fg);
  margin-top: clamp(20px, 3vw, 40px);
  text-transform: uppercase;
}
.vyoma-gloss {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: clamp(1.4rem, 3.2vw, 2.7rem);
  line-height: 1.1;
  color: var(--blue-lift);
  margin-top: clamp(10px, 1.4vw, 18px);
  padding-bottom: clamp(30px, 4vw, 56px);
  border-bottom: 1px solid var(--line);
}
.vyoma-gloss em { font-style: italic; }

.vyoma-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.55fr);
  gap: clamp(28px, 5vw, 80px);
  align-items: start;
  margin-top: var(--stack-3);
}
.vyoma-copy { display: grid; gap: 1.15em; max-width: 58ch; }
.vyoma-copy p:first-child { color: var(--fg-2); }

/* Five rules climbing toward the right — altitude, drawn rather than depicted. */
.vyoma-mark { display: grid; gap: clamp(12px, 1.5vw, 20px); padding-top: 8px; }
.vyoma-rule {
  display: block;
  height: 1px;
  background: linear-gradient(90deg, var(--line-3), rgba(var(--blue-rgb), 0.55));
  transform-origin: left;
}
.vyoma-rule:nth-child(1) { width: 40%; }
.vyoma-rule:nth-child(2) { width: 55%; }
.vyoma-rule:nth-child(3) { width: 70%; }
.vyoma-rule:nth-child(4) { width: 85%; }
.vyoma-rule:nth-child(5) { width: 100%; }

.vyoma-pull { margin-top: var(--stack-4); }
.vyoma-pull p { max-width: 22ch; }


/* --- 03 Beliefs ---------------------------------------------------------- */

.creed { background: linear-gradient(180deg, rgba(var(--blue-rgb), 0.026), transparent 70%); }

.creed-list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1px;
  border-top: 1px solid var(--line-2);
  border-left: 1px solid var(--line);
}
.creed-item {
  padding: clamp(26px, 3vw, 44px) clamp(20px, 2.4vw, 36px);
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  transition: background 0.45s var(--ease);
}
.creed-item:hover { background: rgba(var(--blue-rgb), 0.032); }
.creed-num {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 1.35rem;
  line-height: 1;
  color: var(--blue);
  margin-bottom: clamp(18px, 2.4vw, 34px);
}
.creed-item .h4 { margin-bottom: 12px; text-wrap: balance; }
.creed-item p { max-width: 34ch; }


/* --- 04 Direction -------------------------------------------------------- */

.building-body {
  display: grid;
  gap: 1.15em;
  max-width: 66ch;
  border-top: 1px solid var(--line);
  padding-top: var(--stack-3);
}

.chain { margin-top: var(--stack-4); }
.chain--arc { margin-top: var(--stack-3); }
.chain-label { margin-bottom: var(--stack-2); }

.chain-list {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px clamp(12px, 2vw, 26px);
  counter-reset: chain;
}
.chain-list li {
  position: relative;
  display: flex;
  align-items: center;
  gap: clamp(12px, 2vw, 26px);
}
.chain-list li span {
  font-size: clamp(1.05rem, 2vw, 1.75rem);
  font-weight: 600;
  font-stretch: 106%;
  letter-spacing: -0.026em;
  color: var(--fg);
  white-space: nowrap;
}
/* The connector between steps. */
.chain-list li:not(:last-child)::after {
  content: "";
  width: clamp(18px, 3vw, 46px);
  height: 1px;
  background: linear-gradient(90deg, var(--line-2), rgba(var(--blue-rgb), 0.5));
  flex: none;
}
.chain-list--arc li span {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  font-stretch: 100%;
  font-size: clamp(1.15rem, 2.2vw, 1.95rem);
  letter-spacing: -0.01em;
  color: var(--fg-2);
}

.building-note {
  margin-top: var(--stack-4);
  padding-top: var(--stack-2);
  border-top: 1px solid var(--line);
  max-width: 64ch;
  font-size: var(--fs-small);
  color: var(--fg-3);
}


/* --- 05 Goal ------------------------------------------------------------- */

.goal {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: clamp(100px, 12vw, 190px);
}
.goal-glow {
  position: absolute;
  inset: -30% -10% auto -10%;
  height: 82%;
  z-index: -1;
  background: radial-gradient(52% 100% at 32% 0%, rgba(var(--blue-rgb), 0.13), transparent 70%);
}
.goal-head { margin-top: var(--stack-2); }

.goal-statement {
  font-family: var(--f-sans);
  font-weight: 700;
  font-stretch: 114%;
  font-size: clamp(2.6rem, 8.2vw, 7.2rem);
  line-height: 0.94;
  letter-spacing: -0.045em;
  color: var(--fg);
  margin-top: clamp(18px, 2.4vw, 34px);
  padding-bottom: clamp(32px, 4vw, 60px);
  border-bottom: 1px solid var(--line);
  text-wrap: balance;
}
.goal-statement em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  font-stretch: 100%;
  font-size: 1.05em;
  letter-spacing: -0.012em;
  color: var(--blue-lift);
}

.goal-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.62fr);
  gap: clamp(30px, 5vw, 84px);
  align-items: start;
  margin-top: var(--stack-3);
}
.goal-copy { display: grid; gap: 1.15em; max-width: 54ch; }
.goal-copy p:first-child { color: var(--fg-2); }

/* Each step sits a little further right than the last. */
.ladder { display: grid; gap: clamp(10px, 1.3vw, 18px); }
.ladder li {
  display: flex;
  align-items: center;
  gap: clamp(12px, 1.6vw, 22px);
}
.ladder li:nth-child(2) { padding-left: 8%; }
.ladder li:nth-child(3) { padding-left: 16%; }
.ladder li:nth-child(4) { padding-left: 24%; }
.ladder li:nth-child(5) { padding-left: 32%; }

.ladder-tick {
  width: clamp(22px, 3vw, 44px);
  height: 1px;
  background: rgba(var(--blue-rgb), 0.6);
  flex: none;
}
.ladder-word {
  font-size: clamp(1.2rem, 2.4vw, 2.1rem);
  font-weight: 700;
  font-stretch: 108%;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--fg);
}
.ladder-word--loop {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  font-stretch: 100%;
  font-size: clamp(1.3rem, 2.6vw, 2.3rem);
  letter-spacing: -0.012em;
  color: var(--fg-3);
}


/* --- 06 Ahead ------------------------------------------------------------ */

.future-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.5fr);
  gap: clamp(30px, 5vw, 84px);
  align-items: start;
  border-top: 1px solid var(--line);
  padding-top: var(--stack-3);
}
.future-copy { display: grid; gap: 1.15em; max-width: 60ch; }
.future-copy p:first-child { color: var(--fg-2); }

/* Three horizons, each fainter and further away. */
.future-mark { display: grid; gap: clamp(26px, 4vw, 54px); padding-top: 10px; }
.future-mark span {
  display: block;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--line-2) 30%, rgba(var(--blue-rgb), 0.45));
}
.future-mark span:nth-child(2) { opacity: 0.6; }
.future-mark span:nth-child(3) { opacity: 0.3; }

.future-pull { margin-top: var(--stack-4); }
.future-pull p { max-width: 28ch; }


/* --- Closing ------------------------------------------------------------- */

.closing {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: clamp(96px, 12vw, 180px);
}
.closing-media {
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image:
    linear-gradient(96deg, rgba(var(--cosmic-black-rgb), 0.97) 12%, rgba(var(--cosmic-black-rgb), 0.9) 48%, rgba(var(--cosmic-black-rgb), 0.84) 100%),
    url("../assets/images/hero-banner-640.jpg");
  background-size: cover, cover;
  background-position: center, 40% 22%;
  background-repeat: no-repeat, no-repeat;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 26%, #000 74%, transparent);
  mask-image: linear-gradient(180deg, transparent, #000 26%, #000 74%, transparent);
}
.closing-inner { max-width: 40ch; }
.closing-title { margin-top: var(--stack-2); }
.closing-lede { margin-top: var(--stack-2); max-width: 44ch; }
.closing-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: var(--stack-3);
}


/* --- Current page state -------------------------------------------------- */

.nav-desktop a[aria-current="page"] { color: var(--fg); }
.nav-desktop a[aria-current="page"]::after { transform: none; transform-origin: left; }
.mobile-nav-list a[aria-current="page"] { color: var(--blue-lift); }
.foot-col a[aria-current="page"] { color: var(--fg); }


/* --- About: responsive --------------------------------------------------- */

@media (max-width: 1024px) {
  .hero-shell--page { grid-template-columns: minmax(0, 1fr); }
  .hero-media--page img { object-position: 68% 12%; }

  .lexicon {
    display: grid;
    grid-template-columns: minmax(0, auto) minmax(0, 1fr);
    align-items: baseline;
    column-gap: clamp(16px, 3vw, 32px);
  }
  .lexicon-gloss { margin-bottom: 0; }
  .lexicon-def { grid-column: 1 / -1; margin-top: 14px; }

  .hero-foot--page { flex-wrap: wrap; align-items: flex-start; }
  .hero-foot--page .creed-line { flex-basis: 100%; order: -1; margin-bottom: 4px; max-width: none; }

  .origin-body,
  .vyoma-body,
  .goal-body,
  .future-body { grid-template-columns: minmax(0, 1fr); }
  .origin-aside { border-left: 0; border-top: 1px solid var(--line); padding-left: 0; padding-top: var(--stack-2); }
  .vyoma-mark, .future-mark { display: none; }

  .creed-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .ladder li:nth-child(2) { padding-left: 6%; }
  .ladder li:nth-child(3) { padding-left: 12%; }
  .ladder li:nth-child(4) { padding-left: 18%; }
  .ladder li:nth-child(5) { padding-left: 24%; }
}

@media (max-width: 720px) {
  .hero--page { min-height: 0; }

  /* "Built for businesses" needs 9.71em to set, which at 9vw left roughly one
     pixel of slack at 320 — enough on a phone, but not once a 15px scrollbar
     is present, as it is when a desktop window is dragged this narrow. 8.5vw
     restores real margin at every width without being visibly smaller. */
  .hero-title--page { font-size: clamp(2rem, 10.2vw, 3rem); }

  .hero-media--page img { object-position: 64% 14%; opacity: 0.66; }
  .horizon::before { height: 120px; }

  .creed-list { grid-template-columns: minmax(0, 1fr); }
  .creed-item { padding-inline: 0 clamp(0px, 4vw, 24px); border-right: 0; }
  .creed-list { border-left: 0; }
  .creed-item p { max-width: none; }

  /* Stacked steps read better than a wrapped horizontal chain on a phone. */
  .chain-list { display: grid; gap: 0; }
  .chain-list li { display: grid; grid-template-columns: 1fr; gap: 0; padding-block: 11px; border-bottom: 1px solid var(--line-3); }
  .chain-list li:not(:last-child)::after { display: none; }
  .chain-list li span { white-space: normal; }

  .ladder li:nth-child(n) { padding-left: 0; }
  .ladder li { gap: 14px; }

  .closing-inner { max-width: none; }
}


/* ==========================================================================
   19  SERVICES PAGE
   ==========================================================================
   Scoped to the Services page or to a --svc modifier. No new tokens, no new
   typeface, no duplicated component — the closing CTA is the same .closing
   block the About page uses.

   The architecture is deliberately not cards: each pillar pins a large numeral
   and name to the left while its services scroll past on the right, so the
   reader always knows which of the four they are inside. */


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

/* Carries the same .hero-media--page treatment as the About hero, so the two
   inner pages open the same way. Taller than it would be without the banner,
   to give the image and its horizon line room to read. No bottom border —
   the media's vertical scrim already fades into the page. */
.hero--svc {
  min-height: min(88svh, 900px);
  padding-bottom: clamp(30px, 4vw, 56px);
}
/* Sized so the three authored lines stay three lines. The index column steals
   ~280px, so this headline has less room than the homepage one and cannot be
   set at the same scale without breaking to a fourth, ragged line. */
.hero-title--svc {
  font-size: clamp(2.4rem, 5.6vw, 5.4rem);
  letter-spacing: -0.04em;
}
.hero-shell--svc { grid-template-columns: minmax(0, 1fr) clamp(200px, 20vw, 280px); }

.svc-index { border-top: 1px solid var(--line-2); padding-top: 16px; }
.svc-index .eyebrow { margin-bottom: 18px; }
.svc-index-list { display: grid; gap: 1px; }
.svc-index-list li {
  display: flex;
  align-items: baseline;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--line-3);
  font-size: var(--fs-small);
  font-weight: 500;
}
.svc-index-list span {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 0.8rem;
  color: var(--blue);
  min-width: 1.4em;
}
.svc-index-list a {
  display: inline-block;
  padding-block: 2px;
  color: var(--fg-2);
  transition: color 0.26s var(--ease);
}
.svc-index-list a:hover { color: var(--fg); }


/* --- Pillars ------------------------------------------------------------- */

.pillar--alt { background: linear-gradient(180deg, rgba(var(--blue-rgb), 0.026), transparent 72%); }

.pillar-shell {
  display: grid;
  grid-template-columns: minmax(0, 0.6fr) minmax(0, 1.4fr);
  gap: clamp(30px, 5vw, 96px);
  align-items: start;
}

/* Pinned while its services scroll past. */
.pillar-head {
  position: sticky;
  top: calc(var(--head-h) + 40px);
  align-self: start;
}
.pillar-num {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.6rem, 5.4vw, 4.8rem);
  line-height: 0.82;
  letter-spacing: -0.01em;
  color: var(--blue);
  margin-bottom: clamp(14px, 1.8vw, 24px);
}
.pillar-title {
  font-family: var(--f-sans);
  font-weight: 700;
  font-stretch: 112%;
  font-size: clamp(2.1rem, 4.6vw, 4rem);
  line-height: 0.98;
  letter-spacing: -0.036em;
  color: var(--fg);
  margin-bottom: clamp(14px, 1.8vw, 22px);
}
.pillar-intro {
  max-width: 30ch;
  padding-top: clamp(14px, 1.8vw, 22px);
  border-top: 1px solid var(--line);
  color: var(--fg-3);
}

.svc-list { display: grid; }

.svc {
  padding-block: clamp(30px, 3.6vw, 54px);
  border-top: 1px solid var(--line);
}
.svc:first-child { border-top: 1px solid var(--line-2); }

.svc-titlebar {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 10px 18px;
  margin-bottom: var(--stack-2);
}
.svc-title {
  font-family: var(--f-sans);
  font-weight: 600;
  font-stretch: 106%;
  font-size: clamp(1.35rem, 2.5vw, 2.15rem);
  line-height: 1.06;
  letter-spacing: -0.03em;
  color: var(--fg);
  margin-bottom: var(--stack-2);
}
.svc-titlebar .svc-title { margin-bottom: 0; }

.svc-desc { max-width: 56ch; }
.svc-desc + .svc-desc { margin-top: 1.1em; }

/* The four-word standard, divided by hairlines rather than boxed. */
.svc-standard {
  display: flex;
  flex-wrap: wrap;
  margin-top: var(--stack-2);
}
.svc-standard span {
  padding: 6px clamp(12px, 1.6vw, 22px);
  border-left: 1px solid var(--line-2);
  font-size: var(--fs-meta);
  font-weight: 600;
  font-stretch: 96%;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg);
}
.svc-standard span:first-child { padding-left: 0; border-left: 0; }

.svc-caps {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 clamp(20px, 3vw, 48px);
  margin-top: var(--stack-3);
}
.svc-caps li {
  position: relative;
  padding: 10px 0 10px 22px;
  border-bottom: 1px solid var(--line-3);
  font-size: var(--fs-small);
  color: var(--fg-2);
}
.svc-caps li::before {
  content: "";
  position: absolute;
  left: 0;
  top: calc(10px + 0.8em);
  width: 9px; height: 1px;
  background: var(--blue);
}

.svc-note {
  margin-top: var(--stack-2);
  padding-top: 16px;
  border-top: 1px solid var(--line-3);
  max-width: 58ch;
  font-size: var(--fs-small);
  color: var(--fg-4);
}


/* --- A service that is not open yet -------------------------------------- */

.svc-tag {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 6px 12px;
  border: 1px solid rgba(var(--blue-rgb), 0.45);
  font-size: var(--fs-meta);
  font-weight: 500;
  font-stretch: 92%;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blue-lift);
  white-space: nowrap;
}
.svc-tag-dot {
  width: 5px; height: 5px;
  background: var(--blue);
  flex: none;
}

/* Capabilities that exist as a plan, not yet as a service. */
.svc-caps--soon li { color: var(--fg-3); }
.svc-caps--soon li::before { background: var(--fg-4); }

.svc-soon {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(18px, 2.6vw, 40px);
  align-items: center;
  margin-top: var(--stack-3);
  padding: clamp(20px, 2.4vw, 30px);
  border: 1px solid var(--line);
  background: linear-gradient(150deg, rgba(var(--blue-rgb), 0.07), rgba(245, 245, 245, 0.012));
}
.svc-soon-copy {
  max-width: 58ch;
  font-size: var(--fs-small);
  color: var(--fg-3);
}
.svc-soon-btn { flex: none; }


/* --- 05 Process ---------------------------------------------------------- */

/* Runs horizontally, so it does not read as a second copy of the homepage's
   vertical process rail. */
.stages {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 30px);
  border-top: 1px solid var(--line-2);
}
.stage { position: relative; padding-top: clamp(22px, 2.6vw, 34px); }
.stage::before {
  content: "";
  position: absolute;
  left: 0; top: -1px;
  width: 26px; height: 3px;
  background: var(--blue);
}
.stage-num {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: clamp(1.5rem, 2.4vw, 2.1rem);
  line-height: 1;
  color: var(--fg-4);
  margin-bottom: clamp(12px, 1.6vw, 20px);
  transition: color 0.4s var(--ease);
}
.stage:hover .stage-num { color: var(--blue); }
.stage-title {
  font-size: clamp(1.05rem, 1.5vw, 1.35rem);
  font-weight: 600;
  font-stretch: 104%;
  letter-spacing: -0.024em;
  line-height: 1.14;
  color: var(--fg);
  margin-bottom: 10px;
}
.stage-copy { font-size: var(--fs-small); }


/* --- 06 Approach --------------------------------------------------------- */

.reasons { display: grid; border-top: 1px solid var(--line-2); }
.reason {
  display: grid;
  grid-template-columns: minmax(0, 0.42fr) minmax(0, 0.58fr);
  gap: clamp(16px, 3vw, 52px);
  align-items: baseline;
  padding-block: clamp(20px, 2.4vw, 30px);
  border-bottom: 1px solid var(--line);
  transition: background 0.4s var(--ease);
}
.reason:hover { background: rgba(var(--blue-rgb), 0.030); }
.reason dt {
  font-size: clamp(1.16rem, 2vw, 1.7rem);
  font-weight: 600;
  font-stretch: 106%;
  letter-spacing: -0.028em;
  line-height: 1.1;
  color: var(--fg);
}
.reason dd { font-size: var(--fs-small); color: var(--fg-3); max-width: 46ch; }


/* --- 07 Fit -------------------------------------------------------------- */

.paths {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(24px, 3.4vw, 56px);
}
.path { border-top: 1px solid var(--line-2); padding-top: clamp(18px, 2.2vw, 26px); }
.path-label {
  font-size: var(--fs-meta);
  font-weight: 500;
  font-stretch: 92%;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--blue-lift);
  margin-bottom: clamp(16px, 2vw, 24px);
}
.path-steps { display: grid; }
.path-steps li {
  position: relative;
  padding: 12px 0 12px 26px;
  font-size: clamp(0.98rem, 1.25vw, 1.15rem);
  font-weight: 500;
  color: var(--fg-2);
  border-bottom: 1px solid var(--line-3);
}
/* A rule joining each step to the next. */
.path-steps li::before {
  content: "";
  position: absolute;
  left: 4px; top: 0; bottom: 0;
  width: 1px;
  background: var(--line-2);
}
.path-steps li:first-child::before { top: 50%; }
.path-steps li:last-child::before { bottom: 50%; }
.path-steps li::after {
  content: "";
  position: absolute;
  left: 1px; top: 50%;
  width: 7px; height: 7px;
  margin-top: -3.5px;
  background: var(--ink-0);
  border: 1px solid var(--blue);
}

.fit-note {
  margin-top: var(--stack-3);
  padding-top: var(--stack-2);
  border-top: 1px solid var(--line);
  max-width: 60ch;
  font-size: var(--fs-small);
  color: var(--fg-3);
}


/* --- Services: responsive ------------------------------------------------ */

@media (max-width: 1024px) {
  .hero-shell--svc { grid-template-columns: minmax(0, 1fr); }
  .svc-index {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 clamp(24px, 4vw, 48px);
  }
  .svc-index .eyebrow { grid-column: 1 / -1; }

  /* Pinning stops earning its keep once the head sits above the list. */
  .pillar-shell { grid-template-columns: minmax(0, 1fr); gap: var(--stack-3); }
  .pillar-head { position: static; }
  .pillar-intro { max-width: 46ch; }

  .stages { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0; }
  .stage { padding: clamp(20px, 2.6vw, 30px) clamp(16px, 2vw, 26px) clamp(22px, 2.6vw, 32px) 0; }

  .paths { grid-template-columns: minmax(0, 1fr); gap: var(--stack-3); }
  .path-steps { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 720px) {
  .hero--svc { min-height: 0; }

  .svc-caps { grid-template-columns: minmax(0, 1fr); }

  /* Two columns is the floor before the copy stops fitting. */
  .stages { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  .svc-soon { grid-template-columns: minmax(0, 1fr); align-items: start; }
  .svc-soon-btn { width: 100%; }

  .reason { grid-template-columns: minmax(0, 1fr); gap: 8px; }
  .reason dd { max-width: none; }

  .svc-standard span { padding-inline: clamp(9px, 3vw, 16px); }
  .svc-standard span:first-child { padding-left: 0; }
}

@media (max-width: 480px) {
  .stages { grid-template-columns: minmax(0, 1fr); }
  .svc-index { grid-template-columns: minmax(0, 1fr); }

  /* This headline's first line is the longest on the site, so it needs its own
     small-screen scale: measured against the real rendered width, it has to sit
     at or below 8.6vw to keep "Built around where" on one line at 320pt and up.
     Without this it broke and left "where" stranded. */
  .hero-title--svc { font-size: clamp(2.05rem, 10.3vw, 2.85rem); }
}

/* ==========================================================================
   20  HOME, PROCESS, WORK & CONTACT PAGES
   ==========================================================================
   The six-page structure reuses the existing components almost entirely: the
   page hero treatment from §18, the project compositions from §11–12, the
   process rail from §13, the principles tabs from §15 and the form from §16.
   What follows is only what could not be expressed with something that
   already existed — four headline scales, one hero variant with no index
   column, one preview-copy block and a six-across modifier for the stages
   strip. No new tokens, no new typeface, no new component. */


/* --- Hero variants -------------------------------------------------------
   Each headline is sized against its own longest authored line rather than
   inheriting --fs-display, because the index column and the line content
   differ per page. Measured, not estimated — see the note in §07. */

/* "what takes it beyond." is the longest authored line on the site and needs
   9.36em to set, against the 8.0em the old homepage headline needed — so this
   cannot inherit --fs-display at any width. Measured with the real font
   loaded: natural line width against the shell's actual content box. */
.hero-title--home {
  font-size: clamp(2.35rem, 6.5vw, 6rem);
  letter-spacing: -0.04em;
}
/* Below 720 the clamp floor above would win and overflow, so the phone scale
   is authored separately. 8.8vw holds all three lines from 288px up, with or
   without a classic scrollbar taking 15px off the viewport. */
@media (max-width: 720px) {
  .hero-title--home { font-size: clamp(1.9rem, 10.6vw, 3.8rem); }
}

/* "No surprises in" needs 7.39em, which lands within a pixel of the available
   width at 320 under --fs-display. Its own scale buys back the margin. */
@media (max-width: 720px) {
  .hero-title--process { font-size: clamp(2.05rem, 12.4vw, 4.3rem); }
}

/* Process and Contact open on the headline alone: no index column, because
   on those two pages there is nothing to index that the page does not say
   immediately below. */
.hero-shell--solo { grid-template-columns: minmax(0, 1fr); }

/* Shorter than the other page heroes so the form is not pushed off-screen. */
.hero--contact { min-height: min(70svh, 720px); }


/* --- Home: section previews ----------------------------------------------
   A preview says only enough to be worth following. The copy block is the
   same measure and rhythm as the About page's .origin-copy, and the row that
   carries the link through to the full page is the existing .work-outro. */

.prev-copy {
  display: grid;
  gap: 1.15em;
  max-width: 60ch;
  border-top: 1px solid var(--line);
  padding-top: var(--stack-3);
}
.prev-copy p:first-child { color: var(--fg-2); }

/* The preview grids are the section's own content, so they sit tighter to the
   heading than a full page's would. */
.prev-set { margin-top: var(--stack-3); }


/* --- Process: the stages strip -------------------------------------------
   §19 sizes .stages for the five-stage summary the Services page used to
   carry. The process page runs the full six, so it steps down one column
   later at every breakpoint. */

.stages--six { grid-template-columns: repeat(6, minmax(0, 1fr)); }

@media (max-width: 1180px) {
  .stages--six { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0; }
  .stages--six .stage { padding: clamp(20px, 2.6vw, 30px) clamp(16px, 2vw, 26px) clamp(22px, 2.6vw, 32px) 0; }
}
@media (max-width: 720px) {
  .stages--six { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
  .stages--six { grid-template-columns: minmax(0, 1fr); }
}


/* --- Work: the portfolio lead -------------------------------------------- */

.work-lead {
  max-width: 58ch;
  border-top: 1px solid var(--line);
  padding-top: var(--stack-3);
  margin-bottom: clamp(56px, 7vw, 104px);
}


/* --- Contact: the form page ---------------------------------------------- */

/* The optional marker is the quiet counterpart to the required asterisk, so
   it reads as metadata rather than as part of the label. */
.field label .opt {
  color: var(--fg-4);
  letter-spacing: 0.12em;
}


/* --- Pages: responsive --------------------------------------------------- */

@media (max-width: 720px) {
  .hero--contact { min-height: 0; }
  .prev-set { margin-top: var(--stack-2); }
}


/* ==========================================================================
   21  MOTION & REVEAL
   ========================================================================== */

.js [data-reveal] {
  opacity: 0;
  transform: translateY(20px);
  transition:
    opacity 0.85s var(--ease) var(--d, 0ms),
    transform 0.85s var(--ease-out) var(--d, 0ms);
  will-change: opacity, transform;
}
.js [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* Hero line masks — only under JS, so no-JS renders plain text */
.js .hero-title .line-in {
  transform: translateY(105%);
  transition: transform 1.05s var(--ease-out) var(--d, 0ms);
}
.js .is-loaded .hero-title .line-in { transform: none; }


/* ==========================================================================
   22  RESPONSIVE
   ========================================================================== */

/* --- 1180 : compress the widest compositions --- */
@media (max-width: 1180px) {
  .cap-trigger { grid-template-columns: clamp(44px, 6vw, 66px) minmax(0, 1fr) 24px; }
  .cap-teaser { display: none; }
  .foot-top { grid-template-columns: minmax(0, 1fr); }
}

/* --- 1024 : tablet landscape --- */
@media (max-width: 1024px) {
  :root { --head-h: 72px; }

  .hero-shell { grid-template-columns: minmax(0, 1fr); gap: clamp(30px, 5vw, 46px); }
  .hero-index {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 8px 32px;
    align-items: start;
  }
  .hero-index .eyebrow { grid-column: 1 / -1; }
  .hero-index-note { margin-top: 0; align-self: end; }

  /* Two columns still hold here — each frame is ~450px wide, which is enough
     to read a page layout. They collapse at 720, not before. */
  .w-grid { gap: clamp(44px, 5vw, 64px) clamp(22px, 2.6vw, 34px); }

  .pr { grid-template-columns: minmax(0, 1fr); }
  .pr-stage { min-height: 0; }
  .contact-grid { grid-template-columns: minmax(0, 1fr); }
  .contact-aside {
    border-left: 0;
    border-top: 1px solid var(--line);
    padding-left: 0;
    padding-top: var(--stack-3);
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .section-head--split { grid-template-columns: minmax(0, 1fr); align-items: start; }
  .section-head-aside { border-left: 0; padding-left: 0; border-top: 1px solid var(--line); padding-top: 20px; }

  /* Cover crops harder as the hero narrows, so aim the frame at the planet. */
  .hero-media img { object-position: 30% 55%; }

  /* The positioning note gets its own row rather than fighting for space. */
  .hero-foot { flex-wrap: wrap; }
  .hero-foot-note { order: 3; flex-basis: 100%; }
}

/* --- 900 : mobile navigation takes over --- */
@media (max-width: 900px) {
  .nav-desktop { display: none; }
  .nav-toggle { display: inline-flex; }
  .head-cta { display: none; }

  .foot-nav { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 34px 28px; }
  .w-grid--preview { grid-template-columns: minmax(0, 1fr); }
}

/* --- 720 : phone --- */
@media (max-width: 720px) {
  :root {
    --sec-pad: clamp(68px, 15vw, 96px);

    /* Phone headings only. Every value here is a floor-and-vw pair that the
       desktop scale never reaches, so nothing above 720 moves: at 1440 the
       base clamps in §01 are governed by their vw or max term and these are
       out of the picture entirely.

       The previous note said 11.2vw was the ceiling before the homepage
       hero's authored lines broke mid-phrase. That has not been true for a
       while — measured at 375 the three lines already render as 2, 2 and 3
       boxes, because the copy changed after the figure was taken. Since the
       lines wrap either way, the size was being held down to protect a
       constraint that no longer existed, which is why the headings read
       small on a phone. Raised roughly a fifth across the board.

       Only the size changes. Family, weight, width axis, tracking, colour
       and line-height are all untouched. */
    --fs-display: clamp(2.5rem, 13.2vw, 4.9rem);
    --fs-h2: clamp(2.3rem, 10vw, 3.4rem);
    --fs-h3: clamp(1.72rem, 7.2vw, 2.15rem);
    --fs-h4: clamp(1.3rem, 5.4vw, 1.5rem);
  }

  .hero { min-height: 0; padding-top: calc(var(--head-h) + 46px); }
  .hero-title { letter-spacing: -0.038em; }

  /* Component headings carry their own font-size rather than the h2/h3
     tokens, so none of them followed the scale above — on a phone they were
     the smallest type on the page that still had to read as a heading, down
     to 15px on the accordion rows. Each is lifted by about the same fifth.

     Scoped to this breakpoint so the desktop sizes are untouched, and size is
     the only property named: no family, weight, width axis, tracking, colour
     or line-height appears here. .cw-name and .pillar-title are left alone —
     at 30 and 34px they were already carrying their weight. */
  .cap-name        { font-size: clamp(1.36rem, 5.4vw, 1.6rem); }
  .cap-group-title { font-size: clamp(1.2rem, 4.8vw, 1.32rem); }
  .stage-title     { font-size: clamp(1.24rem, 5vw, 1.4rem); }
  .svc-title       { font-size: clamp(1.6rem, 6.6vw, 1.95rem); }
  .plan-name       { font-size: clamp(1.5rem, 6.2vw, 1.75rem); }
  .legal .h3       { font-size: clamp(1.32rem, 5.4vw, 1.5rem); }

  /* Below 720 the <picture> in every hero swaps to artwork drawn in portrait
     at 853x1844 - a 0.463 ratio against a phone's 0.462 - so cover barely
     crops it and the composition arrives as designed.

     That makes the three re-aiming rules written for the landscape plate
     obsolete here, and actively wrong: object-position pushed the frame at a
     planet that is already in shot, and the homepage's scaleX(-1) mirror
     existed only to move that planet off the left-aligned headline. Both are
     returned to neutral so the art is shown as drawn. The scrims stay - they
     are what keeps the headline legible, not the crop. */
  .hero-media img {
    object-position: 50% 50%;
    transform: none;
    opacity: 0.85;
  }
  .hero-media::after {
    background:
      linear-gradient(180deg, rgba(var(--cosmic-black-rgb), 0.92) 0%, rgba(var(--cosmic-black-rgb), 0.62) 30%, rgba(var(--cosmic-black-rgb), 0.58) 62%, var(--ink-0) 97%);
  }

  /* The closing and contact blocks are a quiet reprise of the hero banner, so
     they follow it onto the portrait plate rather than staying on a landscape
     crop the hero no longer uses. Their scrims and masks are unchanged; only
     the plate behind them moves. The 440w tier is enough here - both are
     heavily scrimmed and read as texture, not as a picture. */
  .closing-media,
  .contact-media {
    background-image:
      linear-gradient(180deg, rgba(var(--cosmic-black-rgb), 0.95) 0%, rgba(var(--cosmic-black-rgb), 0.88) 45%, rgba(var(--cosmic-black-rgb), 0.93) 100%),
      url("../assets/images/hero-banner-mobile-440.jpg");
    background-position: center, 50% 40%;
  }

  .hero-foot { flex-direction: column; align-items: flex-start; gap: 16px; }

  .hero-index { grid-template-columns: minmax(0, 1fr); }
  .hero-index-note { margin-top: 16px; }


  .marquee { padding-block: 13px; }

  .cap-trigger {
    grid-template-columns: 38px minmax(0, 1fr) 20px;
    gap: 12px;
    padding-block: 17px;
  }
  .cap-panel-in { padding-left: 50px; }
  .cap-group-head { flex-direction: column; align-items: flex-start; gap: 6px; }

  .proc { padding-left: 0; }
  .proc-rail { display: none; }
  .proc-step {
    grid-template-columns: minmax(0, 1fr);
    gap: 14px;
  }
  .proc-num { font-size: 2.2rem; }

  .belief-list li {
    grid-template-columns: 34px minmax(0, 1fr);
    gap: 4px 12px;
    align-items: start;
  }
  .belief-txt { grid-column: 2; }

  .pr-tab { grid-template-columns: 34px minmax(0, 1fr); }
  .pr-stage { padding: 26px 22px; }

  .cform-row { grid-template-columns: minmax(0, 1fr); }
  .contact-aside { grid-template-columns: minmax(0, 1fr); }

  /* One project per row on a phone: at two across the frame is under 160px
     tall, which is too small to read a page layout from. */
  .w-grid { grid-template-columns: minmax(0, 1fr); }
  .w-foot { flex-direction: column; align-items: flex-start; }
  .w-foot .w-disc { text-align: left; }
  .w-view { width: 100%; }

  /* The desktop capture is wide; stacked, both get the panel's full width. */
  .lb-shots { grid-template-columns: minmax(0, 1fr); }
  .lb-panel { max-height: 100%; }
  .lb-foot { flex-wrap: wrap; justify-content: center; gap: 10px 18px; }

  /* Cosmic field: less of it, not smaller versions of it -------------------
     A phone shows roughly a fifth of the area a desktop does, so the same
     densities read as considerably busier behind the same amount of type.
     The decoration steps back rather than being scaled down.

     The brand form is the one element that would genuinely get in the way —
     at 72vw it lands squarely behind the headline column, where a desktop
     puts it out to the right of it — so it drops to a third of its opacity
     and pulls further off the edge. The star tiles shrink, which raises the
     count per screen; that is corrected by taking the layer opacity down. */
  .atmos::before {
    width: min(88vw, 460px);
    top: 4vh;
    right: -22vw;
    opacity: 0.018;
  }
  .atmos-wash::before { background-size: 560px 460px; opacity: 0.62; }
  .atmos-wash::after  { background-size: 780px 660px; opacity: 0.5; }
  .site-foot::before { height: 200px; }

  .foot-bottom { flex-direction: column; align-items: flex-start; }
}

/* --- 420 : small phone --- */
@media (max-width: 420px) {
  .brand-logo,
  .site-head.is-stuck .brand-logo { height: 14px; }
  .brand-sub { font-size: 0.5rem; letter-spacing: 0.34em; text-indent: 0.34em; }

  .foot-nav { grid-template-columns: minmax(0, 1fr); }
  .cform-foot { flex-direction: column; align-items: stretch; }
  .cform-foot .btn { width: 100%; }
}

/* Short viewports — do not force the hero to fill the screen */
@media (max-height: 700px) and (min-width: 1025px) {
  .hero { min-height: 0; padding-top: calc(var(--head-h) + 72px); }
}


/* ==========================================================================
   23  REDUCED MOTION & PRINT
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .js [data-reveal] { opacity: 1; transform: none; }
  .js .hero-title .line-in { transform: none; }
  .marquee-track { animation: none; transform: none; }
  .scroll-cue-line::after { animation: none; transform: scaleX(1); }
  .atmos-lens { display: none; }
  .js .cap-panel-in > * { opacity: 1; transform: none; }
  /* Zeroing the duration would still snap the zoom on; remove it outright. */
  .w-tile:hover .w-frame img,
  .w-tile:focus-within .w-frame img { transform: none; }
  .lb-panel { transform: none; }
  /* The button hover needs nothing here any more: the 1px lift this rule used
     to cancel has been removed outright (see §05), and the glow that remains
     is colour rather than motion, so it is left alone. The arrow's nudge is
     motion and is still cancelled, below. */
  .btn:hover .btn-arrow { transform: none; }
  /* Same reasoning for the concept figures: the border and shadow still
     answer the pointer, the lift does not. */
  .cw-fig:hover .cw-shot,
  .cw-fig:focus-within .cw-shot { transform: none; }
}

@media print {
  .atmos, .scroll-rail, .site-head, .mobile-nav, .marquee, .lb { display: none !important; }
  .w-frame { border-color: #ccc; }
  .w-grid { grid-template-columns: minmax(0, 1fr); }
  .cw-shot { border-color: #ccc; box-shadow: none; }
  .cw-lower { grid-template-columns: minmax(0, 1fr); }
  .cw-set { gap: 40px; }
  body { background: #fff; color: #111; }
  .section { padding-block: 24px; }
  a { color: #111; }
  .js [data-reveal] { opacity: 1 !important; transform: none !important; }

  /* The cosmic system is built for a dark screen, so none of it survives onto
     white paper. .atmos is already hidden above, but the section tints, the
     banner scrims and the footer glow are painted by real elements that are
     not — and several of them are now dark enough to print as ink bands.
     .principles is the clearest case: it used to end on a near-white wash and
     now ends on a deep blue, which would lay a solid block behind the
     commitments. All of it is flattened rather than re-toned. */
  .capability, .work, .process, .principles,
  .creed, .pillar--alt, .site-foot, .plan { background: none !important; }
  .site-foot::before,
  .hero-media, .closing-media, .contact-media { display: none !important; }
  .plan { box-shadow: none; }
}


/* ==========================================================================
   24  PRICING PAGE
   ==========================================================================
   Scoped to the Pricing page or to a --plan / --faq modifier. No new tokens,
   no new typeface, no new corner radius — the site has none anywhere — and no
   component that could be expressed with one that already existed.

   Almost all of the page is assembled rather than drawn: the hero is the
   shared .hero--page block from §18 at the About page's headline scale, the
   package buttons are the §05 buttons, the "Most popular" badge is the §19
   .svc-tag, the small print under the Custom plan is .svc-note, the bespoke
   call to action is the §19 .svc-soon panel, the FAQ is the §10 accordion
   driven by the same initCapability module, and the closing block is the same
   .closing every other page ends on.

   What is genuinely new is three things: the plan card, the page-allowance
   band inside it, and the comparison table. Each is built from the existing
   vocabulary — a hairline border on a translucent wash, tracked uppercase
   metadata, serif italic numerals, and the one blue used for accent. */


/* --- The four plans ------------------------------------------------------ */

.plans {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(14px, 1.5vw, 20px);
}

/* A hairline box on a barely-there wash — the same construction as .svc-soon
   and .cform-success. Hover answers with the border and the wash only: the
   lift is reserved for the work captures and the buttons, so a row of four
   cards does not bounce as the pointer crosses it. Because nothing here
   animates a transform, §23 needs no addition. */
.plan {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  /* A blue-black surface lifted just clear of the cosmic ground, over a
     translucent pour of the surface token so the sky still reads faintly
     through the card rather than the card punching a hole in it. */
  background:
    linear-gradient(180deg, rgba(var(--blue-rgb), 0.032), rgba(var(--blue-rgb), 0.008)),
    rgba(10, 15, 23, 0.55);
  box-shadow: 0 18px 44px rgba(var(--cosmic-black-rgb), 0.45);
  padding: clamp(22px, 2.2vw, 32px);
  transition: border-color 0.45s var(--ease), background 0.45s var(--ease);
}
.plan:hover,
.plan:focus-within {
  border-color: var(--cosmic-border);
  background:
    linear-gradient(180deg, rgba(var(--blue-rgb), 0.055), rgba(var(--blue-rgb), 0.014)),
    rgba(10, 15, 23, 0.68);
}

/* The recommended plan. Same recipe as the .pr-stage panel in §15 — a blue
   radial sitting in the top corner over the standard wash — so the emphasis
   is a treatment the site already owns rather than a new one invented for
   this page. The card is not scaled up or lifted: the colour does the work. */
.plan--featured {
  border-color: rgba(var(--blue-rgb), 0.42);
  background:
    radial-gradient(90% 120% at 100% 0%, rgba(var(--blue-rgb), 0.11), transparent 62%),
    linear-gradient(160deg, rgba(245, 245, 245, 0.035), rgba(245, 245, 245, 0.008));
}
.plan--featured:hover,
.plan--featured:focus-within {
  border-color: rgba(var(--blue-rgb), 0.62);
  background:
    radial-gradient(90% 120% at 100% 0%, rgba(var(--blue-rgb), 0.15), transparent 62%),
    linear-gradient(160deg, rgba(245, 245, 245, 0.045), rgba(245, 245, 245, 0.012));
}

/* The numeral and the badge share a row, so the four cards start their names
   on the same line whether or not one of them carries a badge.

   The floor is derived from the badge rather than guessed at: .svc-tag is
   --fs-meta over the inherited 1.62 line-height, plus 6px of padding and 1px
   of border on each side. Because --fs-meta is a clamp, a fixed pixel floor
   would only be correct at one viewport width — at 1440 it left the badged
   card sitting two pixels below its neighbours. */
.plan-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: calc(var(--fs-meta) * 1.62 + 14px);
  margin-bottom: clamp(15px, 1.7vw, 21px);
}
.plan-num {
  font-family: var(--f-serif);
  font-style: italic;
  font-size: 0.95rem;
  color: var(--fg-4);
  transition: color 0.3s var(--ease);
}
.plan:hover .plan-num { color: var(--blue); }
.plan--featured .plan-num { color: var(--blue); }

.plan-name {
  font-size: clamp(1.3rem, 1.9vw, 1.7rem);
  font-weight: 600;
  font-stretch: 106%;
  letter-spacing: -0.028em;
  line-height: 1.1;
  color: var(--fg);
}
.plan-pos {
  margin-top: 10px;
  font-size: var(--fs-small);
  color: var(--fg-3);
}

/* The status line under the Landing Pages name. .svc-tag is inline-flex, so
   it needs a block to sit in before it can take a margin — this is that block
   and nothing else. Nothing existing is touched by it. */
.plan-add { margin-top: 12px; }


/* --- The care statement --------------------------------------------------
   The "why a website needs looking after" copy is capped at 60ch for
   readability, which on a wide screen left the right-hand half of the block
   empty. This puts the one line that block is actually arguing into that
   half, at a size that fills it.

   Source order is statement then copy, because stacked it reads as the
   opening line; on a wide screen the two are placed explicitly into columns
   so the copy keeps the left and the statement takes the right. Both columns
   open on a rule at the same height — the copy's is --line, the statement's
   is the same hairline in accent blue, so they read as one band rather than
   two unrelated boxes. */
/* Two columns, three items, every one placed explicitly. The heading spans
   both tracks on row 1 so the wide layout reads exactly as it did when the
   heading sat outside this grid; the copy and the statement share row 2, which
   is what keeps their two rules on the same line. */
.care-split {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  gap: clamp(30px, 5vw, 84px);
  align-items: start;
}
.care-head             { grid-column: 1 / -1; grid-row: 1; }
.care-split .prev-copy { grid-column: 1; grid-row: 2; }

.care-statement {
  grid-column: 2;
  grid-row: 2;
  border-top: 1px solid rgba(var(--blue-rgb), 0.42);
  padding-top: var(--stack-3);
  font-family: var(--f-sans);
  font-weight: 700;
  font-stretch: 112%;
  /* Sized so the two authored lines hold rather than re-wrapping mid-phrase,
     the same rule the hero headlines follow. "MAINTAINED TO EVOLVE" is the
     binding line at 20 characters. Measured rather than estimated, and the
     measurement has a trap in it: canvas measureText ignores font-stretch, so
     it reports ~454px here while the real line renders ~12% wider at ~512px
     against a 519px column — which is why 2.9vw looked like it fitted and did
     not. These values leave real headroom instead of landing on the edge. */
  font-size: clamp(1.35rem, 2.5vw, 2.3rem);
  line-height: 1.06;
  letter-spacing: 0.005em;
  text-transform: uppercase;
  color: var(--blue);
}

/* One column below the split, and the order changes with it: the statement
   leads, then the question it answers, then the copy. Stacked, a big accent
   line under a smaller heading read as an afterthought rather than as the
   line the block is built on — above it, the heading becomes its answer. */
@media (max-width: 1024px) {
  .care-split { grid-template-columns: minmax(0, 1fr); gap: var(--stack-3); }
  .care-statement        { grid-column: 1; grid-row: 1; }
  .care-head             { grid-column: 1; grid-row: 2; }
  .care-split .prev-copy { grid-column: 1; grid-row: 3; }
}

/* Price and allowance are the two things that have to survive a glance, so
   they sit together above the fold of the card, divided off from the name. */
.plan-price-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin-top: clamp(17px, 1.9vw, 24px);
  padding-top: clamp(15px, 1.7vw, 21px);
  border-top: 1px solid var(--line);
}
.plan-price {
  font-family: var(--f-sans);
  font-weight: 700;
  font-stretch: 110%;
  font-size: clamp(1.9rem, 2.6vw, 2.5rem);
  line-height: 1;
  letter-spacing: -0.038em;
  color: var(--fg);
}
.plan-price-note {
  font-size: var(--fs-meta);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--fg-4);
}

/* A quoted price is words, not a figure, so it is set at the scale of a card
   heading rather than at the scale of a number. At the display size "Custom
   Quote" is wider than a 275px card and would break across two lines.

   The line-height is not decoration: it makes the smaller type occupy the
   same line box as the display price, so a row of cards mixing figures and
   quotes still lines its allowance bands up. 1.45 holds across the whole
   clamp range — 1.72 × 1.45 = 2.494 against 2.5 at the top, 1.32 × 1.45 =
   1.914 against 1.9 at the bottom. Under 1% either end. */
.plan-price--quote {
  font-size: clamp(1.32rem, 1.8vw, 1.72rem);
  line-height: 1.45;
  letter-spacing: -0.028em;
}

/* Prices are not all the same shape — a four-figure sum, a longer one with a
   plus, or two words. Dropping the qualifier onto its own line makes every row
   exactly two lines tall, so the bands below them align without depending on
   how wide any one price happens to set. Without it "₹49,999+ / Scoped" wraps
   in a narrow column while "₹12,999 / One-time" does not, and the Custom card
   alone sits a line low. */
.plan-price-row--stack { row-gap: 5px; }
.plan-price-row--stack .plan-price-note:last-child { flex-basis: 100%; }

/* Where the price opens a block rather than following the name, the rule that
   divides it from the copy above would be a stray line. */
.plan-price-row--lead { margin-top: 0; padding-top: 0; border-top: 0; }

/* The page allowance, stated once and impossible to miss: the only filled
   blue field on the page, using the --blue-veil token that already exists. */
.plan-pages {
  display: block;
  margin-top: clamp(13px, 1.5vw, 17px);
  padding: 11px 12px;
  border: 1px solid rgba(var(--blue-rgb), 0.34);
  background: var(--blue-veil);
  font-size: clamp(0.84rem, 1vw, 0.93rem);
  font-weight: 600;
  font-stretch: 96%;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  text-align: center;
  color: var(--fg);
}

/* The §19 capability list, one column instead of two. */
.svc-caps--plan {
  grid-template-columns: minmax(0, 1fr);
  margin-top: clamp(17px, 1.9vw, 23px);
}
.svc-caps--plan li strong { color: var(--fg); font-weight: 600; }

/* Pinned to the bottom so the four buttons line up however differently the
   feature lists run — the same job .w-foot does on a work tile.

   .btn is white-space: nowrap over overflow: hidden, so a label that outgrows
   its box loses its last letters rather than wrapping. In a four-across card
   the column is ~206px and "Build Something Bespoke" does not fit. Three
   things buy the room back, none of which changes the button: a block button
   centres its own label, so the 1.7em side padding is doing nothing here; the
   card CTAs carry no arrow, which is already how the ghost buttons elsewhere
   on the site are drawn; and wrapping is permitted, so a longer label added
   later takes a second line rather than losing its last word. */
.plan-cta { margin-top: auto; padding-top: clamp(17px, 1.9vw, 25px); }
.plan-cta .btn { padding-inline: 14px; white-space: normal; }
.plan .svc-note { max-width: none; }

/* §19 sizes .svc-soon as copy beside a button. Used as a statement panel with
   no button, its second track would still take the column gap as trailing
   space, so the single-column case is named. */
.svc-soon--solo { grid-template-columns: minmax(0, 1fr); }

/* Where a service leads with a statement line rather than straight into its
   description. .pull-small carries no margin of its own — on the About page
   it is the only thing in its column — so it needs the gap here. */
.svc .pull-small { margin-bottom: var(--stack-2); }

/* Cards sit side by side from 721 up, so the allowance bands have to agree
   across a row. The positioning line is the only thing above them whose height
   varies, and it varies with the grid: measured, it runs to two lines at
   two-across and three at four-across, where the column is at its narrowest.
   Reserving the worst case for each zone holds the bands on one line without
   shortening anyone's copy. Below 721 the cards stack, so the floor is dropped
   rather than left to open a gap under every card on a phone. */
@media (min-width: 721px) {
  .plan-pos { min-height: 3.24em; }   /* 2 lines at the inherited 1.62 */
}
@media (min-width: 1181px) {
  .plan-pos { min-height: 4.86em; }   /* 3 lines */
}

@media (max-width: 1180px) {
  /* Four across stops being readable once each card is under ~230px. */
  .plans { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
  .plans { grid-template-columns: minmax(0, 1fr); gap: clamp(18px, 4vw, 26px); }
}



/* --- Comparison ----------------------------------------------------------
   A real table, drawn with the same hairlines as every other list on the
   site. It is the one block that cannot compress below its content, so it
   scrolls inside its own container rather than forcing the page sideways. */

.cmp-wrap {
  overflow-x: auto;
  overscroll-behavior-x: contain;
}
.cmp {
  width: 100%;
  min-width: 680px;
  border-collapse: collapse;
}

.cmp th,
.cmp td {
  padding: clamp(12px, 1.4vw, 17px) clamp(10px, 1.2vw, 18px);
  border-bottom: 1px solid var(--line-3);
  text-align: center;
  vertical-align: middle;
}
.cmp th:first-child,
.cmp td:first-child { text-align: left; padding-left: 0; }

.cmp thead th {
  border-bottom: 1px solid var(--line-2);
  font-size: var(--fs-meta);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  font-stretch: 92%;
  font-weight: 500;
  color: var(--fg-3);
}
.cmp thead th.is-featured { color: var(--blue-lift); }

.cmp tbody th {
  font-size: var(--fs-small);
  font-weight: 500;
  color: var(--fg-2);
}
.cmp td { font-size: var(--fs-small); color: var(--fg-2); }
.cmp tbody tr { transition: background 0.4s var(--ease); }
.cmp tbody tr:hover { background: rgba(var(--blue-rgb), 0.030); }

/* Carried on a <col>, so the recommended column reads as one field rather
   than as a highlight repeated on every cell. */
.cmp-hi { background: rgba(var(--blue-rgb), 0.055); }

/* The base reset sets svg to display:block, which would defeat the cell's
   text-align — both marks are put back inline so they centre. */
.cmp-yes { display: inline-block; color: var(--blue); vertical-align: middle; }
.cmp-no {
  display: inline-block;
  width: 10px; height: 1px;
  background: var(--fg-4);
  vertical-align: middle;
}

/* Only worth saying where the table actually has to be scrolled. */
.cmp-hint { display: none; }
@media (max-width: 900px) {
  .cmp-hint { display: block; }
}


/* --- FAQ -----------------------------------------------------------------
   The §10 accordion with no teaser column and a question-sized name.

   Both trigger rules have to be written at 0,2,0: §22 restates .cap-trigger
   inside its 1180 and 720 blocks, a media query contributes no specificity,
   and a bare .cap-trigger there would lose to the rule below — leaving the
   FAQ on a four-column grid all the way down. Same trap as .cw--flip in §11. */

.cap-list--faq .cap-trigger {
  grid-template-columns: clamp(46px, 5vw, 74px) minmax(0, 1fr) 28px;
}
.cap-list--faq .cap-name {
  font-size: clamp(1.02rem, 1.5vw, 1.32rem);
  line-height: 1.25;
}
@media (max-width: 720px) {
  .cap-list--faq .cap-trigger {
    grid-template-columns: 38px minmax(0, 1fr) 20px;
    gap: 12px;
  }

  /* The phone heading scale is set in §22, but §24 is declared after it, so
     these two were still winning on specificity and order and stayed at 21
     and 16px while the same components on Services went up. Repeated here,
     where they are the last word. Size only, as above. */
  .plans .plan-name { font-size: clamp(1.5rem, 6.2vw, 1.75rem); }
  .cap-list--faq .cap-name { font-size: clamp(1.3rem, 5.2vw, 1.5rem); }
}


/* --- Pricing: print ------------------------------------------------------
   §23 runs before this section, so the table's own print behaviour is set
   here rather than added there. */

@media print {
  .plans { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .plan { border-color: #ccc; background: none; }
  .plan-pages { border-color: #ccc; background: none; }
  .cmp-wrap { overflow: visible; }
  .cmp { min-width: 0; }
}
