/* AuxaOne
   The logo's gold divider is the page's spine. Every major block is split the way the logo is:
   your side | the line | AuxaOne's side. In the hero, real tasks cross that line.

   Structure and rhythm follow the Outsource Consultants design system (Refero):
   flat surfaces, zero radius, hairline rules, alternating full-bleed tonal bands,
   display type carrying the hierarchy on its own, and a separate micro-label
   register for anything technical. Two registers, no middle voice.

   Colour, type and the logo stay AuxaOne's: navy is the tonal surface,
   ivory is the paper, gold is only ever the line. */

:root {
  --navy: #0B1F33;
  --navy-ink: #C3CDD8;      /* logo tagline colour on navy */
  --navy-dim: #8A99AB;
  --ivory: #F7F4EE;         /* logo paper */
  --paper: #FFFDF8;         /* task slips */
  --slate: #3E4C5C;         /* logo tagline colour on ivory */
  --slate-dim: #66727F;
  --gold: #86642A;          /* gold on ivory */
  --gold-lt: #C9A55A;       /* gold on navy */
  --line-navy: rgba(195, 205, 216, .14);
  --line-ivory: rgba(11, 31, 51, .12);

  --serif: 'Cormorant Garamond', 'Cormorant', Garamond, 'Times New Roman', serif;
  --sans: 'Hanken Grotesk', 'Helvetica Neue', Arial, sans-serif;
  /* the annotation register. Point this at a mono (IBM Plex Mono, JetBrains Mono)
     if you ever want the reference system's full technical look. */
  --micro: var(--sans);

  /* type scale: body is the quiet register, display does the shouting */
  --t-caption: 10.5px;
  --t-micro: 12px;
  --t-body: 16px;
  --t-body-lg: 18px;
  --t-subheading: clamp(21px, 2vw, 25px);
  --t-heading-sm: clamp(24px, 2.5vw, 30px);
  --t-heading: clamp(28px, 3vw, 36px);
  --t-heading-lg: clamp(38px, 6.4vw, 92px);
  --t-display: clamp(50px, 9.1vw, 128px);
  --track: .16em;           /* micro-label tracking */

  /* spacing scale */
  --s6: 6px; --s10: 10px; --s12: 12px; --s15: 15px; --s16: 16px;
  --s18: 18px; --s20: 20px; --s24: 24px; --s26: 26px; --s30: 30px; --s46: 46px;

  --max: 1200px;
  /* the hero carries a picture beside its type, so it gets a wider measure than the
     sections below it. The masthead takes the same one, or the logo stops lining up
     with the headline. */
  --max-hero: 1340px;
  --gut: clamp(20px, 4.5vw, 60px);
  /* distance from the edge of the screen to the wrap's content edge. negate it as a
     margin and an element bleeds to the edge from inside the centred column. */
  --edge: max(var(--gut), calc((100vw - var(--max)) / 2 + var(--gut)));
  --cg: clamp(28px, 4.6vw, 76px);   /* the gap either side of the line */
  --band: clamp(80px, 10vw, 148px); /* section gap */
  --head: 84px;
}

