/* ==========================================================================
   APPA design v2 — built from design/rev3-concept.html (revision 3, reviewed).
   Loaded INSTEAD of site.css when DESIGN=v2. tokens.css is shared by both
   designs and is not modified here: the palette, the per-brand themes and the
   contrast rules are the same in v1 and v2.

   Differences from the concept, all deliberate:
   - Self-hosted Cormorant Garamond and Mulish. The concept's Google Fonts link
     is not used; the fonts are already in the repo.
   - Every Cormorant use is SemiBold 600 (--display-weight), not the concept's
     Light 300. Decided 17 Sept.
   - Real logo SVGs replace the concept's typed "APPA" / "GW" marks.
   - Brand fills take --brand-on from tokens.css rather than the concept's
     hardcoded #fff, so Clay Stone and Antique Gold get ink text.
   - No `html { overflow-x: clip }`. v1 carries that rule; v2 fits by design.
   - Flat brand colours on the material board (20 Sept, client feedback). The
     concept's metal sheen / stone dot texture on the four business tiles is
     gone; each tile is a single flat fill.
   - No texture anywhere (20 Sept, client feedback). The .stone dot texture
     that was still on .board__appa (the closing CTA bar) is gone too; that
     bar keeps its shade-4 flat fill.
   ========================================================================== */

/* The upright face is declared in tokens.css and shared. The italic is v2 only:
   v2 sets italic closing lines and pull quotes in real Cormorant italic rather
   than letting the browser synthesise a slant from the upright. Same family,
   same release (Version 4.001), same OFL as OFL-Cormorant.txt. */
@font-face {
  font-family: "Cormorant Garamond";
  src: url("/assets/fonts/cormorant-italic-var.woff2") format("woff2");
  font-weight: 300 700; font-style: italic; font-display: swap;
}

:root {
  /* One value drives every Cormorant use in v2. */
  --display-weight: 600;

  /* Surfaces, from the concept. Brand colours come from tokens.css. */
  --v2-paper:  #F4F2EE;
  --v2-line:   #CFCBC4;
  --v2-soft:   #5E6166;
  --v2-body:   #3C3F44;
  --v2-black:  #0E0E0E;

  --gut: clamp(20px, 4.4vw, 64px);
  --v2-wrap: 1360px;
  --mark-src: url("/assets/logos/appa-stacked-white.svg");
}

/* ==========================================================================
   Shade scale — one brand colour per page
   ==========================================================================
   A page uses its own brand colour, shades of it, and neutrals. Nothing else.
   Mixed brand colours appear only where the four businesses are deliberately
   shown side by side: the companies board, the footer brand dots, the
   projects-strip category dots and the brand switcher.

   TEXT RULE, and it is not a guideline:
     shades 1-4  ink   (--ink)
     shades 5-6  white
   White on shades 1-4 is allowed for large serif headings (>= 24px, which
   need 3:1) and NEVER for body text. Measured, every scale below:
     shade 1-4 on ink   4.66 : 1  or better
     shade 5-6 on white 5.32 : 1  or better
   So a role that flips text colour must flip which end of the scale it sits
   on -- do not keep the background and change the text.

   APPA's six steps are the client's own values, supplied 18 Sept.
   ========================================================================== */
[data-theme="appa"] {
  --shade-1: #E8E3DD;  /* 01 Mist       ink   13.07:1 */
  --shade-2: #D1CCC4;  /* 02 Sand       ink   10.44:1 */
  --shade-3: #B7AEA2;  /* 03 Clay       ink    7.61:1 */
  --shade-4: #928877;  /* 04 Clay Stone ink    4.77:1  (white is 3.49 -- fails) */
  --shade-5: #6F6558;  /* 05 Taupe      white  5.71:1 */
  --shade-6: #4A433B;  /* 06 Deep Stone white  9.73:1 */
}

/* provisional — client to supply
   Derived from each brand colour at APPA's own lightness steps (OKLCH: the
   brand's hue kept, chroma following APPA's curve), so the brand colour itself
   stays in its scale unchanged -- at step 05 for Dark Copper, 06 for Petrol
   Blue and Charcoal, 04 for Antique Gold. Contrast is measured, not assumed,
   and every step satisfies the text rule above. */
[data-theme="goodworks"] {
  --shade-1: #F7DFCD;  /* ink   13.01:1 */
  --shade-2: #E4C6B0;  /* ink   10.32:1 */
  --shade-3: #D3A582;  /* ink    7.52:1 */
  --shade-4: #B67A48;  /* ink    4.66:1 */
  --shade-5: #926037;  /* white  5.32:1  <- Dark Copper */
  --shade-6: #5C3C22;  /* white  9.88:1 */
}
[data-theme="auspacificworks"] {
  --shade-1: #C1EBFF;  /* ink   13.17:1 */
  --shade-2: #A0D5F3;  /* ink   10.56:1 */
  --shade-3: #60BBEB;  /* ink    7.78:1 */
  --shade-4: #0096D7;  /* ink    5.04:1 */
  --shade-5: #0071A6;  /* white  5.37:1 */
  --shade-6: #00597C;  /* white  7.72:1  <- Petrol Blue */
}
[data-theme="prestigeworks"] {
  --shade-1: #EEE3CB;  /* ink   13.09:1 */
  --shade-2: #D9CCAE;  /* ink   10.48:1 */
  --shade-3: #C2AD7D;  /* ink    7.60:1 */
  --shade-4: #AF924D;  /* ink    5.59:1  <- Antique Gold */
  --shade-5: #7B632A;  /* white  5.74:1 */
  --shade-6: #51421E;  /* white  9.78:1 */
}
[data-theme="allianceworks"] {
  --shade-1: #E1E4E9;  /* ink   13.08:1 */
  --shade-2: #C9CDD3;  /* ink   10.44:1 */
  --shade-3: #AAB0BA;  /* ink    7.64:1 */
  --shade-4: #828A97;  /* ink    4.79:1 */
  --shade-5: #616772;  /* white  5.69:1 */
  --shade-6: #4C5057;  /* white  8.10:1  <- Charcoal */
}

/* Surface roles. Components reference these, never a shade number and never a
   brand hex, so re-pointing a role re-colours every page that uses it. */
:root {
  --zone-bg:    var(--shade-5);  --zone-fg:  #fff;        /* key-point section ground */
  --steps-bg:   var(--shade-6);  --steps-fg: #fff;        /* the process list */
  --band-bg:    var(--shade-5);  --band-fg:  #fff;        /* callout bands */
  --cta-bg:     var(--shade-6);  --cta-fg:   #fff;        /* final call to action */
  --panel-a-bg: var(--shade-1);  --panel-a-fg: var(--ink);
  --panel-b-bg: var(--shade-6);  --panel-b-fg: #fff;
  --panel-c-bg: var(--shade-2);  --panel-c-fg: var(--ink);
  --cap-bg:     var(--shade-2);  --cap-fg:   var(--ink);  /* process photo caption */
  --accent:     var(--shade-6);                           /* italic lines, pull quotes */
  --accent-soft: var(--shade-3);                          /* quote mark, icon rules */
  --on-dark-soft: rgba(255, 255, 255, .85);               /* body copy on 5-6 */

  /* Held constant across brands on purpose, and neither is a brand surface:
     a focus ring people recognise, and an error colour that must not become
     whatever the current brand happens to be. */
  --focus: var(--petrol-blue);
  --alert: var(--dark-copper);
}

/* The stacked mark that the hero cut-out is cut from, per brand. */
[data-theme="appa"]            { --mark-src: url("/assets/logos/appa-stacked-white.svg"); }
[data-theme="goodworks"]       { --mark-src: url("/assets/logos/goodworks-stacked-white.svg"); }
[data-theme="auspacificworks"] { --mark-src: url("/assets/logos/auspacificworks-stacked-white.svg"); }
[data-theme="prestigeworks"]   { --mark-src: url("/assets/logos/prestigeworks-stacked-white.svg"); }
[data-theme="allianceworks"]   { --mark-src: url("/assets/logos/allianceworks-stacked-white.svg"); }

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0; background: #fff; color: var(--ink);
  font-family: var(--font-body); font-size: 17px; line-height: 1.72;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
h1, h2, h3 {
  font-family: var(--font-display); font-weight: var(--display-weight);
  line-height: 1.04; letter-spacing: -.015em; margin: 0; color: inherit;
}
p { margin: 0 0 1em; }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
/* A mouse click must never leave a ring behind. Browsers still paint their own
   default outline on <summary> and <button> after a click, so it is cleared for
   the focus-but-not-focus-visible case only; keyboard focus keeps its ring. */
a:focus:not(:focus-visible),
button:focus:not(:focus-visible),
summary:focus:not(:focus-visible),
[tabindex]:focus:not(:focus-visible) { outline: none; }
.more summary:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }

.wrap { max-width: var(--v2-wrap); margin: 0 auto; padding-inline: var(--gut); }
/* padding-inline, never the `padding` shorthand: an inline `padding` on .wrap
   zeroes the responsive gutter. That cost a round trip on 14 Sept. */

.sr, .visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip {
  position: absolute; left: 1rem; top: 0; z-index: 99;
  background: var(--ink); color: #fff; padding: .5rem 1rem;
  transform: translateY(-200%);
}
.skip:focus { transform: none; }

/* Nothing in a grid or flex row may refuse to shrink: that is what pushes a
   page sideways. Long unbroken strings wrap instead of widening the row. */
.split__grid > *, .board__appa .wrap > *, .steps__head > *, .gets__head > *,
.kp > li, .icons > li, .stick__grid > *, .end .wrap > *, .foot__tb > *,
.pj__top > *, .hdr__inner > *, .intro__grid > *, .feat > *, .how__top > * { min-width: 0; }
h1, h2, h3, p, .v2-stmt, .kp b, .work h3 { overflow-wrap: break-word; }

/* ---------- shared type ---------- */
.eyebrow {
  display: block; font-size: 12px; letter-spacing: .2em; text-transform: uppercase;
  font-weight: 600; margin: 0 0 18px; color: var(--v2-soft);
}
/* Eyebrows on a shade 5-6 ground. 12px is body text, so it needs 4.5:1:
   .85 white reaches 4.66:1 on shade 5, the lightest ground any of these
   sit on. .7 and .75 were tuned against Petrol Blue and do not hold here. */
.eyebrow--light { color: var(--on-dark-soft); }
.lead {
  font-family: var(--font-display); font-size: clamp(24px, 2.2vw, 32px);
  line-height: 1.3; font-weight: var(--display-weight); color: var(--ink); margin-bottom: 22px;
}
.prose p:last-child { margin-bottom: 0; }