*, *::before, *::after { box-sizing: border-box; }
html { background: var(--navy); -webkit-text-size-adjust: 100%; }
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-stopped { overflow: clip; }
body {
  margin: 0;
  background: var(--navy);
  color: var(--ivory);
  font-family: var(--sans);
  font-size: var(--t-body-lg);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img, svg { max-width: 100%; }
a { color: inherit; }
h1, h2, h3, h4 { text-wrap: balance; }
:focus-visible { outline: 2px solid var(--gold-lt); outline-offset: 4px; border-radius: 0; }
[tabindex="-1"]:focus { outline: none; }
.ivory :focus-visible { outline-color: var(--gold); }
.wrap { max-width: var(--max); margin-inline: auto; padding-inline: var(--gut); }
.hero > .wrap, .masthead > .wrap { max-width: var(--max-hero); }
.skip { position: absolute; left: 16px; top: -60px; z-index: 100; background: var(--ivory); color: var(--navy); padding: 10px 16px; border-radius: 0; font-weight: 600; text-decoration: none; }
.skip:focus { top: 12px; }

/* ---------- the circuit ---------- */
/* One line down the whole page, painted above the band backgrounds and below the
   header. The stroke colour is a gradient whose stops are generated from the real
   band boundaries, so the line switches gold as it crosses from navy to ivory and
   never loses contrast. */
.circuit { position: absolute; top: 0; left: 0; z-index: 5; pointer-events: none; overflow: visible; }
/* round joins, not mitred: the orthogonal route cannot tell the difference at this
   weight, but the drawings spliced into the same path turn hard enough in places to
   throw mitre spikes */
.circuit path { stroke-linecap: square; stroke-linejoin: round; }
/* There is no unlit trace. One was here — it showed the whole route and both drawings
   in advance, which read as current arriving on a circuit that was already there, but it
   also gave the drawings away before the line got to them. Removed on request. */
.c-live { stroke: url(#c-lit); stroke-width: 1.5; }
.c-pulse { stroke: url(#c-hot); stroke-width: 2.4; }
/* the pen tip, at the head of the pulse. It only means anything because the drawings
   are on this same path: one point locates the frontier whether the line is running
   down a margin or going round a gear tooth */
.c-pen { fill: url(#c-lit); opacity: 0; }
/* source geometry for the two drawings; never rendered from its own element */
.fig-src { position: absolute; width: 0; height: 0; overflow: hidden; }
.c-nodes rect { fill: url(#c-lit); opacity: 0; transition: opacity .4s ease; }
.c-nodes rect.on { opacity: 1; }
/* once the circuit is up it supplies the spine, so the static rules stand down —
   otherwise they would read as already-lit stretches of the line. the class is only
   added after a successful build, so no-js and sub-900px keep their rules. */
/* html. prefix is load-bearing: `.ivory .rule` has the same class count and is
   defined later, so without it that rule wins and the spine stays lit */
html.circuit-on .rule-hero,
html.circuit-on .svc-rule,
html.circuit-on .section-head .rule { background: none; }

/* until the intro runs, keep the hero out of sight (falls back to visible after 2.5s) */
.js .hero-grid, .js .brand svg { visibility: hidden; animation: show-anyway 0s 2.5s forwards; }
@keyframes show-anyway { to { visibility: visible; } }

/* ---------- the micro register: labels, tags, annotations ---------- */
.group-title, .copy,
.nav-link a, .foot-meta, .menu-btn span {
  font-family: var(--micro);
  font-size: var(--t-caption);
  font-weight: 500;
  line-height: 1.5;
  letter-spacing: var(--track);
  text-transform: uppercase;
  font-variant-numeric: tabular-nums;
}

/* ---------- buttons and links ---------- */
/* neutral fill, chromatic mark: gold is a square on the button, never the button */
.btn {
  position: relative; isolation: isolate;
  display: inline-flex; align-items: stretch;
  height: 54px; border-radius: 0; border: 1px solid transparent;
  font: 500 15.5px/1 var(--sans); letter-spacing: .005em; text-decoration: none; cursor: pointer;
  background: var(--ivory); color: var(--navy);
  transition: background-color .35s, color .35s, border-color .35s;
}
.btn > span { display: flex; align-items: center; padding-inline: var(--s24); }
/* the glyph square (::after) holds a short ivory dash (::before) that turns a quarter on
   its centre on hover: — becomes |. The dash is its own box laid over the square's centre
   so it can rotate without taking the square with it. 1.5px, the circuit's own weight. */
.btn::after { content: ""; flex: 0 0 auto; width: 54px; background: var(--gold); }
.btn::before {
  content: ""; position: absolute; z-index: 1; top: 50%; right: 18px;   /* 54/2 − 18/2 */
  width: 18px; height: 1.5px; margin-top: -.75px; background: var(--ivory);
  transition: transform .38s cubic-bezier(.7, 0, .2, 1);
}
.btn:hover::before, .btn:focus-visible::before { transform: rotate(90deg); }
.btn:hover, .btn:focus-visible { background: var(--navy); color: var(--ivory); border-color: var(--gold); }
.ivory .btn:hover, .ivory .btn:focus-visible { border-color: var(--navy); }
.btn-small { height: 42px; font-size: 13px; }
.btn-small > span { padding-inline: var(--s16); }
.btn-small::after { width: 42px; }
.btn-small::before { right: 14px; width: 14px; }   /* 42/2 − 14/2 */

.text-link {
  color: var(--ivory); font: 500 15.5px/1.4 var(--sans); text-decoration: none; padding-bottom: 3px;
  background: linear-gradient(currentColor, currentColor) 0 100% / 100% 1px no-repeat;
  transition: background-size .45s cubic-bezier(.7, 0, .2, 1);
}
.text-link:hover { background-size: 0 1px; background-position: 100% 100%; }

/* ---------- header ---------- */
/* content density defines the bar, not a container: flat fill, one hairline */
.masthead {
  position: fixed; inset: 0 0 auto; z-index: 50;
  padding-top: env(safe-area-inset-top, 0px);
  background: var(--navy);
  border-bottom: 1px solid transparent;
  transition: transform .5s cubic-bezier(.7, 0, .2, 1), border-color .3s;
}
.masthead.scrolled { border-bottom-color: var(--line-navy); }
.masthead.hidden { transform: translateY(-100%); }
.masthead-in { display: flex; align-items: center; justify-content: space-between; gap: var(--s24); height: var(--head); }
.brand { display: block; line-height: 0; }
.brand svg { height: 25px; width: auto; display: block; overflow: visible; }
.wm-auxa { fill: #FFFFFF; }
.wm-rule, .wm-one { fill: var(--gold-lt); }
.masthead nav ul { display: flex; align-items: center; gap: var(--s30); margin: 0; padding: 0; list-style: none; }
.nav-link a {
  display: block; color: var(--navy-ink); text-decoration: none; padding-block: var(--s6);
  background: linear-gradient(var(--gold-lt), var(--gold-lt)) 0 100% / 0 1px no-repeat;
  transition: color .25s, background-size .4s cubic-bezier(.7, 0, .2, 1);
}
.nav-link a:hover { color: #fff; background-size: 100% 1px; }

/* menu toggle: paper square + gold glyph square */
.menu-btn {
  display: none; align-items: stretch; height: 42px; padding: 0;
  background: var(--ivory); color: var(--navy); border: 0; border-radius: 0; cursor: pointer;
}
.menu-btn span { display: flex; align-items: center; padding-inline: var(--s15); }
/* the same dash as the buttons while closed; it gives way to × once the menu is open */
.menu-btn i {
  position: relative; display: flex; align-items: center; justify-content: center; width: 42px;
  background: var(--gold); color: var(--ivory); font: 400 16px/1 var(--sans); font-style: normal;
}
.menu-btn i::before {
  content: ""; position: absolute; top: 50%; left: 14px; width: 14px; height: 1.5px;
  margin-top: -.75px; background: var(--ivory);
  transition: transform .38s cubic-bezier(.7, 0, .2, 1), opacity .2s;
}
.menu-btn[aria-expanded="true"] i::before { opacity: 0; }
.menu-btn[aria-expanded="true"] i::after { content: "\00d7"; }
/* only where hover is real: on touch it would stick after the tap */
@media (hover: hover) {
  .menu-btn[aria-expanded="false"]:hover i::before { transform: rotate(90deg); }
}

/* ---------- the line ---------- */
.rule { display: block; width: 1px; background: var(--gold-lt); position: relative; }
.ivory .rule { background: var(--gold); }
.rule i {
  position: absolute; left: 50%; top: 0; width: 3px; height: 150px; margin-left: -1px;
  background: var(--gold-lt); opacity: 0; pointer-events: none;
}
/* reach for a task and the line wakes up, so the drop target teaches itself */
.rule-hero::after {
  content: ""; position: absolute; left: 50%; top: 42%; width: 3px; height: 24%;
  margin-left: -1px; background: var(--gold-lt);
  opacity: 0; transition: opacity .5s cubic-bezier(.7, 0, .2, 1); pointer-events: none;
}

/* ---------- hero ---------- */
/* with the handover stage gone the headline no longer fills a screen on its own, so
   the hero claims one and centres in it — the photograph and the gear need the room */
.hero {
  position: relative; overflow: hidden;
  padding: calc(var(--head) + clamp(36px, 4.4vw, 60px)) 0 clamp(36px, 4vw, 56px);
  min-height: 100vh; display: grid; align-content: center;
}

/* Duotone by blend mode rather than a baked file, so the palette stays editable:
   the photograph recoloured gold and screened over a navy plate, which drops every
   shadow onto exactly the page colour and dissolves the image into the band. */
.hero-media {
  /* 132% of the hero's height so an ±11% drift of itself never uncovers an edge */
  position: absolute; inset: -16% 0; z-index: 0;
  isolation: isolate; background: var(--navy);
}
.hero-media img {
  /* NO zoom: the frame is composed on thirds and cropping into it throws that away */
  width: 100%; height: 100%; object-fit: cover; object-position: 50% 50%;
  display: block; mix-blend-mode: screen;
  filter: grayscale(1) sepia(1) saturate(3.2) hue-rotate(-14deg) contrast(1.14) brightness(.94);
}
.hero::after {
  /* a pool behind the headline column, a floor so the hero settles into the band below,
     and a wash that keeps the left legible while the right stays open for the drawing */
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background:
    radial-gradient(110% 72% at 18% 34%, rgba(11, 31, 51, .8) 0%, rgba(11, 31, 51, .4) 48%, rgba(11, 31, 51, 0) 76%),
    linear-gradient(180deg, rgba(11, 31, 51, .24) 0%, rgba(11, 31, 51, 0) 30%, rgba(11, 31, 51, .3) 62%, rgba(11, 31, 51, .82) 100%),
    linear-gradient(100deg, rgba(11, 31, 51, .9) 0%, rgba(11, 31, 51, .6) 26%, rgba(11, 31, 51, .26) 54%, rgba(11, 31, 51, .14) 78%, rgba(11, 31, 51, .34) 100%);
}
.hero::before {
  /* fine grain so the navy reads as card stock, not a flat screen */
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none; opacity: .07; mix-blend-mode: soft-light;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
/* Type on the left, the scene on the right, the pillars across the foot of both. The
   drawing's column is the wider of the two: it is the thing with detail in it. */
.hero-grid {
  position: relative; z-index: 3;
  display: grid;
  grid-template-columns: minmax(0, 1.75fr) minmax(0, 1fr);
  column-gap: var(--cg);
  align-items: center;
}
/* One cell, not two rows: the drawing's column used to span the headline's row and the
   intro's, so its height (and the margin that parks it) pushed those two apart. */
.hero-copy { grid-column: 1; grid-row: 1; }
/* two lines, and the first one is the louder of the two: the claim, then the scope */
.hero-title {
  margin: 0 0 clamp(26px, 3vw, 42px);
  /* sized to hold "One partner" on one line in this column — it is the measure, not
     the scale, that decides the break, so check both when either changes */
  font: 500 clamp(50px, 8vw, 116px)/.96 var(--serif);
  letter-spacing: -.018em; color: var(--ivory);
  max-width: 22ch;
}
.hero-title .t-lead { display: block; }
.hero-title .t-rest {
  display: block; margin-top: .14em;
  font-size: clamp(24px, 2.9vw, 44px); line-height: 1.08; letter-spacing: -.012em;
  color: var(--navy-ink);
}
.hero-title .line { padding-bottom: .06em; }
/* the One is gold, the same way it is in the logo */
.hero-title .hl-one { color: var(--gold-lt); }
.hero-intro { margin-top: clamp(30px, 3.4vw, 48px); max-width: 44ch; }

/* The drawing's box. It only reserves the room — the stroke is painted by .hero-line,
   which spans the whole hero so the trace can start at the button and end in the scene.
   js/site.js sets its margin-top: the scene is parked so its horizon lands on the
   button's middle, which is what lets the trace between them be a single straight line.
   The width cap is in vh so a short viewport gets a smaller scene rather than a taller
   hero. */
.hero-draw {
  grid-column: 2; grid-row: 1; align-self: start; justify-self: end;
  /* The box is the SCENE, not the canvas: the source is 1920×880 but the people and the
     table only occupy 898×817 of it, so sizing to the canvas drew them at less than half
     the size they could be and left the dead space around them inside the hero. The
     horizon's two tails run outside this box — one back toward the button, one off the
     edge of the screen — which is where the bleed comes from now. Height-first, so a
     short viewport gets a smaller scene rather than a taller hero. */
  /* Its right edge is the measure's right edge, so the margin beside it matches the one
     the headline starts from; it grows leftward into the column gap instead, which is
     where the dead space between the type and the scene used to be. */
  height: clamp(260px, 50vh, 540px); width: auto; aspect-ratio: 898 / 817;
  max-width: calc(100% + 90px);
}
.hero-line { position: absolute; left: 0; top: 0; z-index: 3; pointer-events: none; overflow: visible; }
.hl-path { stroke: var(--gold-lt); stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.hl-pen { fill: var(--gold-lt); opacity: 0; }

/* ---------- the hero's base: three pillars ---------- */
/* laid on the hero's own columns on purpose. The 1px track between them is the one the
   circuit already runs down, so the line passes between pillar two and pillar three and
   never crosses type. Change these tracks and you put the line through a word. */
.hero-trio {
  grid-column: 1 / -1; grid-row: 3; width: 100%;
  /* the circuit needs this gap: it comes back in from the gutter under the drawing and
     the elbow wants ~50px of drop before the turn above the hairline */
  margin-top: clamp(96px, 8vw, 136px);
  display: grid;
  grid-template-columns: minmax(0, 1.32fr) 1px minmax(0, 1fr);
  grid-template-rows: auto auto;
  column-gap: var(--cg); row-gap: clamp(20px, 2.4vw, 32px);
}
/* drawn by the circuit, outward from where the line crosses it — see circuit.render */
.trio-rule { grid-column: 1 / -1; grid-row: 1; height: 1px; background: var(--gold-lt); opacity: .5; transform-origin: 0 50%; }
.js .trio-rule { transform: scaleX(0); }
.trio-pair {
  grid-column: 1; grid-row: 2;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(20px, 2.8vw, 46px);
}
.pillar-side { grid-column: 3; grid-row: 2; }
.pillar h2 { margin: var(--s15) 0 var(--s10); font: 500 var(--t-subheading)/1.1 var(--serif); letter-spacing: -.008em; color: var(--ivory); }
.pillar p { margin: 0; font-size: var(--t-body); line-height: 1.5; color: var(--navy-dim); }
/* the glyphs fade up as the hairline's crawl reaches them; JS owns opacity and y */
.pillar-ico { display: block; width: 26px; height: 26px; fill: none; stroke: var(--gold-lt); stroke-width: 1.4; stroke-linecap: square; stroke-linejoin: miter; }
.js .pillar-ico { opacity: 0; }
.lead { margin: 0; max-width: 50ch; font-size: var(--t-body-lg); line-height: 1.55; color: var(--navy-ink); }
.actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s18) var(--s26); margin-top: var(--s24); }
.rule-hero { grid-column: 2; grid-row: 2; }


/* ---------- bands ---------- */
/* alternating tonal fields, never two of the same tone in a row */
.band { padding-block: var(--band); }
.ivory { background: var(--ivory); color: var(--navy); }
.navy { background: var(--navy); color: var(--ivory); border-top: 1px solid var(--line-navy); }
.section-head {
  display: grid; grid-template-columns: minmax(0, 1.22fr) 1px minmax(0, 1fr); column-gap: var(--cg);
  grid-template-rows: auto auto; align-items: end; margin-bottom: clamp(56px, 7vw, 96px);
}
.section-head h2 {
  grid-column: 1; grid-row: 2; margin: 0;
  font: 500 var(--t-heading-lg)/.96 var(--serif); letter-spacing: -.016em;
}
.section-head .rule { grid-column: 2; grid-row: 1 / 3; align-self: stretch; }
.section-intro { grid-column: 3; grid-row: 2; margin: 0; max-width: 42ch; font-size: var(--t-body-lg); color: var(--navy-ink); }
.ivory .section-intro { color: var(--slate); }
.section-head .statement { font: 500 var(--t-heading)/1.2 var(--serif); color: var(--navy); max-width: 22ch; }

/* ---------- photography ---------- */
/* Never in a card, never with a radius, never contained. A photograph either runs
   the full bleed of the band or it runs off the edge of the screen. Both are graded
   back toward the palette so they sit with the navy rather than shouting over it. */
.shot {
  position: relative; overflow: hidden;
  display: grid; align-items: center;
  min-height: clamp(420px, 62vh, 660px);
  background: var(--navy); border-top: 1px solid var(--line-navy);
}
/* 148% of the section's height, so a ±16% drift of itself (≈24% of the section)
   never uncovers an edge. See the matching numbers in js/site.js. */
.shot-media { position: absolute; inset: -24% 0; z-index: 0; }
.shot-media img { width: 100%; height: 100%; object-fit: cover; display: block; filter: saturate(.78) contrast(1.05); }
.shot::after {
  /* the type side stays on solid navy; the photograph opens up to the right */
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(94deg, var(--navy) 0 16%, rgba(11, 31, 51, .8) 46%, rgba(11, 31, 51, .4) 100%);
}
.shot-in { position: relative; z-index: 2; width: 100%; }
.shot-in .actions { margin-top: clamp(26px, 3vw, 40px); }
.shot-line {
  margin: 0; font: 500 var(--t-heading-lg)/.98 var(--serif);
  letter-spacing: -.016em; color: var(--ivory);
}

/* reasons left, photograph running off the right edge of the screen */

/* ---------- services: a column that stays, a list that moves ---------- */
/* The headline, the copy and the plate sit still while the services run past them.
   The gold spine stretches the whole section rather than stopping at the head. */
.svc-layout {
  display: grid; grid-template-columns: minmax(0, 1fr) 1px minmax(0, 1.3fr);
  column-gap: var(--cg); align-items: start;
}
.svc-rule { grid-column: 2; grid-row: 1; align-self: stretch; }
.svc-aside {
  grid-column: 1; grid-row: 1;
  position: sticky; top: calc(var(--head) + clamp(28px, 4vw, 56px));
}
.svc-aside h2 { margin: 0 0 var(--s26); font: 500 var(--t-heading-lg)/.96 var(--serif); letter-spacing: -.016em; }
/* the shorter this column is, the longer it stays pinned before its grid area runs
   out — so it is kept deliberately lean */
/* one line, at every width it is asked to hold one at: the measure is the column and
   the size is the body's, not the body-large the other section intros use */
.svc-aside .section-intro {
  margin: 0 0 var(--s24); max-width: none;
  /* clamped so it still holds one line in the narrower column just above 900px */
  font-size: clamp(14px, 1.55vw, 16px); line-height: 1.5;
}
/* Sits higher up the column than it used to — the lead-in above it is one line now —
   but not against it: the top two sheets fly ~45px above the drawing box on scroll, so
   this gap is what keeps them off the text. */
.svc-aside .plate { max-width: 260px; margin: var(--s46) 0 0; }
.svc-list { grid-column: 3; grid-row: 1; min-width: 0; }
.svc-list .group { grid-template-columns: minmax(0, 1fr); }
/* the half of the intro that travels with the services. The group below it opens with
   its own hairline, which is the rule under this. */
.svc-note {
  margin: var(--s20) 0 var(--s46);
  max-width: 56ch; font-size: var(--t-body); line-height: 1.55; color: var(--slate);
}

/* runs off the right edge of the screen, from inside the centred column */
/* The plate is clipped; the cut-out standing on it is not — that is the whole point of
   the two boxes. Giving .svc-shot overflow:hidden again would crop the people back
   inside the rectangle. */
.svc-shot {
  position: relative;
  margin: var(--s46) calc(-1 * var(--edge)) var(--s30) 0;
  height: clamp(190px, 20vw, 262px);
}
/* --edge is measured in vw, and 100vw includes a classic scrollbar (Windows), so the
   bleed overshoots the screen by the scrollbar's width and the page scrolls sideways.
   Clip the band at its own edge instead. `clip`, not `hidden`: it makes no scroll
   container, so the sticky aside in this band keeps working. */
#services { overflow-x: clip; }
.svc-shot-frame { position: absolute; inset: 0; overflow: hidden; display: block; }
.svc-shot-bg { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Stands on the plate's bottom edge and breaks its top with the people, not with its
   box. The file carries transparent padding — the ink starts 21% down it and 17% in —
   so the box is deliberately larger than the figures and offset left to compensate:
   at 156% the heads clear the plate's top edge by about 60px and the ink still lands
   inside the plate on both sides. Re-measure both fractions if the cut-out is replaced. */
.svc-shot-cut {
  position: absolute; left: -32px; bottom: 0;
  height: 156%; width: auto; max-width: none; display: block;
}

/* services, grouped by who does the work — full-width rows, not a card grid */
.group { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2.6fr); column-gap: var(--cg); padding-block: var(--s46) var(--s30); border-top: 1px solid var(--line-ivory); }
.group-title { margin: var(--s6) 0 var(--s20); color: var(--gold); }
.services { min-width: 0; }
.service { border-bottom: 1px solid var(--line-ivory); position: relative; }
/* a gold line crawls along each row's divider as it comes into view. absolutely
   positioned so it stays out of the summary's grid. */
.row-line {
  position: absolute; left: 0; right: 0; bottom: -1px; height: 1px;
  background: var(--gold); transform-origin: 0 50%; pointer-events: none;
}
.js .row-line { transform: scaleX(0); }
/* the same crawl on the rules that open a group — the band above its label and the one
   under it — so every hairline the vertical passes is drawn by it, not just the ones
   between rows. Both sit on a 1px border, which is outside the padding box an absolute
   child is positioned against, hence -1px. */
.row-line.top { top: -1px; bottom: auto; }
.service:first-child { border-top: 1px solid var(--line-ivory); }
/* ---------- drawn plates ---------- */
/* Line drawings, no frame and no container — they sit straight on the band.
   The "fill" is the band's own colour, used only so stacked sheets occlude
   each other; nothing here paints a background. */
.plate {
  grid-column: 3; grid-row: 1; align-self: end; justify-self: start;
  width: 100%; max-width: 400px; height: auto; margin-bottom: var(--s30);
  overflow: visible;   /* the top sheets fly outside the viewBox on scroll */
  stroke-width: 1.5; stroke-linecap: square; stroke-linejoin: miter;
  --plate-ink: var(--gold-lt); --plate-bg: var(--navy);
}
.ivory .plate { --plate-ink: var(--gold); --plate-bg: var(--ivory); }
.plate .sheet, .plate .wall { fill: var(--plate-bg); stroke: var(--plate-ink); }
.plate .edge { fill: none; stroke: var(--plate-ink); }

.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
/* one flat colour, hairline, sharp corners — the accent's "icon strokes" role */
.svc-ico {
  width: 21px; height: 21px; flex: 0 0 auto;
  fill: none; stroke: var(--gold); stroke-width: 1.4;
  stroke-linecap: square; stroke-linejoin: miter;
  transform: translateY(3px);
}
/* the glyph holds the gold constant; the title alone carries the open/hover state,
   so there is only ever one thing changing colour in a row */

.service > summary {
  display: grid; grid-template-columns: 21px minmax(0, 1fr) auto;
  align-items: baseline; column-gap: var(--s18);
  padding-block: var(--s20); cursor: pointer; list-style: none;
}
.service > summary::-webkit-details-marker { display: none; }
/* glyphs start undrawn and get drawn on by scroll. dasharray/dashoffset are inherited
   properties, so they reach the paths inside the <use> shadow tree. guarded by .js so
   they are simply visible when gsap never loads. */
.js .svc-ico { stroke-dasharray: 1; stroke-dashoffset: 1; }
.service > summary::after { content: "+"; font: 400 var(--t-subheading)/1 var(--serif); color: var(--gold); }
.service[open] > summary::after { content: "\00d7"; }
.service h4 { margin: 0; font: 500 var(--t-subheading)/1.1 var(--serif); color: var(--navy); transition: color .25s; }
.service > summary:hover h4, .service[open] h4 { color: var(--gold); }
/* the open panel hangs off the title rather than running flush left */
/* hangs off the title, not the glyph — same indent the summary's text column starts at */
.service-body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: var(--cg); padding: 0 0 var(--s26) calc(21px + var(--s18)); }
.service-body p { margin: 0; font-size: var(--t-body); color: var(--slate); max-width: 38ch; }
.service-body ul { margin: 0; padding: 0; list-style: none; font-family: var(--micro); font-size: 11px; font-weight: 500; letter-spacing: .12em; text-transform: uppercase; line-height: 2.1; color: var(--slate-dim); }

/* process */
/* This head breaks its own headline (From first call / to a running team), and that
   second line will not fit the standard 1.22fr column at --t-heading-lg. The column
   takes the room from the intro beside it rather than the headline dropping a size:
   every section head on the page is set at the same size, and that is the hierarchy. */
#process .section-head { grid-template-columns: minmax(0, 2.6fr) 1px minmax(0, 1fr); }
/* why */
/* The one head on the page that breaks its headline in two *and* keeps its intro beside
   it. Stacking them (headline across the measure, intro underneath on the right) left a
   band of empty ivory under the headline and set the intro adrift from it. Both drop a
   step in size instead, so the two lines fit a wider first column and the two blocks
   come out close to the same height — bottom-aligned by the head's own `align-items`,
   which puts their tops within a line of each other too.
   The margin below is the only room the circuit has to turn: the elbow between the
   gutter and the gear's column has to fit under the head and clear of the quadrants'
   rules, and under about 110px it degenerates into a vertical that ignores the turn
   (see `dy < 48` in site.js). Do not shrink it further. */
#why .section-head { grid-template-columns: minmax(0, 1.78fr) 1px minmax(0, 1fr); margin-bottom: clamp(120px, 8.4vw, 150px); }
#why .section-head h2 { font-size: clamp(34px, 5.3vw, 76px); }
#why .section-head .statement { font: 500 clamp(20px, 2.05vw, 27px)/1.32 var(--serif); max-width: 26ch; }
.steps { position: relative; list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); column-gap: var(--cg); }
.track { position: absolute; left: 0; right: 0; top: 46px; height: 1px; background: var(--line-navy); }
.track i { display: block; height: 100%; background: var(--gold-lt); transform-origin: 0 50%; }
.js .track i { transform: scaleX(0); }
.step { position: relative; min-width: 0; }
/* one per step, lit as the track's fill reaches it — the same beat the hero's pillar
   glyphs have, driven by the .on class the track's scrub already sets */
.step-ico {
  display: block; width: 26px; height: 26px; margin: var(--s18) 0 0;
  fill: none; stroke: var(--gold-lt); stroke-width: 1.4;
  stroke-linecap: square; stroke-linejoin: miter;
}
.js .step-ico { opacity: 0; transform: translateY(10px); transition: opacity .55s ease, transform .55s cubic-bezier(.2, .7, .3, 1); }
.js .step.on .step-ico { opacity: 1; transform: none; }
.step-n { position: relative; z-index: 1; display: inline-block; padding-right: var(--s18); background: var(--navy); font: 500 clamp(64px, 7vw, 96px)/1 var(--serif); color: var(--navy-dim); transition: color .6s; }
.js .step-n { color: rgba(195, 205, 216, .28); }
.js .step.on .step-n { color: var(--gold-lt); }
.step h3 { margin: var(--s26) 0 var(--s10); font: 500 var(--t-heading-sm)/1.12 var(--serif); color: var(--ivory); }
.step p { margin: 0; font-size: var(--t-body); color: var(--navy-ink); max-width: 28ch; }

/* why */
/* Four quadrants around the gear. The middle track is the drawing's own box and the
   line's own column — change these tracks and the line stops meeting the gear. */
.reasons {
  display: grid;
  grid-template-columns: minmax(0, 1fr) clamp(220px, 23vw, 330px) minmax(0, 1fr);
  grid-template-rows: auto auto;
  column-gap: var(--cg); row-gap: clamp(40px, 5.6vw, 86px);
  align-items: start;
}
.reason { position: relative; min-width: 0; padding-top: var(--s24); border-top: 1px solid var(--line-ivory); }
.reason:nth-of-type(1) { grid-column: 1; grid-row: 1; }
.reason:nth-of-type(2) { grid-column: 3; grid-row: 1; }
.reason:nth-of-type(3) { grid-column: 1; grid-row: 2; }
.reason:nth-of-type(4) { grid-column: 3; grid-row: 2; }
/* the gear's box: the drawing is mapped into it, and it sets the aspect the clipped
   gear actually draws at (its height is 1.177 of its width) */
.why-core { grid-column: 2; grid-row: 1 / span 2; align-self: center; aspect-ratio: 62 / 73; }
/* lit as the line comes down past each quadrant — same beat as the hero's pillars */
.reason-ico {
  display: block; width: 26px; height: 26px; margin: 0 0 var(--s18);
  fill: none; stroke: var(--gold); stroke-width: 1.4;
  stroke-linecap: square; stroke-linejoin: miter;
}
.js .reason-ico { opacity: 0; transform: translateY(10px); transition: opacity .55s ease, transform .55s cubic-bezier(.2, .7, .3, 1); }
.js .reason.on .reason-ico { opacity: 1; transform: none; }
.reasons h3 { margin: 0 0 var(--s12); font: 500 var(--t-heading-sm)/1.12 var(--serif); color: var(--navy); }
.reasons p { margin: 0; font-size: var(--t-body); color: var(--slate); }

/* contact */
/* The headline holds while the section runs past it — the services aside's move,
   repeated so the page ends the way its middle behaved. The min-height is what it holds
   *for*: the grid is otherwise only as tall as the headline and there is nothing to
   stick through. It also buys the empty navy the address sits alone in. */
.contact-layout {
  grid-template-columns: minmax(0, 1.22fr) 1px minmax(0, 1fr);
  grid-template-rows: none; align-items: start; margin-bottom: 0;
  min-height: clamp(420px, 66vh, 700px);
}
.contact-aside {
  grid-column: 1; grid-row: 1;
  position: sticky; top: calc(var(--head) + clamp(28px, 4vw, 56px));
}
.contact-layout .rule { grid-column: 2; grid-row: 1; align-self: stretch; }
.contact-body { grid-column: 3; grid-row: 1; }
.contact-body p { margin: 0 0 var(--s26); color: var(--navy-ink); max-width: 40ch; font-size: var(--t-body-lg); }
/* The letter slides in as the section comes up — scrubbed, not looped, so it is the
   reader doing it. Stroked like the circuit rather than like the source icon: the
   drawing is the site's hairline register, not a UI glyph. */
.env {
  display: block; width: clamp(118px, 12.5vw, 172px); height: auto;
  margin: 0 0 var(--s30);
  fill: none; stroke: var(--gold-lt); stroke-width: 6;
  stroke-linecap: square; stroke-linejoin: round;
}
.email-line { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s12) var(--s16); }
.email {
  font: 500 clamp(26px, 2.6vw, 36px)/1.2 var(--serif); color: #fff; text-decoration: none; padding-bottom: 2px;
  background: linear-gradient(var(--gold-lt), var(--gold-lt)) 0 100% / 100% 1px no-repeat;
  transition: background-size .45s cubic-bezier(.7, 0, .2, 1);
}
.email:hover { background-size: 0 1px; background-position: 100% 100%; }
/* A square beside the address rather than a labelled control under it. Sized off the
   address's own type so the two read as one line; the label it used to carry lives in
   aria-label, and the result of pressing it in a live region. */
.copy {
  display: inline-grid; place-items: center; position: relative;
  width: clamp(30px, 2.4vw, 36px); height: clamp(30px, 2.4vw, 36px); padding: 0;
  background: none; border: 1px solid rgba(201, 165, 90, .45); border-radius: 0;
  cursor: pointer; transition: border-color .25s;
}
.copy:hover, .copy:focus-visible { border-color: var(--gold-lt); }
.copy-ico {
  grid-area: 1 / 1; width: 56%; height: 56%;
  fill: none; stroke: var(--gold-lt); stroke-width: 1.5;
  stroke-linecap: square; stroke-linejoin: miter;
  transition: opacity .2s ease;
}
.copy-tick { opacity: 0; }
.copy.done .copy-ico { opacity: 0; }
.copy.done .copy-tick { opacity: 1; }
/* the only thing a screen reader gets back from the press */
.copy-say { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* footer */
/* Centred because the run ends inside it: the line comes down the page, draws the
   lockup's divider, and the two words arrive either side of it. */
.foot { padding-block: clamp(64px, 6.5vw, 96px) clamp(56px, 6vw, 80px); border-top: 1px solid var(--line-navy); }
.foot-in { display: flex; flex-direction: column; align-items: center; gap: var(--s24); }
.foot-logo { display: block; line-height: 0; }
.foot-logo svg { width: min(420px, 82vw); height: auto; display: block; }
.foot-meta { margin: 0; line-height: 2; color: var(--navy-dim); text-align: center; }
/* the divider is not filled by the logo — the circuit draws it, on its last 45px */
html.circuit-on .fl-bar { fill: none; }
/* and the words arrive either side of it as it lands. The shift is in the logo's own
   user units, so it stays the same fraction of the mark at every width. */
.js .fl-a, .js .fl-o, .js .fl-tag {
  transform-box: view-box; opacity: 0;
  transition: opacity .85s ease, transform .85s cubic-bezier(.2, .7, .3, 1);
}
.js .fl-a { transform: translateX(80px); }
.js .fl-o { transform: translateX(-80px); }
.js .fl-tag { transition-delay: .22s; }
.js .foot-logo.on .fl-a,
.js .foot-logo.on .fl-o,
.js .foot-logo.on .fl-tag { opacity: 1; transform: none; }

/* ---------- smaller screens: the line turns horizontal ---------- */
@media (max-width: 900px) {
  .masthead nav {
    position: fixed; left: 0; right: 0; top: calc(var(--head) + env(safe-area-inset-top, 0px));
    background: var(--navy); border-block: 1px solid var(--line-navy); display: none;
  }
  [data-nav="open"] .masthead nav { display: block; }
  .masthead nav ul { flex-direction: column; align-items: stretch; gap: 0; padding: 0 var(--gut) var(--s24); }
  .nav-link { border-bottom: 1px solid var(--line-navy); }
  .nav-link a { padding-block: var(--s18); font-size: var(--t-micro); background: none; }
  .masthead nav li:last-child { padding-top: var(--s20); }
  .masthead nav .btn { display: flex; width: 100%; }
  .masthead nav .btn > span { flex: 1; }
  .menu-btn { display: flex; }

  .hero-grid { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; }
  .hero-title, .hero-intro, .hero-trio { grid-column: 1; grid-row: auto; }
  .hero-trio { grid-template-columns: minmax(0, 1fr); row-gap: var(--s26); }
  /* grid-row must be cleared too, or the side pillar keeps its desktop row and lands
     on top of the first one */
  .trio-pair { grid-column: 1; grid-row: auto; grid-template-columns: minmax(0, 1fr); row-gap: var(--s26); }
  .pillar-side { grid-column: 1; grid-row: auto; }
  /* no circuit down here to draw them, so they are simply there */
  .js .trio-rule { transform: none; }
  .js .pillar-ico, .js .reason-ico { opacity: 1; transform: none; }
  .hero-title { max-width: none; }
  .rule-hero { display: none; }
  /* a phone column is too narrow for the circuit to route around the type */
  .circuit { display: none; }
  /* and too narrow for the scene and its trace: the stroke needs a run at it */
  .hero-draw, .hero-line { display: none; }

  .section-head { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; row-gap: var(--s26); }
  /* the id selector upstairs outranks the one above, and the two reasons it exists for
     — a column wide enough for the headline's second line, and room under it for the
     circuit's elbow — are both gone in one column with no line to draw */
  #why .section-head { grid-template-columns: minmax(0, 1fr); margin-bottom: clamp(56px, 7vw, 96px); }
  #why .section-head h2 { font-size: var(--t-heading-lg); }
  .section-head h2, .section-intro, .contact-body, .plate { grid-column: 1; grid-row: auto; }
  .plate { max-width: 250px; margin: var(--s30) 0 0; }
  .section-head .rule { grid-column: 1; grid-row: auto; width: 64px; height: 1px; }
  .group { grid-template-columns: minmax(0, 1fr); }

  .svc-layout { grid-template-columns: minmax(0, 1fr); }
  .svc-rule { display: none; }
  /* no circuit down here to draw them, so they are simply there */
  .js .row-line { transform: none; }
  .svc-aside { position: static; grid-column: 1; grid-row: auto; margin-bottom: var(--s46); }
  .svc-aside .plate { max-width: 250px; }
  .svc-list { grid-column: 1; grid-row: auto; }
  /* a phone-width slice of a 1800px strip lands on empty navy, so bias the crop
     toward the filaments */
  .svc-shot { margin-inline: calc(-1 * var(--gut)); height: clamp(150px, 34vw, 200px); }
  .svc-shot img { object-position: 78% 50%; }

  .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s46); }
  .track { display: none; }
  .reasons { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .reason:nth-of-type(n) { grid-column: auto; grid-row: auto; }
  /* no line down here to draw it */
  .why-core { display: none; }

  .shot { min-height: clamp(380px, 56vh, 500px); }

  /* no line down here to draw the divider or walk the words in */
  html.circuit-on .fl-bar { fill: var(--gold-lt); }
  .js .fl-a, .js .fl-o, .js .fl-tag { opacity: 1; transform: none; }
  .contact-layout { grid-template-columns: minmax(0, 1fr); min-height: 0; row-gap: var(--s30); }
  .contact-aside, .contact-body { grid-column: 1; grid-row: auto; position: static; }
}
@media (max-width: 600px) {
  body { font-size: 17px; }
  .hero-title { font-size: clamp(42px, 11.6vw, 58px); }
  .service-body { grid-template-columns: minmax(0, 1fr); row-gap: var(--s16); padding-left: var(--s16); }
  .steps, .reasons { grid-template-columns: minmax(0, 1fr); }
  .foot-meta { text-align: center; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: .01ms !important; animation-duration: .01ms !important; }
  /* nothing draws them on, so they must start drawn */
  .js .svc-ico { stroke-dasharray: none; stroke-dashoffset: 0; }
  .c-pulse, .c-pen { display: none; }
  .js .pillar-ico, .js .reason-ico { opacity: 1; transform: none; }
  .js .trio-rule { transform: none; }
  .js .fl-a, .js .fl-o, .js .fl-tag { opacity: 1; transform: none; }
}