/* Italic closing lines / statements. Real Cormorant italic, same 600 weight. */
.v2-stmt {
  font-family: var(--font-display); font-style: italic; font-weight: var(--display-weight);
  font-size: clamp(22px, 2vw, 30px); line-height: 1.25; max-width: 36ch;
  margin: clamp(40px, 5vw, 72px) 0 0;
}

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; gap: 12px; padding: 15px 24px;
  font-weight: 600; font-size: 15px; background: #fff; color: var(--ink);
  border: 1px solid var(--ink); transition: background .2s, color .2s;
}
.btn:hover { background: var(--ink); color: #fff; }
.btn--solid { background: var(--shade-6); color: #fff; border-color: var(--shade-6); }
.btn--solid:hover { background: var(--shade-5); color: #fff; }
/* Brand fills always take their readable text colour from tokens.css. */
.btn--brand, .btn--brand-solid, .btn--primary { background: var(--brand); color: var(--brand-on); border-color: var(--brand); }
.btn--brand:hover, .btn--brand-solid:hover, .btn--primary:hover { filter: brightness(1.08); background: var(--brand); color: var(--brand-on); }
.btn--outline-light { background: transparent; color: #fff; border-color: rgba(255,255,255,.8); }
.btn--outline-light:hover { background: #fff; color: var(--ink); }
/* dark-outline sits on light ground (the holding pages' "Back to APPA Group"). */
.btn--dark-outline { background: transparent; color: var(--ink); border-color: var(--ink); }
.btn--dark-outline:hover { background: var(--ink); color: #fff; }
.btn--dark { background: var(--bar); color: #fff; border-color: var(--bar); }
.btn--dark:hover { background: #000; color: #fff; }
.link {
  display: inline-flex; align-items: center; gap: 12px; font-weight: 600; font-size: 15px;
  border-bottom: 1px solid currentColor; padding-bottom: 3px;
}
.link svg, .btn svg { width: 18px; height: 10px; flex: none; transition: transform .2s; }
.link:hover svg, .btn:hover svg { transform: translateX(4px); }
.actions, .hero__acts { display: flex; gap: 26px; align-items: center; flex-wrap: wrap; margin-top: 32px; }

/* ---------- placeholder labelling (same switch as v1: site.showPlaceholderTags) ---------- */
.ph-wrap { display: block; position: relative; }
.ph-tag {
  position: absolute; left: 0; top: 0; z-index: 5; max-width: calc(100% - 2px);
  background: rgba(20,19,17,.82); color: #fff; font-family: var(--font-body);
  font-size: 10.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  line-height: 1.45; padding: 6px 10px; pointer-events: none;
}
.ph-tag::before { content: "Placeholder — "; opacity: .7; }

/* An empty image slot in v2 is never a grey box. It is the brand colour, or
   paper, at the shape the photo will take — the concept's "Photos: off" state.
   Still labelled, so an unfilled slot reads as "photo goes here". */
.img-pending { position: relative; background: var(--brand); width: 100%; height: 100%; }
.img-pending--paper { background: var(--v2-paper); }
.img-pending--fill { position: absolute; inset: 0; }

/* ---------- reveal on scroll (same contract as v1: hidden only once JS confirms) ---------- */
.js .rv-on { opacity: 0; transform: translateY(22px); transition: opacity .8s ease, transform .8s cubic-bezier(.2,.7,.3,1); }
.js .rv-on.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js .rv-on { opacity: 1; transform: none; transition: none; }
  html { scroll-behavior: auto; }
}

/* ==========================================================================
   Brand switcher
   ========================================================================== */
.switch { display: grid; grid-template-columns: repeat(5, 1fr); }
.sw {
  --c: var(--brand); background: var(--c); color: #fff; min-height: 60px;
  display: flex; align-items: center; justify-content: center; gap: 12px; padding: 8px 10px;
  border-right: 1px solid rgba(255,255,255,.28); transition: background .2s, color .2s;
  box-shadow: inset 0 0 0 0 var(--c); min-width: 0;
}
.sw:last-child { border-right: 0; }
/* One of the four places mixed brand colours are correct: every business is
   shown at once, so each tab must be its own colour (see the shade-scale
   note). The others are the companies board, the footer dots and the
   projects-strip category dots. */
.sw[data-theme="appa"]            { --c: var(--clay-stone); }
.sw[data-theme="goodworks"]       { --c: var(--dark-copper); }
.sw[data-theme="auspacificworks"] { --c: var(--petrol-blue); }
.sw[data-theme="prestigeworks"]   { --c: var(--antique-gold); }
.sw[data-theme="allianceworks"]   { --c: var(--charcoal); }
/* The logos scale down inside their cell. A flex item keeps min-width:auto by
   default, which makes an image refuse to shrink below its intrinsic width —
   that is what pushed the switcher off-screen under 420px. The mark files are
   wide (the APPA mark is roughly 3.3:1), so they need max-height, not height. */
.sw img { width: auto; height: auto; max-width: 100%; max-height: 26px; min-width: 0; }
.sw__h, .sw__m { display: none; }
.sw__h--white { display: block; }
.sw:hover, .sw:focus-visible, .sw.on {
  background: var(--tint); color: var(--ink); box-shadow: inset 0 -4px 0 var(--c);
}
/* Scoped to the width where .sw__h is actually shown (>760px, see the
   max-width:760px block below). Unscoped, this outranks that block's
   .sw__h--colour { display: none } by specificity ((0,2,0) beats (0,1,0))
   regardless of source order, so the active/hover tab kept showing the full
   lockup under 760px on top of the mark — two logos in one tab. */
@media (min-width: 761px) {
  .sw:hover .sw__h--white, .sw:focus-visible .sw__h--white, .sw.on .sw__h--white { display: none; }
  .sw:hover .sw__h--colour, .sw:focus-visible .sw__h--colour, .sw.on .sw__h--colour { display: block; }
}
.sw:focus-visible { outline-offset: -4px; }

/* ==========================================================================
   Header
   ========================================================================== */
/* The header shares the page wrap, so the logo lines up with the content below.
   That leaves 1232px of content, and the full-size nav needed 1283px — which is
   why it never fit and "Careers" sat under Enquire from 1501px up. There is no
   full-size state any more: the nav is one size at every width, needing about
   1068px, which the 1232px wrap clears comfortably. */
.hdr {
  background: #fff; border-bottom: 1px solid var(--v2-line);
  position: sticky; top: 0; z-index: 30;
  transition: background .3s, border-color .3s, box-shadow .3s;
}
.hdr__inner { display: flex; align-items: center; gap: 24px; padding-block: 18px; transition: padding .3s; }
/* The logo may shrink: flex-shrink:0 plus an intrinsically wide SVG is what
   pushed Enquire and the toggle off-screen under 420px on the two longest
   brand names, and min-width:0 is needed because a flex item will not go
   below its content size otherwise.

   The HEIGHT MUST STAY DEFINITE. With height:auto and max-width:100% together,
   the image's width resolves against an anchor whose own width comes from that
   image — a circular percentage that Chrome settles at zero, so both logos
   computed to 0x0 and the header looked empty. object-fit keeps the artwork
   proportional when max-width does clamp the box. */
.hdr__logo { flex: 0 1 auto; min-width: 0; }
.hdr__logo img { height: 30px; width: auto; max-width: 100%; object-fit: contain; object-position: left center; }
.hdr__logo .hdr__logo--white { display: none; }
.nav { margin-left: auto; }   /* no min-width:0 — see the note on .hdr .wrap */
.nav ul { display: flex; gap: clamp(14px, 1.3vw, 22px); list-style: none; margin: 0; padding: 0; }
.nav a {
  font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase; font-weight: 500;
  color: #3A3D42; padding-block: 6px; white-space: nowrap; display: block;
}
.nav a:hover { color: var(--ink); }
.nav a[aria-current] { color: var(--ink); box-shadow: inset 0 -1px 0 currentColor; }
.enq {
  background: var(--brand); color: var(--brand-on); font-size: 12.5px; letter-spacing: .12em;
  text-transform: uppercase; font-weight: 600; padding: 15px 22px; white-space: nowrap;
  outline: 2px solid transparent; outline-offset: 3px; transition: outline-color .15s; flex-shrink: 0;
}
.enq:hover, .enq:focus-visible { outline-color: var(--ink); }
.nav-toggle {
  display: none; flex-direction: column; gap: 5px; background: none; border: 0;
  padding: 10px; cursor: pointer; margin-left: 0; flex-shrink: 0;
}
.nav-toggle span:not(.sr) { width: 23px; height: 1.5px; background: var(--ink); display: block; transition: background .3s; }

/* Scrolled state. The client asked for white text and the white logo on every
   brand here, not --brand-on: Clay Stone (3.49:1) and Antique Gold (2.98:1)
   fall below 4.5:1 with white, so this bar is a deliberate, recorded exception. */
.hdr.is-stuck { background: var(--brand); border-color: transparent; box-shadow: 0 6px 24px rgba(0,0,0,.12); }
.hdr.is-stuck .hdr__inner { padding-block: 12px; }
.hdr.is-stuck .hdr__logo img { height: 28px; }
.hdr.is-stuck .hdr__logo .hdr__logo--colour { display: none; }
.hdr.is-stuck .hdr__logo .hdr__logo--white { display: block; }
.hdr.is-stuck .nav a, .hdr.is-stuck .nav a:hover { color: #fff; }
.hdr.is-stuck .nav a[aria-current] { box-shadow: inset 0 -1px 0 currentColor; }
.hdr.is-stuck .enq { background: #fff; color: var(--ink); }
.hdr.is-stuck .enq:hover, .hdr.is-stuck .enq:focus-visible { outline-color: #fff; }
.hdr.is-stuck .nav-toggle span:not(.sr) { background: #fff; }

/* Anchor landing position. The section ids stay live for in-page links even
   though the jump menu is gone (A3); this clears the sticky header plus a
   little breathing room, where it used to clear the header plus the jump bar. */
[id^="s-"] { scroll-margin-top: calc(var(--headh, 74px) + 24px); }

/* ==========================================================================
   Hero
   ========================================================================== */
.hero {
  position: relative; min-height: min(88vh, 820px); display: flex; align-items: flex-end;
  color: #fff; overflow: hidden; background: var(--brand);
}
.hero__slide { position: absolute; inset: 0; opacity: 0; transition: opacity .9s ease; }
.hero__slide.on { opacity: 1; }
.hero__slide img, .hero__slide .img-pending { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero__shade {
  position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(90deg, rgba(18,16,14,.82) 0%, rgba(18,16,14,.45) 45%, rgba(18,16,14,0) 75%),
              linear-gradient(0deg, rgba(18,16,14,.55), transparent 40%);
}
.hero__inner { position: relative; z-index: 2; width: 100%;
  padding-block: clamp(60px, 9vw, 120px) clamp(28px, 4vw, 48px);
  padding-bottom: calc(3vw + clamp(28px, 4vw, 48px));   /* clears the cut-out, as the concept does */
}
.hero__title { font-size: clamp(44px, 5.6vw, 92px); max-width: 14ch; }
.hero__lead { max-width: 48ch; font-size: clamp(17px, 1.4vw, 19px); font-weight: 300; margin: 26px 0 32px; color: #F1ECE4; }
.hero .btn { background: #fff; border-color: #fff; }
.hero .btn:hover { background: transparent; color: #fff; }
.hero .link { color: #fff; }
/* ---------- hero bottom mark ----------
   Matches v1's live brand pages: the brand's stacked mark stretched across the
   width of the .wrap box, 46px tall, flush with the hero's bottom edge, so only
   a horizontal slice of the letterforms shows. v1 gets that from `object-fit:
   cover` in a 46px-tall box; `mask-size: cover` is the same crop.

   Drawn as a mask rather than an image file so the shapes can take the colour
   of the section BELOW the hero, which is what makes them read as a cut-out.
   --mark-src is set per brand from the theme, so holding.njk needs no change.

   min(--v2-wrap, 100%) centred reproduces the .wrap border box exactly: 1360px
   at left 40 on a 1440 viewport, full-bleed once the viewport is narrower. */
.bhero::before {
  content: ""; position: absolute; z-index: 2; bottom: 0; left: 50%;
  transform: translateX(-50%);
  width: min(var(--v2-wrap), 100%); height: 46px; pointer-events: none;
  background-color: var(--mark-fill, var(--v2-paper));
  -webkit-mask-image: var(--mark-src); mask-image: var(--mark-src);
  -webkit-mask-size: cover; mask-size: cover;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
/* The fill is the background of whatever section follows the hero. */
.bhero::before { --mark-fill: var(--v2-paper); }   /* next: .holding */

/* ---------- homepage hero cut-out ----------
   The concept's .cut, verbatim: the same viewBox and the same five shapes,
   full-bleed and stretched with preserveAspectRatio="none". The fill is the
   colour of the section below the hero, so the shapes read as that section
   cutting up into the photo. The holding pages use the mask above instead,
   because the concept has no brand pages and each brand's shapes have to come
   from its own mark. */
.cut { position: absolute; left: 0; right: 0; bottom: -1px; z-index: 3; line-height: 0; pointer-events: none; }
.cut svg { display: block; width: 100%; height: auto; }
.cut polygon, .cut rect { fill: var(--v2-paper); }
/* holding.njk is shared with v1 and still emits the <img> mark; v2 draws it. */
.bhero__mark { display: none; }

/* Inner-page hero */
.hero--inner { min-height: min(70vh, 640px); }
/* Client, 21 Sept: every APPA page's hero title uses Home's exact sizing
   rule -- the inner-page override (112px vs Home's 92px) is gone. .hero__title
   above is the single source now; nothing here restates it. */
.hero--inner .hero__shade { background: linear-gradient(0deg, rgba(16,15,14,.85), rgba(16,15,14,.2) 65%); }
.hero--inner .cut { display: none; }

/* ==========================================================================
   textSection — statement / feature / bleed / band / intro / longform
   ========================================================================== */
.section { position: relative; }
.ts--statement { background: var(--v2-paper); padding-block: clamp(70px, 9vw, 130px); }
.split__grid { display: grid; grid-template-columns: 1.25fr 1fr; gap: clamp(30px, 6vw, 110px); align-items: end; }
.ts--statement h2 { font-size: clamp(38px, 4.6vw, 72px); }
.split__txt { color: var(--v2-body); max-width: 46ch; }
.ts--statement .v2-stmt { color: var(--accent); margin-top: 26px; }
.ts--statement .lead { font-size: clamp(20px, 1.7vw, 24px); }

/* Read more / Show less */
.more { margin-top: 14px; border-top: 1px solid var(--v2-line); }
.more summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 12px;
  padding: 16px 0; font-weight: 600; font-size: 15px;
}
.more summary::-webkit-details-marker { display: none; }
.more summary .pl {
  width: 26px; height: 26px; border: 1px solid currentColor; border-radius: 50%;
  display: grid; place-items: center; transition: transform .25s; flex: none;
}
.more[open] summary .pl { transform: rotate(45deg); }
.more summary .t2 { display: none; }
.more[open] summary .t1 { display: none; }
.more[open] summary .t2 { display: inline; }
.more__body { padding-bottom: 10px; color: inherit; font-size: 16px; max-width: 62ch; }
.split .more, .gets__head .more, .how .more, .board .more { border-top: 0; margin-top: 0; }
.split .more summary, .gets__head .more summary, .how .more summary, .board .more summary { padding: 8px 0; }

/* feature — text panel beside a two-thirds photo */
.ts--feature { display: grid; grid-template-columns: minmax(320px, 1fr) 2fr; background: var(--v2-paper); }
.ts--feature .feat__txt { padding: clamp(40px, 5vw, 80px) clamp(24px, 4vw, 64px); display: flex; flex-direction: column; justify-content: center; }
.ts--feature h2 { font-size: clamp(40px, 4.4vw, 68px); margin-bottom: 16px; }
.ts--feature .feat__media { position: relative; min-height: clamp(420px, 46vw, 640px); }
.ts--feature .feat__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* No photo: the panel takes the brand colour rather than leaving a hole. The
   media block must also stop reserving its min-height, or the section runs on
   for another 420-640px of empty colour below the text. */
.ts--feature.is-noimg { grid-template-columns: 1fr; background: var(--brand); color: var(--brand-on); }
.ts--feature.is-noimg .feat__media { display: none; }
/* No opacity here: ink at .92 over shade 4 composites to #272625 and lands at
   4.32:1, under the 4.5:1 body text needs. Full ink is 4.77:1. */
.ts--feature.is-noimg .eyebrow, .ts--feature.is-noimg .split__txt { color: inherit; }
.ts--feature.is-noimg .btn { background: transparent; color: inherit; border-color: currentColor; }

/* bleed — full-bleed photo with the text on it */
.ts--bleed { position: relative; min-height: clamp(520px, 58vw, 760px); display: flex; align-items: center; color: #fff; overflow: hidden; background: var(--brand); }
.ts--bleed > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ts--bleed::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(14,18,16,.85), rgba(14,18,16,.35) 50%, transparent 75%); }
.ts--bleed.is-noimg::after { background: linear-gradient(90deg, rgba(14,18,16,.5), transparent 70%); }
.ts--bleed .wrap { position: relative; z-index: 2; width: 100%; }
.ts--bleed h2 { font-size: clamp(46px, 6vw, 96px); max-width: 10ch; margin-bottom: 24px; }
.ts--bleed p { max-width: 40ch; font-weight: 300; color: #EDEAE4; }
.ts--bleed .eyebrow { color: rgba(255,255,255,.75); }
.ts--bleed .link, .ts--bleed .v2-stmt { color: #fff; }

/* band — offset photo with a brand-colour card overlapping it */
.ts--band { padding-block: clamp(70px, 9vw, 130px); overflow: hidden; }
.band__grid { display: grid; grid-template-columns: repeat(12, 1fr); align-items: center; }
.band__media { grid-column: 1 / span 8; grid-row: 1; min-height: clamp(340px, 44vw, 600px); margin-left: calc(var(--gut) * -1); position: relative; }
.band__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* The callout band. It takes shade 5 with white text, not the brand colour:
   on APPA that was Clay Stone (shade 4), which forces ink and reads as a pale
   slab rather than a statement. Shade 5 with white is 5.71:1 on APPA and
   5.32:1 at worst across the four brand scales. Flipping the text alone was
   not an option -- white on shade 4 is 3.49:1, under the 4.5:1 this needs. */
.band__card {
  grid-column: 7 / span 6; grid-row: 1; background: var(--band-bg); color: var(--band-fg);
  padding: clamp(34px, 4.4vw, 64px); position: relative; z-index: 2; margin-top: clamp(120px, 16vw, 240px);
}
.band__card h2 { font-size: clamp(32px, 3.4vw, 50px); margin-bottom: 18px; }
.band__card h2:only-child { margin-bottom: 0; }
.band__card p { font-weight: 300; margin: 0; }
.ts--band.is-noimg .band__card { grid-column: 1 / -1; margin-top: 0; }
/* The eyebrow and any body copy in the card sit on shade 5, so they take the
   same white the heading does rather than the light-on-brand treatment. */
.band__card .eyebrow--light { color: var(--on-dark-soft); }

/* intro — lead, two narrow columns, then Read more */
.ts--intro { padding-block: clamp(70px, 9vw, 130px); }
.intro__grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 24px; }
.intro__head { grid-column: 1 / span 5; }
.ts--intro h2 { font-size: clamp(40px, 4.4vw, 66px); }
.intro__body { grid-column: 7 / span 6; }
.cols { columns: 2 280px; column-gap: 40px; color: var(--v2-body); font-size: 16px; }
.cols p { break-inside: avoid; }
/* A paragraph too short to fill a column runs the width of the body instead. */
.intro__wide { color: var(--v2-body); font-size: 16px; }
.intro__wide p:last-child { margin-bottom: 0; }

/* longform — sticky photo beside long copy, callout as a pull quote */
.ts--longform { background: var(--v2-paper); padding-block: clamp(70px, 9vw, 130px); }
.stick__grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(30px, 6vw, 100px); align-items: start; }
.stick__media { position: sticky; top: calc(var(--headh, 74px) + 46px); margin: 0; }
.stick__media img, .stick__media .img-pending { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
.stick__media figcaption { font-size: 13px; color: var(--v2-soft); margin-top: 10px; }
.ts--longform h2 { font-size: clamp(38px, 4vw, 60px); margin-bottom: 28px; }
.ts--longform h3 { font-family: var(--font-body); font-weight: 700; font-size: 18px; letter-spacing: 0; margin: 34px 0 8px; }
.ts--longform p { color: var(--v2-body); max-width: 58ch; }
.ts--longform.is-noimg .stick__grid { grid-template-columns: 1fr; }
.pq { margin: 44px 0; position: relative; }
.pq p {
  font-family: var(--font-display); font-style: italic; font-weight: var(--display-weight);
  font-size: clamp(28px, 2.8vw, 40px); line-height: 1.2; color: var(--accent); max-width: 22ch;
}
.pq::before {
  content: "\201C"; position: absolute; left: -.1em; top: -.55em; font-family: var(--font-display);
  font-size: 120px; line-height: 1; color: var(--accent-soft); opacity: .55;
}

/* ---------- centred ----------
   One column, centred, under a short brand rule. Used on Careers so the page
   is not three heading-left / text-right bands in a row. */
.ts--centred { background: var(--v2-paper); padding-block: clamp(70px, 9vw, 130px); }
.centred { max-width: 60ch; margin-inline: auto; text-align: center; }
.centred__rule { display: block; width: 64px; height: 4px; background: var(--brand); margin: 0 auto clamp(24px, 3vw, 34px); }
.centred h2 { font-size: clamp(38px, 4.4vw, 64px); margin-bottom: clamp(20px, 2.4vw, 30px); }
.centred p { color: var(--v2-body); }
.centred .v2-stmt { margin-inline: auto; }

/* ==========================================================================
   cardGrid "companies" — the material board
   ========================================================================== */
.board__head { padding-block: clamp(56px, 7vw, 96px) clamp(30px, 4vw, 48px); }
.board__head h2 { font-size: clamp(40px, 4.8vw, 72px); }
.board__row { display: grid; grid-template-columns: repeat(4, 1fr); }
.bw { display: flex; flex-direction: column; color: var(--brand-on); position: relative; min-width: 0; }
/* The strip takes the tile's own business colour when it holds no photo:
   .bw carries data-theme, so --brand is already that business's colour here. */
.bw__media { position: relative; aspect-ratio: 16 / 10; overflow: hidden; transition: filter .3s; background: var(--brand); }
.bw__media img, .bw__media .img-pending { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.bw:hover .bw__media { filter: brightness(1.12); }
.bw__body {
  position: relative; padding: 26px 26px 30px; flex: 1; display: flex; flex-direction: column;
  overflow: hidden; min-height: 260px; background: var(--brand); color: var(--brand-on);
}
.bw__body > * { position: relative; }
/* No opacity on either of these. The tile fills are the four brand colours,
   and --brand-on is already the only text colour that clears 4.5:1 on each --
   dimming it to .8 dropped the material name to 4.06:1 on Dark Copper and
   4.07:1 on Antique Gold, and the fold to 4.35 / 4.44:1. At full strength the
   worst tile is 4.77:1. */
.bw h3 { font-size: clamp(30px, 2.6vw, 40px); margin-top: 28px; }
.bw p { font-size: 15px; margin: 8px 0 18px; max-width: 28ch; min-height: 3.1em; }
.bw .link { align-self: flex-start; font-size: 14px; }
/* Client, 20 Sept: flat brand colours on the material board -- no gradient or
   pattern overlay on the four business tiles, so each is a single flat fill.
   The concept's .metal sheen is gone outright (it was only ever used here). */
/* Client, 20 Sept: no texture anywhere. .stone's dot texture (this rule used
   to exist here, scoped to .board__appa.stone) is removed outright; the
   closing CTA bar below keeps its shade-4 flat fill with no overlay. */
.board__appa { background: var(--shade-4); color: var(--ink); position: relative; }
.board__appa .wrap { display: flex; justify-content: space-between; align-items: center; gap: 24px; flex-wrap: wrap; padding-block: 26px; position: relative; }
.board__appa h3 { font-size: clamp(26px, 2.4vw, 34px); }

/* ==========================================================================
   cardGrid "rows" / "grid" — staggered panels
   ========================================================================== */
.gets { background: var(--zone-bg); color: var(--zone-fg); padding-block: clamp(70px, 9vw, 130px); position: relative; overflow: hidden; }
.gets::before { content: ""; position: absolute; right: -6vw; top: -8vw; width: 38vw; height: 38vw; border-radius: 50%; border: 1px solid rgba(255,255,255,.18); pointer-events: none; }
.gets .eyebrow { color: var(--on-dark-soft); }
.gets__head { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; align-items: end; margin-bottom: clamp(40px, 5vw, 72px); }
.gets h2 { font-size: clamp(40px, 4.6vw, 70px); }
.gets__head p, .gets__head .more__body { margin: 0; color: var(--on-dark-soft); max-width: 44ch; }
.gets__head .more summary .pl { border-color: #fff; }
.gets .v2-stmt { color: var(--on-dark-soft); }
.kp { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(14px, 1.6vw, 24px); align-items: start; }
.kp--4 { grid-template-columns: repeat(4, 1fr); }
.kp li {
  padding: clamp(28px, 3vw, 44px) clamp(24px, 2.4vw, 36px) clamp(30px, 3vw, 44px);
  min-height: clamp(300px, 26vw, 380px); display: flex; flex-direction: column; position: relative;
  transition: transform .35s cubic-bezier(.2,.7,.2,1);
}
.kp li:hover { transform: translateY(-8px); }
/* Every panel briefs its own photo, 4:5, above the card content. */
.kp__media { position: relative; display: block; aspect-ratio: 4 / 5; overflow: hidden;
  margin: calc(-1 * clamp(28px, 3vw, 44px)) calc(-1 * clamp(24px, 2.4vw, 36px)) clamp(22px, 2.4vw, 30px);
  background: var(--brand); }
.kp__media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.kp-a .kp__media { background: var(--shade-4); }
.kp-c .kp__media { background: var(--shade-5); }
.kp-a { background: var(--panel-a-bg); color: var(--panel-a-fg); }
.kp-b { background: var(--panel-b-bg); color: var(--panel-b-fg); border: 1px solid rgba(255,255,255,.35); }
.kp-c { background: var(--panel-c-bg); color: var(--panel-c-fg); }
.kp .ico { width: 64px; height: 64px; border-radius: 50%; border: 1px solid currentColor; display: grid; place-items: center; margin-bottom: auto; flex: none; }
.kp .ico img, .kp .ico svg { width: 30px; height: 30px; }
.kp-a .ico, .kp-c .ico { color: var(--shade-6); }
/* Panel titles, down ~15% at every width on the client's note that they were
   too big: 28->24, 2.6->2.2vw, 40->34. The brief quoted clamp(24px,2.1vw,32px)
   as the starting point, but that is the concept's value -- v2 shipped these
   larger -- so the 15% is taken off what is actually on screen. */
.kp b { display: block; font-family: var(--font-display); font-weight: var(--display-weight); font-size: clamp(24px, 2.2vw, 34px); line-height: 1.1; margin: 36px 0 12px; }
.kp .kp__t { font-size: 15.5px; line-height: 1.6; opacity: .9; }
.kp .kp__t p { margin: 0 0 .8em; }
.kp .kp__t p:last-child { margin-bottom: 0; }
/* The concept fades these to .55, which drops every panel below 4.5:1. They
   inherit each panel's readable colour at full opacity instead. */
.kp .kp__n { position: absolute; top: 18px; right: 22px; font-family: var(--font-display); font-weight: var(--display-weight); font-size: 15px; letter-spacing: .06em; }
/* On a card with a photo slot the numeral sits over that slot, not over the
   panel -- and no photo can be relied on for contrast. It takes the card's own
   ground as a chip there, so it reads against the panel colour either way.
   Without this it was white on shade 4 (3.49:1) and ink on shade 5 (2.92:1). */
.kp li.kp--media .kp__n { background: inherit; top: 0; right: 0; padding: 10px 14px; }
/* Stagger, as the concept: three across drops 2 and 3, four across steps all four. */
.kp:not(.kp--4) li:nth-child(2) { margin-top: clamp(30px, 4vw, 64px); }
.kp:not(.kp--4) li:nth-child(3) { margin-top: clamp(60px, 8vw, 128px); }
.kp:not(.kp--4) li:nth-child(5) { margin-top: clamp(30px, 4vw, 64px); }
.kp:not(.kp--4) li:nth-child(6) { margin-top: clamp(60px, 8vw, 128px); }
.kp--4 li:nth-child(2) { margin-top: clamp(20px, 3vw, 48px); }
.kp--4 li:nth-child(3) { margin-top: clamp(40px, 6vw, 96px); }
.kp--4 li:nth-child(4) { margin-top: clamp(60px, 9vw, 144px); }

/* ==========================================================================
   cardGrid "people" — the compact portrait grid
   ==========================================================================
   Replaces the staggered colour panels on About. People are not a sequence, so
   there are no numerals and no stagger: a small round photo, the name in the
   serif, the role in small muted type and an optional bio. Cards in a row
   share a height (the grid stretches them), so the rows line up whether or not
   a person has a bio yet. -- A4, 18 Sept
   ========================================================================== */
.ppl { background: var(--v2-paper); padding-block: clamp(70px, 9vw, 130px); }
.ppl__head { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; align-items: end; margin-bottom: clamp(40px, 5vw, 72px); }
.ppl__head > * { min-width: 0; }
.ppl h2 { font-size: clamp(40px, 4.6vw, 70px); }
.ppl__head p, .ppl__head .more__body { margin: 0; color: var(--v2-body); max-width: 44ch; }
.ppl__grid {
  list-style: none; margin: 0; padding: 0; display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(30px, 3.4vw, 52px) clamp(20px, 2.2vw, 32px);
}
.ppl__card { display: flex; flex-direction: column; min-width: 0; }
/* The disc. With no photo it is a light step of the page's own scale carrying
   the person's initials in ink -- never a grey box. */
.ppl__ph {
  width: 96px; height: 96px; flex: none; border-radius: 50%; overflow: hidden;
  background: var(--shade-2); color: var(--ink);
  display: grid; place-items: center; margin-bottom: 18px;
}
.ppl__ph img { width: 100%; height: 100%; object-fit: cover; }
.ppl__ini { font-family: var(--font-display); font-weight: var(--display-weight); font-size: 30px; line-height: 1; letter-spacing: .03em; }
.ppl__name { display: block; font-family: var(--font-display); font-weight: var(--display-weight); font-size: 22px; line-height: 1.16; }
.ppl__role { font-size: 13px; line-height: 1.45; letter-spacing: .03em; color: var(--v2-soft); margin: 5px 0 0; }
.ppl__bio { font-size: 15px; line-height: 1.6; color: var(--v2-body); margin-top: 12px; }
.ppl__bio p { margin: 0 0 .7em; }
.ppl__bio p:last-child { margin-bottom: 0; }
/* The photo brief sits under the disc: it does not fit inside 96px. */
.ph-tag--static { position: static; display: inline-block; align-self: flex-start; margin: -8px 0 12px; }

/* 4 across at 1080 and up, 2 from 1079, 1 from 759. */
@media (max-width: 1079px) { .ppl__grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 759px)  { .ppl__grid { grid-template-columns: 1fr; } .ppl__head { grid-template-columns: 1fr; } }

/* ==========================================================================
   steps "list" — the interactive process
   ========================================================================== */
.steps { background: var(--steps-bg); color: var(--steps-fg); padding-block: clamp(70px, 9vw, 130px); overflow: hidden; }
.steps__head { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; align-items: end; margin-bottom: clamp(40px, 5vw, 72px); }
.steps h2 { font-size: clamp(40px, 4.6vw, 70px); }
.steps__head p, .steps__head .more__body { color: var(--on-dark-soft); margin: 0 0 1em; max-width: 44ch; }
.steps__head p:last-child { margin-bottom: 0; }
.steps .eyebrow { color: var(--on-dark-soft); }
.steps .more summary .pl { border-color: #fff; }
.proc { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(30px, 5vw, 80px); align-items: start; }
.proc__media { position: sticky; top: calc(var(--headh, 74px) + 46px); }
.proc__frame { position: relative; aspect-ratio: 4 / 4.6; overflow: hidden; background: var(--brand); }
.proc__shot { position: absolute; inset: 0; opacity: 0; transition: opacity .6s; }
.proc__shot.on { opacity: 1; }
.proc__shot img, .proc__shot .img-pending { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.proc__cap { position: absolute; left: 0; bottom: 0; z-index: 2; background: var(--cap-bg); color: var(--cap-fg); padding: 18px 22px; font-size: 14px; max-width: 70%; }
.proc__cap b { display: block; font-family: var(--font-display); font-size: 28px; font-weight: var(--display-weight); line-height: 1.05; margin-bottom: 4px; }
.proc__list { list-style: none; margin: 0; padding: 0; border-top: 1px solid rgba(255,255,255,.25); }
.proc__list li { border-bottom: 1px solid rgba(255,255,255,.25); }
.proc__btn {
  all: unset; display: grid; grid-template-columns: auto 1fr auto; gap: 0 clamp(18px, 2.4vw, 36px);
  align-items: center; width: 100%; padding: clamp(22px, 2.6vw, 34px) 0; cursor: pointer; box-sizing: border-box;
}
.proc__btn:focus-visible { outline: 2px solid #fff; outline-offset: -2px; }
.proc__n {
  font-family: var(--font-display); font-weight: var(--display-weight); font-size: clamp(56px, 6vw, 96px);
  line-height: .9; color: transparent; -webkit-text-stroke: 1px rgba(255,255,255,.55);
  transition: color .3s, -webkit-text-stroke-color .3s; min-width: 1.4ch;
}
.proc__ico { width: clamp(48px, 5vw, 76px); height: clamp(48px, 5vw, 76px); display: grid; place-items: center; flex: none; }
.proc__ico img { width: 100%; height: 100%; object-fit: contain; }
.proc__t { font-family: var(--font-display); font-weight: var(--display-weight); font-size: clamp(28px, 3vw, 44px); line-height: 1.05; transition: transform .3s; transform-origin: left; }
.proc__pl { width: 38px; height: 38px; border: 1px solid rgba(255,255,255,.55); border-radius: 50%; display: grid; place-items: center; font-size: 20px; line-height: 1; transition: transform .3s, background .3s, color .3s; }
.proc__body { grid-column: 2; max-height: 0; overflow: hidden; transition: max-height .45s ease; }
.proc__body p { margin: 0; padding: 6px 0 clamp(22px, 2.6vw, 34px); color: var(--on-dark-soft); font-size: 16px; max-width: 44ch; }
/* The open step's numeral sits on shade 6, so it takes a light step of the
   same scale rather than a second brand's colour. Measured below; this size
   needs 3:1. */
.proc__list li.on .proc__n { color: var(--shade-2); -webkit-text-stroke-color: var(--shade-2); }
.proc__list li.on .proc__pl { transform: rotate(45deg); background: #fff; color: var(--ink); border-color: #fff; }
.proc__list li.on .proc__body { max-height: 460px; }
.proc__list li:hover .proc__t { transform: translateX(6px); }
.no-js .proc__body, .proc__list li.on .proc__body { max-height: none; }
.steps.is-noimg .proc { grid-template-columns: 1fr; }
.steps.is-noimg .proc__list { max-width: 820px; }

/* ==========================================================================
   steps "grid" — photo + text, then the icon row
   ========================================================================== */
.how { background: #fff; --how-pad: clamp(40px, 6vw, 96px); padding-bottom: var(--how-pad); }
.how__top { display: grid; grid-template-columns: 1.1fr 1fr; }
.how__media { position: relative; min-height: clamp(340px, 40vw, 560px); }
.how__media img, .how__media .img-pending { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.how__txt { padding: var(--how-pad) clamp(24px, 5vw, 80px); align-self: center; }
.how h2 { font-size: clamp(40px, 4.4vw, 66px); margin-bottom: 20px; }
.how__txt p { color: var(--v2-body); max-width: 46ch; }
.how .more { max-width: 46ch; }
.how.is-noimg .how__top { grid-template-columns: 1fr; }
.icons { list-style: none; margin: 0; padding: clamp(34px, 4vw, 56px) 0; display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; border-bottom: 1px solid var(--v2-line); }
.icons li { display: flex; gap: 16px; align-items: flex-start; }
.ico { width: 52px; height: 52px; flex: none; border: 1px solid currentColor; border-radius: 50%; display: grid; place-items: center; color: var(--shade-6); }
.ico img, .ico svg { width: 24px; height: 24px; }
.ico--n { font-family: var(--font-display); font-weight: var(--display-weight); font-size: 20px; color: var(--v2-soft); }
.icons b { display: block; font-size: 16px; }
.icons .more summary { padding: 6px 0; font-size: 13px; }
.icons .more__body { font-size: 14.5px; max-width: 34ch; }
.icons .more__body p { margin: 0; }
.how .v2-stmt { color: var(--accent); margin: 36px 0 0; }
.how__closing { color: var(--v2-body); max-width: 70ch; margin: 18px 0 0; }
.how__closing > :last-child { margin-bottom: 0; }
/* No steps: the icon row (and its padding and rule) is not in the markup, so
   the callout or closing is the first thing under the top block, whose own
   bottom padding is already the gap. With nothing under it at all, that
   padding is the section's bottom too, so the section's is not added twice. */
.how.is-nosteps .wrap > :first-child { margin-top: 0; }
.how.is-bare { padding-bottom: 0; }

/* ==========================================================================
   featuredProjects — the gallery strip
   ========================================================================== */
.pj { padding-block: clamp(56px, 7vw, 100px) clamp(56px, 7vw, 110px); background: var(--v2-black); color: #fff; }
.pj__top { display: flex; justify-content: space-between; align-items: end; gap: 30px; flex-wrap: wrap; margin-bottom: clamp(36px, 5vw, 64px); }
.pj__top h2 { font-size: clamp(40px, 4.6vw, 68px); }
.pj__top .eyebrow { color: rgba(255,255,255,.65); }
/* The heading sets this column's width, as in the concept, so .pj__nav stays
   on the right; the intro and its fold carry their own measure. */
.pj__top > .rv { flex: 0 1 auto; min-width: 0; }
.pj__intro { color: rgba(255,255,255,.8); max-width: 52ch; margin: 14px 0 0; }
.pj__intro p:last-child { margin-bottom: 0; }
.pj__nav { display: flex; align-items: center; gap: 12px; }
.pj__nav .link { color: #fff; margin-right: 18px; }
.rbtn { width: 48px; height: 48px; border-radius: 50%; border: 1px solid rgba(255,255,255,.5); background: transparent; color: #fff; cursor: pointer; display: grid; place-items: center; transition: background .2s, color .2s, opacity .2s; flex: none; }
.rbtn:hover, .rbtn:focus-visible { background: #fff; color: var(--v2-black); }
.rbtn:disabled { opacity: .25; cursor: default; background: transparent; color: #fff; }
.rbtn svg { width: 16px; height: 10px; }
.strip { list-style: none; margin: 0; padding: 0; display: grid; grid-auto-flow: column; grid-auto-columns: calc(50% - 1px); gap: 2px; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; cursor: grab; }
.strip::-webkit-scrollbar { display: none; }
.strip.drag { cursor: grabbing; scroll-snap-type: none; user-select: none; }
.strip li { scroll-snap-align: start; min-width: 0; }
.work { display: block; color: #fff; }
.work__img { position: relative; overflow: hidden; aspect-ratio: 4 / 3; }
.work__img img, .work__img .img-pending { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform .8s cubic-bezier(.2,.7,.2,1); }
.work:hover .work__img img { transform: scale(1.03); }
.work__txt { padding: 26px clamp(18px, 1.6vw, 26px) 0; max-width: 620px; }
.work__cat { display: flex; align-items: center; gap: 10px; font-size: 13px; letter-spacing: .12em; text-transform: uppercase; color: rgba(255,255,255,.85); flex-wrap: wrap; }
.work__cat i { width: 9px; height: 9px; display: inline-block; flex: none; outline: 1px solid rgba(255,255,255,.35); }
.work h3 { font-size: clamp(28px, 2.6vw, 40px); line-height: 1.12; margin: 16px 0 14px; max-width: 18ch; }
.work p { font-size: 16px; line-height: 1.65; color: rgba(255,255,255,.85); margin: 0; max-width: 48ch; }
.pj__bar { height: 1px; background: rgba(255,255,255,.2); margin-top: clamp(36px, 4vw, 56px); position: relative; }
.pj__bar i { position: absolute; left: 0; top: -1px; height: 3px; background: #fff; width: 40%; transition: transform .15s; }
.pj .v2-stmt { color: rgba(255,255,255,.85); margin-top: 32px; }

/* ==========================================================================
   finalCta
   ========================================================================== */
.final { position: relative; color: var(--cta-fg); overflow: hidden; background: var(--cta-bg); }
.final__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.final::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(18,16,14,.9), rgba(18,16,14,.42) 60%, rgba(18,16,14,.15)); }
.final.is-noimg::after { background: none; }
.final .wrap { position: relative; z-index: 2; padding-block: clamp(90px, 12vw, 170px); display: grid; grid-template-columns: 1.4fr 1fr; gap: 40px; align-items: end; }
.final h2 { font-size: clamp(44px, 6vw, 96px); }
.final p { font-weight: 300; font-size: 18px; max-width: 34ch; }
.final .btn { background: #fff; border-color: #fff; }
.final .btn:hover { background: transparent; color: #fff; }
.final .link { color: #fff; }
.final__statement { font-family: var(--font-display); font-style: italic; font-weight: var(--display-weight); font-size: 20px; margin: 24px 0 0; max-width: none; }

/* ==========================================================================
   Footer — the concept's four-column table
   ========================================================================== */
.footer { background: var(--ink); color: #C9CBCE; padding-block: 44px 30px; font-size: 14px; }
.footer__tb { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; border: 1px solid #45484D; }
.footer__tb > div { padding: 18px 20px; border-right: 1px solid #45484D; min-width: 0; }
.footer__tb > div:last-child { border-right: 0; }
.footer__h { margin: 0 0 10px; font-family: var(--font-body); font-size: 12.5px; font-weight: 600;
  letter-spacing: 0; line-height: 1.4; color: #8E9297; }
.footer ul { list-style: none; margin: 0; padding: 0; }
.footer li { display: flex; align-items: center; gap: 8px; padding: 2px 0; }
.footer a { transition: color .2s; }
.footer a:hover { color: #fff; }
.footer a[aria-current] { color: #fff; font-weight: 700; }
/* Client, 20 Sept: size the footer logo off the column width instead of a
   fixed height, so it scales with the footer__id column at every breakpoint. */
.footer__logo { height: auto; width: 100%; max-width: 380px; }
.footer__copy { margin: 12px 0 0; max-width: 28ch; }
/* The brand dot. data-theme is what tokens.css keys --brand off, so each
   business colours its own dot with no extra mapping. */
.footer .chip { width: 9px; height: 9px; flex: none; background: var(--brand); outline: 1px solid rgba(255,255,255,.22); }

/* ==========================================================================
   Holding pages
   ========================================================================== */
.bhero { position: relative; min-height: min(62vh, 520px); display: flex; align-items: flex-end; overflow: hidden; background: var(--brand); }
/* Direct child, so this only ever styles the hero photo. */
.bhero > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.bhero::after { content: ""; position: absolute; inset: 0; background: linear-gradient(to top, rgba(14,13,11,.78) 0%, rgba(14,13,11,.28) 55%, rgba(14,13,11,.08) 100%); }
.bhero__inner { position: relative; z-index: 2; width: 100%; padding-bottom: 46px; }
.holding { padding-block: clamp(70px, 9vw, 120px); background: var(--v2-paper); }
.holding--after-hero { padding-top: clamp(50px, 6vw, 90px); }
.holding__grid { display: grid; grid-template-columns: 4fr 8fr; gap: clamp(30px, 6vw, 78px); align-items: center; }
.holding__grid > * { min-width: 0; }
.holding__mark { height: 150px; width: auto; }
.holding__rule { width: 88px; height: var(--brand-rule); background: var(--brand); }
.holding__title { font-size: clamp(40px, 4.6vw, 64px); max-width: 17ch; }
.holding .lead { font-size: clamp(20px, 1.7vw, 24px); max-width: 52ch; }
.holding__note { max-width: 52ch; margin-top: 18px; color: var(--v2-soft); }

/* ==========================================================================
   Legal + generic page body (contact.njk and the partnership form section)
   ========================================================================== */
.legal { padding-block: clamp(70px, 9vw, 120px); }
.prose--legal { max-width: 46rem; }
.prose--legal h1 { font-size: clamp(38px, 4vw, 54px); margin-bottom: 30px; }
.prose--legal h2 { font-size: 28px; margin: 38px 0 12px; }
.prose--legal ul { padding-left: 1.2em; }
.prose--legal li p { margin: 0; }
main > .wrap > h1 { font-size: clamp(40px, 4.6vw, 70px); margin-bottom: 10px; }

/* ==========================================================================
   FORMS — ported verbatim from site.css (lines 293-461) so the contact and
   partnership forms behave identically in both designs. Tokens only.
   src/contact.njk and components/form.njk are untouched by v2.
   ========================================================================== */

.appaform { max-width: 46rem; }

.appaform__group { padding: var(--space-m) 0; border-top: 1px solid var(--line); }
.appaform__group:first-of-type { border-top: 0; padding-top: 0; }

.appaform__legend {
  font-family: var(--font-body);
  font-size: var(--step--1);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 var(--space-s);
  font-weight: 700;
}

.appaform__fields { display: grid; gap: 1.5rem; }

/* Two columns from tablet up, but only for the short inputs. Textareas,
   file inputs and choice sets always span the full width — a 9-option
   checkbox list in a half-column is unreadable. */
@media (min-width: 48rem) {
  .appaform__fields { grid-template-columns: 1fr 1fr; }
  .field--textarea,
  .field--file,
  .field--radio,
  .field--checkboxes,
  .field--consent { grid-column: 1 / -1; }
}

.field { min-width: 0; }   /* grid children default to min-width:auto and won't shrink */

.field__label {
  display: block;
  font-size: var(--step--1);
  font-weight: 600;
  color: var(--ink);
  margin-bottom: .4rem;
}

.field__req { color: var(--brand-ink); margin-left: .15em; }

.field__help {
  font-size: var(--step--1);
  color: var(--muted);
  margin: 0 0 .5rem;
  line-height: 1.45;
}
.field__help a { color: var(--brand-ink); }

.field__set { border: 0; padding: 0; margin: 0; min-width: 0; }

.appaform input[type="text"],
.appaform input[type="email"],
.appaform input[type="tel"],
.appaform select,
.appaform textarea {
  width: 100%;
  font: inherit;
  font-size: var(--step-0);
  color: var(--text);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: .7rem .85rem;
  transition: border-color .18s ease, box-shadow .18s ease;
}

.appaform textarea { resize: vertical; line-height: 1.5; }

.appaform input:focus-visible,
.appaform select:focus-visible,
.appaform textarea:focus-visible {
  outline: 0;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent);
}

/* File inputs are unstyleable across browsers beyond the button. Keep it plain
   and readable rather than faking a drop zone that behaves differently in Safari. */
.appaform input[type="file"] {
  width: 100%;
  font: inherit;
  font-size: var(--step--1);
  color: var(--text);
  padding: .6rem;
  border: 1px dashed var(--line);
  border-radius: 2px;
  background: var(--wash);
}

.field__choices { display: grid; gap: .55rem; }
@media (min-width: 40rem) {
  .field__choices { grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); }
}

.choice {
  display: flex;
  gap: .6rem;
  align-items: flex-start;
  font-size: var(--step-0);
  color: var(--text);
  line-height: 1.45;
  cursor: pointer;
  overflow-wrap: break-word;
}
.choice input { margin-top: .3rem; accent-color: var(--brand); flex: none; }

.choice--consent { font-size: var(--step--1); align-items: flex-start; }

/* Honeypot — off-screen, not display:none. Some bots skip hidden fields. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.appaform__actions {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding-top: var(--space-m);
  border-top: 1px solid var(--line);
}

.appaform__status { margin: 0; font-size: var(--step--1); color: var(--muted); }
.appaform__status[data-state="error"] { color: var(--alert); }

.appaform[data-busy] { opacity: .6; pointer-events: none; }

.appaform__done {
  max-width: var(--measure);
  padding: var(--space-l) 0;
}
.appaform__done h2 {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--step-3);
  color: var(--ink);
  margin: 0 0 .6rem;
}
.appaform__done p { color: var(--text); font-size: var(--step-1); line-height: 1.6; margin: 0; }

/* Scroll-linked motion only. A focus ring and a button state are visitor-initiated
   and stay put — do NOT add a blanket transition reset here. */
@media (prefers-reduced-motion: reduce) {
  .appaform input,
  .appaform select,
  .appaform textarea { transition-duration: .01ms; }
}

/* File constraint line — ours, not the client's copy. Sits under the input
   and turns into the error message when a file is rejected. */
.field__limits {
  font-size: var(--step--1);
  color: var(--muted);
  margin: .45rem 0 0;
  line-height: 1.45;
}
.field__limits[data-state="error"] { color: var(--alert); font-weight: 600; }

/* Screen-reader-only text. Used for "(opens in a new tab)". */
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}


/* ==========================================================================
   Responsive
   The concept scrolled sideways between 1081px and 1300px: the full nav was
   still shown while Enquire and the toggle needed the same row. The nav now
   collapses to the toggle below 1300px, and 1300-1500px tightens nav spacing
   and type so the full row fits. Nothing here uses overflow-x on html or body.
   ========================================================================== */
@media (max-width: 1239px) {
  /* Collapse point from measurement: the tightened nav needs 1068px and fits
     down to about 1175px, so 1240px leaves roughly 64px of margin. */
  .nav {
    display: none; position: absolute; top: 100%; left: 0; right: 0;
    background: #fff; border-bottom: 1px solid var(--v2-line); margin: 0;
  }
  .nav.is-open { display: block; }
  .nav ul { flex-direction: column; gap: 0; padding: 8px var(--gut) 20px; }
  .nav a { display: block; padding: 14px 0; border-bottom: 1px solid var(--v2-line); font-size: 13px; letter-spacing: .12em; color: #3A3D42; }
  .hdr.is-stuck .nav { background: #fff; }
  .hdr.is-stuck .nav a { color: #3A3D42; }
  .nav-toggle { display: flex; }
  .enq { margin-left: auto; }
  .sw img { max-height: 22px; }
}
@media (max-width: 1080px) {
  .board__row { grid-template-columns: 1fr 1fr; }
  .ts--feature, .how__top, .stick__grid, .intro__grid { grid-template-columns: 1fr; }
  .intro__head, .intro__body { grid-column: 1 / -1; }
  .icons { grid-template-columns: 1fr 1fr; }
  .proc { grid-template-columns: 1fr; }
  .kp, .kp--4 { grid-template-columns: 1fr 1fr; }
  .kp li:nth-child(n) { margin-top: 0; }
  .gets__head, .steps__head { grid-template-columns: 1fr; }
  .proc__media, .stick__media { position: static; }
  .proc__frame { aspect-ratio: 16 / 10; }
  .stick__media img, .stick__media .img-pending { aspect-ratio: 16 / 10; }
  .ts--feature .feat__media { min-height: clamp(320px, 52vw, 460px); }
  .final .wrap { grid-template-columns: 1fr; }
}
@media (max-width: 760px) {
  .switch { grid-template-columns: repeat(5, 1fr); }
  .sw { min-height: 48px; padding: 6px; }
  .sw img { max-height: 20px; }
  .sw__h--white, .sw__h--colour { display: none; }
  .sw__m--white { display: block; }
  .sw__m--colour { display: none; }
  .sw:hover .sw__m--white, .sw:focus-visible .sw__m--white, .sw.on .sw__m--white { display: none; }
  .sw:hover .sw__m--colour, .sw:focus-visible .sw__m--colour, .sw.on .sw__m--colour { display: block; }
  .hdr__inner { gap: 14px; padding-block: 12px; }
  .hdr__logo img { height: 24px; }
  .hdr.is-stuck .hdr__logo img { height: 22px; }
  .enq { padding: 12px 16px; font-size: 11px; letter-spacing: .1em; }
  .split__grid, .steps__head, .gets__head { grid-template-columns: 1fr; }
  .board__row, .icons { grid-template-columns: 1fr; }
  .kp, .kp--4 { grid-template-columns: 1fr; }
  .kp li:nth-child(n) { margin-top: 0; min-height: 0; }
  .proc__n { font-size: 44px; }
  .proc__btn { gap: 0 16px; }
  .strip { grid-auto-columns: 86%; }
  .work__img { aspect-ratio: 4 / 5; }
  .pj__nav { width: 100%; }
  .pj__nav .link { margin-right: auto; }
  .hero { min-height: min(84vh, 640px); }
  .hero__shade { background: linear-gradient(0deg, rgba(18,16,14,.9) 30%, rgba(18,16,14,.3)); }
  .cols { columns: 1; }
  .band__media { grid-column: 1 / -1; grid-row: 1; margin-right: calc(var(--gut) * -1); }
  .band__card { grid-column: 1 / -1; grid-row: 2; margin-top: -60px; margin-left: 18px; }
  .holding__grid { grid-template-columns: 1fr; }
  .holding__mark { height: 110px; }
  .ts--bleed::after { background: linear-gradient(0deg, rgba(14,18,16,.85), rgba(14,18,16,.35)); }
  .pq::before { font-size: 80px; }
  .footer__tb { grid-template-columns: 1fr 1fr; }
  .footer__tb > div { border-bottom: 1px solid #45484D; }
  .footer__tb > div:nth-child(2n) { border-right: 0; }
  .footer__tb > div:nth-last-child(-n+2) { border-bottom: 0; }
}
@media (max-width: 420px) {
  .enq { padding: 11px 12px; letter-spacing: .06em; }
  .hdr__inner { gap: 10px; }
  .bw__body { padding: 22px 20px 26px; }
}

/* The brand dot on a project card. data-theme is what tokens.css keys --brand
   off, so the dot picks up that business's colour with no extra mapping. */
.work__cat i { background: var(--brand); }

/* Full-bleed band (steps callout over band_image) — same contract as v1. */
.band { position: relative; min-height: clamp(380px, 42vw, 560px); display: flex; align-items: center; overflow: hidden; background: var(--band-bg); color: var(--band-fg); }
.band > img, .band video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.band::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(14,18,16,.85), rgba(14,18,16,.35) 50%, transparent 75%); }
.band .wrap { position: relative; z-index: 2; width: 100%; }
.band__text { font-family: var(--font-display); font-weight: var(--display-weight); font-size: clamp(38px, 5vw, 76px); line-height: 1.04; letter-spacing: -.015em; max-width: 16ch; margin: 0; }
@media (max-width: 760px), (prefers-reduced-motion: reduce) { .band video { display: none; } }
@media (max-width: 760px) { .band::after { background: linear-gradient(0deg, rgba(14,18,16,.85), rgba(14,18,16,.35)); } }

/* Board tile: the business description folds rather than being dropped. */
.bw__more { border-top: 1px solid currentColor; margin: 0 0 18px; }
.bw__more summary { padding: 10px 0; font-size: 13px; }
.bw__more summary .pl { width: 22px; height: 22px; }
.bw__more .more__body { font-size: 14.5px; max-width: 34ch; }
.bw__more .more__body p { margin: 0 0 .8em; }
.bw__more .more__body p:last-child { margin-bottom: 0; }
.bw p { min-height: 0; }
/* Subtitle on a panel card (the About team cards carry a role here). */
.kp__sub { font-size: 14px; letter-spacing: .06em; text-transform: uppercase; opacity: .75; margin: -4px 0 12px; }

/* Projects strip intro: the second paragraph folds rather than being dropped. */
.pj__top .more { border-top-color: rgba(255,255,255,.3); max-width: 52ch; }
.pj__top .more__body { color: rgba(255,255,255,.8); }
.pj__top .more summary .pl { border-color: #fff; }

/* Very narrow phones: the header row is logo + Enquire + toggle and must fit
   320px without anything sliding off. Found by the width sweep. */
@media (max-width: 400px) {
  .hdr__inner { gap: 8px; }
  .hdr__logo img { height: 20px; }
  .hdr.is-stuck .hdr__logo img { height: 19px; }
  .enq { padding: 10px 11px; font-size: 10px; letter-spacing: .04em; }
  .nav-toggle { padding: 8px 2px; }
  .sw { padding: 6px 3px; }
}

/* Footer on the narrowest phones: one column, dividers between rows only. */
@media (max-width: 460px) {
  .footer__tb { grid-template-columns: 1fr; }
  .footer__tb > div { border-right: 0; border-bottom: 1px solid #45484D; }
  .footer__tb > div:last-child { border-bottom: 0; }
}
