/* ============================================================
   NORTH LIGHT - CWC Flooring
   An architectural materials showroom. Gallery light, navy ink.
   ============================================================ */

:root{
  --paper:        #F2F4F6;   /* gallery light            */
  --paper-2:      #EAEEF2;   /* a shade cooler           */
  --paper-3:      #E2E7EC;   /* hairline panels          */
  --navy:         #0E2240;   /* the ink                  */
  --navy-deep:    #0A1A32;   /* interlude depth          */
  --navy-soft:    #16315A;   /* raised navy panel        */
  --steel:        #4A6B90;   /* restrained accent        */
  --steel-pale:   #9DB3C9;   /* accent on navy           */
  --oak-a:        #E9E3D6;   /* pale oak                 */
  --oak-b:        #E0D8C7;
  --oak-c:        #D6CDBA;
  --ink-40:       rgba(14,34,64,.40);
  --ink-60:       rgba(14,34,64,.70);
  --line:         rgba(14,34,64,.16);
  --line-soft:    rgba(14,34,64,.09);
  --light-60:     rgba(242,244,246,.62);
  --light-40:     rgba(242,244,246,.40);
  --line-light:   rgba(242,244,246,.18);
  --line-light-2: rgba(242,244,246,.10);
  --sans: "Hanken Grotesk", "Helvetica Neue", sans-serif;
  --serif: "Instrument Serif", Georgia, serif;
  --gutter: clamp(1.25rem, 5vw, 5.5rem);
  --measure: 34em;
  --nav-h: 5.5rem;          /* the fixed bar measures ~86px; anything pinned
                               under it has to clear this much */
}

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

html{
  scroll-behavior:smooth;
  scroll-padding-top:5.5rem;
}

body{
  background:var(--paper);
  color:var(--navy);
  font-family:var(--sans);
  font-weight:300;
  font-size:1.0625rem;
  line-height:1.65;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  /* clip (not hidden) prevents horizontal scroll WITHOUT turning body into a
     scroll container - hidden here silently breaks the story's position:sticky */
  overflow-x:clip;
}

::selection{ background:var(--navy); color:var(--paper); }
.on-navy ::selection{ background:var(--paper); color:var(--navy); }

a{ color:inherit; text-decoration:none; }
a:focus-visible, button:focus-visible{
  outline:1.5px solid var(--steel);
  outline-offset:4px;
}

em.word{
  font-family:var(--serif);
  font-style:italic;
  font-weight:400;
  letter-spacing:.005em;
}

/* ---------- shared furniture ---------------------------------- */

.shell{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
}

.kicker{
  display:flex;
  align-items:center;
  gap:1rem;
  font-size:.6875rem;
  font-weight:500;
  letter-spacing:.32em;
  text-transform:uppercase;
  color:var(--steel);
}
.kicker::before{
  content:"";
  width:2.75rem;
  height:1px;
  background:currentColor;
  opacity:.55;
}
.on-navy .kicker{ color:var(--steel-pale); }

/* oversized section numeral, cropped off the edge */
.numeral{
  position:absolute;
  top:-.08em;
  right:-.12em;
  font-size:clamp(11rem, 28vw, 26rem);
  font-weight:200;
  line-height:1;
  letter-spacing:-.04em;
  color:rgba(14,34,64,.055);
  pointer-events:none;
  user-select:none;
  z-index:0;
  will-change:transform;
}
.numeral.is-left{ right:auto; left:-.1em; }
.on-navy .numeral{ color:rgba(242,244,246,.05); }

/* clip, not hidden: contains the bleeding numerals without becoming a scroll
   container (which would break the pinned story's position:sticky ancestor chain) */
section{ position:relative; overflow:clip; }

/* ---------- reveals -------------------------------------------- */

.rv{
  opacity:0;
  transform:translateY(2.25rem);
  transition:opacity .45s cubic-bezier(.22,.61,.27,1), transform .45s cubic-bezier(.22,.61,.27,1);
  transition-delay:var(--d, 0s);
  will-change:opacity, transform;
}
.rv.rv-soft{ transform:translateY(1rem); }
.rv.in{ opacity:1; transform:none; }

/* ---------- arrival: morning light floods the gallery ---------- */

.veil{
  position:fixed;
  inset:0;
  z-index:120;
  background:linear-gradient(180deg, rgba(10,26,50,.62) 0%, rgba(10,26,50,.44) 100%);
  opacity:1;
  pointer-events:none;
  transition:opacity .6s cubic-bezier(.33,0,.2,1), visibility 0s linear .65s;
}
html.is-ready .veil{ opacity:0; visibility:hidden; }

.ar{
  opacity:0;
  transform:translateY(1.1rem);
  transition:opacity .45s cubic-bezier(.22,.61,.27,1), transform .45s cubic-bezier(.22,.61,.27,1);
  transition-delay:var(--d, 0s);
}
html.is-ready .ar{ opacity:1; transform:none; }

/* headline word-masks: letters rise from their baseline */
.wm{
  display:inline-block;
  overflow:hidden;
  vertical-align:bottom;
  padding:.08em .04em .14em 0;
  margin:-.08em -.04em -.14em 0;
}
.wm-i{
  display:inline-block;
  transform:translateY(114%);
  transition:transform 1.15s cubic-bezier(.22,.61,.27,1);
  transition-delay:calc(.18s + var(--w, 0) * .07s);
  will-change:transform;
}
html.is-ready .wm-i{ transform:translateY(0); }

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior:auto; }
  .rv, .ar{ opacity:1; transform:none; transition:none; }
  .wm-i{ transform:none; transition:none; }
  .veil{ display:none; }
  .crest-glow{ opacity:1; transform:none; transition:none; }
  .hero-still{ transform:none; transition:none; }
  *{ animation-duration:.001s !important; transition-duration:.001s !important; }
}

/* ============================================================
   NAV
   ============================================================ */

.nav{
  position:fixed;
  inset:0 0 auto 0;
  z-index:60;
  transition:background-color .45s ease, border-color .45s ease, color .45s ease;
  border-bottom:1px solid transparent;
  /* over the hero photo the bar is light; it inverts to ink once solid */
  color:var(--paper);
}
.nav .brand .mark{ background:currentColor; }
.nav .brand small{ color:var(--light-60); }
.nav .nav-links a{ color:var(--light-60); }
.nav .nav-links a::after{ background:var(--paper); }
.nav .nav-links a:hover{ color:var(--paper); }
.nav .nav-tel{ border-color:var(--line-light); color:var(--paper); }
.nav .nav-tel:hover{ background:var(--paper); border-color:var(--paper); color:var(--navy); }
.nav.is-solid{
  background:var(--paper);
  border-bottom-color:var(--line-soft);
  color:var(--navy);
}
.nav.is-solid .brand small{ color:var(--ink-60); }
.nav.is-solid .nav-links a{ color:var(--ink-60); }
.nav.is-solid .nav-links a::after{ background:var(--navy); }
.nav.is-solid .nav-links a:hover{ color:var(--navy); }
.nav.is-solid .nav-tel{ border-color:var(--line); color:var(--navy); }
.nav.is-solid .nav-tel:hover{ background:var(--navy); border-color:var(--navy); color:var(--paper); }
/* Dark-page variant of the solid bar (/projects). The plain .nav treatment is
   already built for dark ground, but on desktop it hides the brand (there it
   hands off to the hero mark), so this keeps the solid bar's layout and swaps
   only the palette. Every rule is :not(.is-open) - below 769px the open menu
   forces its own paper panel and navy ink, and these are more specific than
   those rules, so without the guard they would win and put white type and a
   white logo on a white bar. */
.nav.is-solid.on-dark:not(.is-open){
  background:var(--navy-deep);
  border-bottom-color:var(--line-light-2);
  color:var(--paper);
}
.nav.is-solid.on-dark:not(.is-open) .brand small{ color:var(--light-60); }
.nav.is-solid.on-dark:not(.is-open) .brand-logo-light{ display:block; }
.nav.is-solid.on-dark:not(.is-open) .brand-logo-dark{ display:none; }
.nav.is-solid.on-dark:not(.is-open) .nav-links a{ color:var(--light-60); }
.nav.is-solid.on-dark:not(.is-open) .nav-links a::after{ background:var(--paper); }
.nav.is-solid.on-dark:not(.is-open) .nav-links a:hover{ color:var(--paper); }
.nav.is-solid.on-dark:not(.is-open) .nav-tel{ border-color:var(--line-light); color:var(--paper); }
.nav.is-solid.on-dark:not(.is-open) .nav-tel:hover{ background:var(--paper); border-color:var(--paper); color:var(--navy); }
/* the navy-on-navy CTA would disappear against the bar */
.nav.is-solid.on-dark:not(.is-open) .btn-primary{ background:var(--paper); color:var(--navy); border-color:var(--paper); }
.nav.is-solid.on-dark:not(.is-open) .btn-primary:hover{ background:transparent; color:var(--paper); }
.nav-inner{
  max-width:90rem;
  margin-inline:auto;
  padding:1.1rem var(--gutter);
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:1.5rem;
}
/* the phone number and the quote button travel together on the right */
.nav-right{
  display:flex;
  align-items:center;
  gap:1rem;
}
/* Both are single-line controls. Without this the flex basis of 0 below lets
   the cluster shrink under its content and "Get a quote" breaks onto two
   lines around 950-1200px; nowrap raises their min-content so the cluster
   refuses to shrink that far and the brand side absorbs the squeeze instead. */
.nav-right .nav-tel,
.nav-right .nav-cta{ white-space:nowrap; }
/* Links centred on the BAR, not on the space left over between the brand and
   the buttons - those two are very different widths, so centring in the gap
   would sit the links noticeably left. Giving the brand and the right-hand
   cluster an equal flex basis of 0 makes them take equal shares of the free
   space, which puts the middle child on the bar's true centre. Desktop only:
   below 769px the links become the dropdown panel and leave the flow. */
@media (min-width: 769px){
  .nav-inner{ justify-content:flex-start; }
  .brand{ flex:1 1 0; }
  .nav-nav{ flex:0 0 auto; }
  .nav-right{ flex:1 1 0; justify-content:flex-end; }
}
.brand{
  display:flex;
  align-items:center;
  gap:.8rem;
  font-weight:600;
  letter-spacing:.26em;
  font-size:1rem;
}
/* the mark: white over the hero photo, full-colour once the bar goes solid */
.brand-logo{ display:block; height:2.65rem; width:auto; }
.brand-logo-dark{ display:none; }
.nav.is-solid .brand-logo-light,
.nav.is-open .brand-logo-light{ display:none; }
.nav.is-solid .brand-logo-dark,
.nav.is-open .brand-logo-dark{ display:block; }
.brand{ transition:opacity .5s ease; }
/* on desktop the mark lives large on the hero; it hands off to the bar on scroll */
@media (min-width:769px){
  .nav:not(.is-solid) .brand{ opacity:0; pointer-events:none; }
}
.brand .mark{
  display:inline-block;
  width:.55rem; height:.55rem;
  background:var(--navy);
  transform:translateY(-1px);
}
.brand small{
  font-weight:400;
  font-size:.625rem;
  letter-spacing:.28em;
  color:var(--ink-60);
  text-transform:uppercase;
}
.nav-links{
  display:flex;
  gap:2.1rem;
  list-style:none;
  font-size:.75rem;
  font-weight:500;
  letter-spacing:.18em;
  text-transform:uppercase;
}
.nav-links a{
  position:relative;
  padding-block:.35rem;
  color:var(--ink-60);
  transition:color .3s ease;
}
.nav-links a::after{
  content:"";
  position:absolute;
  left:0; bottom:0;
  width:100%; height:1px;
  background:var(--navy);
  transform:scaleX(0);
  transform-origin:right center;
  transition:transform .45s cubic-bezier(.22,.61,.27,1);
}
.nav-links a:hover{ color:var(--navy); }
.nav-links a:hover::after{ transform:scaleX(1); transform-origin:left center; }

/* Services flyout - a small caret + panel of the four material links. Sits
   as a fourth nav state alongside the bar's transparent/solid/on-dark ones,
   so its own colour rules are written at the same specificity as each of
   those (nav-links swapped for nav-sub) and placed after them, rather than
   inheriting whatever the bar happens to be doing underneath it: the panel
   is always an opaque paper card, never the translucent-over-hero bar. */
.nav-has-sub{ position:relative; }
.nav-caret{
  display:inline-block;
  width:0; height:0;
  margin-left:.4em;
  vertical-align:.14em;
  border-left:.28em solid transparent;
  border-right:.28em solid transparent;
  border-top:.32em solid currentColor;
  opacity:.65;
  transition:transform .3s cubic-bezier(.22,.61,.27,1);
}
.nav-has-sub:hover .nav-caret,
.nav-has-sub:focus-within .nav-caret{ transform:rotate(180deg); }
.nav-sub{
  position:absolute;
  top:100%; left:50%;
  margin-top:.3rem;
  min-width:10.5rem;
  list-style:none;
  background:var(--paper);
  border:1px solid var(--line-soft);
  box-shadow:0 24px 40px -28px rgba(14,34,64,.5);
  padding:.4rem;
  opacity:0;
  visibility:hidden;
  pointer-events:none;
  transform:translate(-50%, -4px);
  transition:opacity .25s ease, transform .25s cubic-bezier(.22,.61,.27,1), visibility 0s linear .25s;
}
.nav-has-sub:hover .nav-sub,
.nav-has-sub:focus-within .nav-sub{
  opacity:1;
  visibility:visible;
  pointer-events:auto;
  transform:translate(-50%, 0);
  transition:opacity .25s ease, transform .25s cubic-bezier(.22,.61,.27,1), visibility 0s;
}
.nav-sub a{
  display:block;
  padding:.5rem .75rem;
  font-size:.6875rem;
  letter-spacing:.13em;
  white-space:nowrap;
}
.nav-sub a::after{ display:none; }
.nav .nav-sub a{ color:var(--ink-60) !important; }
.nav.is-solid .nav-sub a{ color:var(--ink-60) !important; }
.nav.is-solid.on-dark:not(.is-open) .nav-sub a{ color:var(--ink-60) !important; }
.nav-sub a:hover{ color:var(--navy) !important; background:var(--paper-2); }
.nav-tel{
  font-size:.8125rem;
  font-weight:500;
  letter-spacing:.08em;
  white-space:nowrap;
  border:1px solid var(--line);
  padding:.55rem 1.1rem;
  display:inline-flex;
  align-items:center;
  min-height:44px;
  transition:background .35s ease, color .35s ease, border-color .35s ease;
}
.nav-tel:hover{
  background:var(--navy);
  border-color:var(--navy);
  color:var(--paper);
}

/* the mobile menu control + phone-in-menu: hidden on desktop, shown ≤768 */
.nav-links-tel{ display:none; }
.nav-toggle{
  display:none;
  align-items:center;
  gap:.6rem;
  background:transparent;
  border:0;
  padding:.4rem .2rem;
  cursor:pointer;
  color:inherit;
  font:inherit;
  min-height:44px;
}
.nav-toggle-label{
  font-size:.75rem;
  font-weight:500;
  letter-spacing:.18em;
  text-transform:uppercase;
}
.nav-toggle-box{
  display:inline-flex;
  flex-direction:column;
  justify-content:center;
  gap:.32rem;
  width:1.35rem;
  height:1rem;
}
.nav-toggle-box span{
  display:block;
  height:1.5px;
  width:100%;
  background:currentColor;
  transition:transform .35s cubic-bezier(.22,.61,.27,1), opacity .3s ease;
}
.nav.is-open .nav-toggle-box span:first-child{ transform:translateY(.41rem) rotate(45deg); }
.nav.is-open .nav-toggle-box span:last-child{ transform:translateY(-.41rem) rotate(-45deg); }

/* ============================================================
   01 - HERO  (light)
   ============================================================ */

/* The stage fills a screen's worth of height and holds the type over the
   shot: a looping video on the home page (app.js §14), a plain static image
   on the projects page. Neither pins or grows - .hero-track is now just a
   wrapper, kept for the two pages to share this same styling. */
.hero{
  /* the generic section padding would otherwise band the shot top and bottom;
     the stage carries the hero's own spacing now */
  padding:0;
  background:
    linear-gradient(168deg, rgba(255,255,255,.65) 0%, rgba(255,255,255,0) 44%),
    linear-gradient(0deg, var(--paper-2) 0%, var(--paper) 56%);
}
.hero-track{ position:relative; }
.hero-stage{
  position:relative;
  min-height:100svh;
  display:flex;
  flex-direction:column;
  justify-content:flex-end;
  padding:8.5rem var(--gutter) 0;
  overflow:hidden;
}
.hero-grid{
  max-width:90rem;
  margin-inline:auto;
  width:100%;
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,26rem);
  gap:3rem;
  align-items:end;
}
.hero h1{
  font-size:clamp(2.9rem, 9.2vw, 8.25rem);
  font-weight:200;
  line-height:.98;
  letter-spacing:-.025em;
  text-wrap:balance;
  max-width:13em;
}
.hero h1 em.word{ font-size:.97em; }
/* the mark sits large on the right of the hero, then hands off to the nav bar */
.hero-brand{
  align-self:center;
  justify-self:center;
  padding-bottom:1rem;
}
.hero-brand img{
  display:block;
  height:clamp(10rem, 23vw, 20rem);
  width:auto;
  margin:0 auto;
}
/* ============================================================
   02 - THE STORY IN THREE DATES  (navy, pinned)
   ============================================================ */

.story{
  background:
    radial-gradient(120% 90% at 85% -10%, rgba(94,127,163,.18) 0%, rgba(94,127,163,0) 55%),
    var(--navy);
  color:var(--paper);
}
.story-year{
  font-size:clamp(5rem, 13vw, 12.5rem);
  font-weight:200;
  letter-spacing:-.05em;
  line-height:.9;
  color:var(--paper);
}
.story-year sup{
  font-size:.14em;
  font-weight:400;
  letter-spacing:.3em;
  text-transform:uppercase;
  color:var(--steel-pale);
  vertical-align:top;
  top:1.4em;
  position:relative;
}
.story-copy h3{
  font-size:clamp(1.3rem, 2.2vw, 1.8rem);
  font-weight:400;
  letter-spacing:-.01em;
  line-height:1.3;
  margin-bottom:1.1rem;
  text-wrap:balance;
}
.story-copy p{
  color:var(--light-60);
  max-width:30em;
  font-size:1rem;
}
.story-foot{
  position:absolute;
  bottom:clamp(1.6rem, 5vh, 3rem);
  left:var(--gutter);
  right:var(--gutter);
  display:flex;
  justify-content:space-between;
  font-size:.6875rem;
  letter-spacing:.28em;
  text-transform:uppercase;
  /* raised from --light-40 (~3.45:1) to meet WCAG AA for small text on navy */
  color:rgba(242,244,246,.74);
}

/* - one archival plate per date. The past is rendered as memory:
   near-monochrome, cooled to the ink; the present-day showroom below
   is the only place colour returns. */
.story-text{
  display:grid;
  gap:clamp(.9rem, 2vh, 1.4rem);
  align-content:center;
  min-width:0;
}
.story-fig{
  position:relative;
  align-self:center;
  justify-self:end;
  border:1px solid var(--line-light);
  background:var(--navy-deep);
}
/* explicit width + fixed ratio so every date shows an identical portrait plate,
   centred and right-aligned, never overflowing or bottom-heavy */
.story-fig .fig{
  display:block;
  width:clamp(15rem, 23vw, 22rem);
  aspect-ratio:4 / 5;
  height:auto;
  margin-left:auto;
}
.story-fig .fig img{ filter:grayscale(.72) saturate(.72) contrast(1.06) brightness(.9); object-position:center; }
.story-fig .fig::after{
  background:linear-gradient(168deg, rgba(14,34,64,.32) 0%, rgba(8,18,34,.62) 100%);
}
.story-fig figcaption{
  position:absolute;
  left:0; right:0; bottom:0;
  z-index:2;
  padding:1.1rem 1.15rem .95rem;
  display:flex;
  justify-content:space-between;
  align-items:baseline;
  gap:1rem;
  font-size:.625rem;
  font-weight:500;
  letter-spacing:.24em;
  text-transform:uppercase;
  color:var(--light-60);
  background:linear-gradient(to top, rgba(6,14,28,.86) 0%, rgba(6,14,28,0) 100%);
}
.story-fig figcaption b{ color:var(--steel-pale); font-weight:500; white-space:nowrap; }

/* ============================================================
   03 - THE SHOWROOM  (light, material panels)
   ============================================================ */

.showroom{
  background:var(--paper);
  padding-block:clamp(3rem, 6vh, 5rem) 0;
}
.showroom-intro{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
  margin-bottom:clamp(2rem, 4.5vh, 3.5rem);
  position:relative;
  z-index:1;
}
.showroom-intro h2{
  font-size:clamp(2.2rem, 5.4vw, 4.6rem);
  font-weight:200;
  letter-spacing:-.02em;
  line-height:1.05;
  margin-top:1.6rem;
  max-width:15em;
  text-wrap:balance;
}
.showroom-intro p{
  margin-top:1.75rem;
  max-width:var(--measure);
  color:var(--ink-60);
}

/* ---- MATERIALS as alternating bands ----------------------------------------
   A wide photograph on one side; a large faint numeral and a hairline
   connector (the site's set-out mark) in the opposite margin; the copy set
   over a navy scrim at the panel's left edge, reading title, description,
   brand wall, button. The photograph and the numeral alternate sides via
   :nth-child, so a sixth band just continues the zig-zag; the copy inside
   the panel does not alternate with them.
   Reveals reuse .rv (the numeral stays faint because its softness is a colour
   alpha, not opacity). Stacks to a readable photo-and-caption on phones. */
.mat-bands{
  max-width:96rem;
  margin-inline:auto;
  padding:0 var(--gutter) clamp(2rem, 4vh, 3rem);
  display:flex;
  flex-direction:column;
  gap:clamp(1rem, 2.5vh, 1.5rem);
}
.mat-band{
  display:flex;
  align-items:center;
  gap:clamp(1.5rem, 4vw, 4rem);
}
.mat-band:nth-child(even){ flex-direction:row-reverse; }

/* the numeral + connector, out in the margin */
.mat-mark{
  flex:0 0 clamp(6rem, 27%, 21rem);
  display:flex;
  align-items:center;
  gap:clamp(1rem, 2.5vw, 2.5rem);
}
.mat-band:nth-child(even) .mat-mark{ flex-direction:row-reverse; }
.mat-num{
  font-size:clamp(4.5rem, 11vw, 11rem);
  font-weight:200;
  line-height:.8;
  letter-spacing:-.03em;
  color:rgba(74,107,144,.4);       /* steel, softened by alpha so .rv lands it faint */
}
.mat-rule{
  flex:1;
  height:1px;
  background:var(--line);
  position:relative;
}
.mat-rule::after{                  /* set-out dot at the photo-facing end */
  content:"";
  position:absolute;
  top:50%;
  right:-3.5px;
  width:7px; height:7px;
  border-radius:50%;
  background:var(--steel);
  transform:translateY(-50%);
}
.mat-band:nth-child(even) .mat-rule::after{ right:auto; left:-3.5px; }

/* The band panel: a photograph of the band's own material, under a navy veil,
   with the title and the marks reversed out in white.
   An earlier version set navy type straight over room photos, and every mark
   needed a glow painted behind it to hold it off a busy floor - which is what
   made them look grubby. Reversed out of a veil this dark, white type and
   single-ink marks hold on their own, so there are no halos. The veil is
   deepest on the side the title sits, and eases toward the far edge so the
   floor still reads. */
.mat-panel{
  flex:1 1 auto;
  position:relative;
  isolation:isolate;
  overflow:hidden;
  background:var(--navy);          /* shows while the photo loads */
  padding:clamp(1.6rem, 3vw, 2.8rem);
  display:flex;
  flex-direction:column;
  justify-content:center;
  gap:.55rem;
}
.mat-panel > .fig{ position:absolute; inset:0; z-index:-1; }
/* the band is a thin strip of a landscape photo, and in every one of these
   the floor is in the lower part of the frame - crop there, not the middle */
.mat-panel > .fig img{ object-position:50% 78%; }
/* Two veils, not one. The side veil is deepest under the title and eases off
   hard toward the far edge, so most of the photograph now reads as a floor
   rather than a navy wash; the foot veil then darkens the last third of the
   band, where the brand marks and the button sit, enough for white to hold.
   Where they overlap - the near bottom corner - the total is about what the
   old flat veil was, so nothing got harder to read; everywhere else the
   material is roughly twice as visible.
   The side veil no longer mirrors on the even bands. It used to run to the
   centre-facing edge, which was right while the copy mirrored with it; now
   that every band's copy reads from the left, a mirrored veil would put the
   title over the thinnest part of the wash. Deep left, open right, in all
   five. The photograph and the margin numeral still alternate, which is what
   carries the zig-zag. */
.mat-panel > .fig::before{
  content:"";
  position:absolute; inset:0;
  z-index:1;
  background:
    linear-gradient(0deg,  rgba(8,20,38,.42) 0%, rgba(8,20,38,.08) 52%, rgba(8,20,38,0) 78%),
    linear-gradient(90deg, rgba(8,20,38,.78) 0%, rgba(8,20,38,.46) 46%, rgba(8,20,38,.24) 100%);
  pointer-events:none;
}
.mat-copy{
  display:flex;
  flex-direction:column;
  gap:.45rem;
  color:var(--paper);
}
/* THE HEAD
   One row: the title and its line of description on the reading side, the
   button squared off against them on the other. Stacked under the logo wall
   the button cost the band a button's height plus its margin, for a control
   nobody reads in that order anyway - the eye goes title, description, marks.
   Set against the title it reads as the title's own call to action and the
   band loses about seventy pixels. The row does not reverse on the even
   bands: title, description and button sit the same way round in all five,
   so the eye picks up the next title where it left the last one instead of
   crossing the page for it. */
.mat-head{
  align-self:stretch;
  width:100%;
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:clamp(1.25rem, 3vw, 2.5rem);
}
/* min-width:0 so a long title wraps inside the row rather than shouldering
   the button off the end of the panel */
.mat-head-text{ min-width:0; }

/* The title has to win the band outright. It used to be set at the same
   optical size as the brand marks below it, so the eye had two things
   competing for the top of the hierarchy and settled on neither - which is
   what made the bands hard to scan. It is now roughly a third larger than the
   marks, and they have come down to meet it. The soft shadow is spread wide
   and low in opacity: over a lighter veil it does the work the veil used to,
   without reading as a halo. */
.mat-copy h3{
  font-size:clamp(1.65rem, 3vw, 2.65rem);
  font-weight:400;
  letter-spacing:-.022em;
  line-height:1.06;
  max-width:13em;
  text-wrap:balance;
  text-shadow:0 1px 20px rgba(8,20,38,.6), 0 1px 3px rgba(8,20,38,.45);
}
.mat-copy h3 a{
  color:inherit;
  border-bottom:1px solid rgba(242,244,246,.26);
  transition:border-color .35s ease;
}
.mat-copy h3 a:hover{ border-bottom-color:var(--paper); }
.mat-copy a:focus-visible{ outline-color:var(--steel-pale); }

/* the description: one line, and one line only. Anything longer and the band
   stops being a plate in a cabinet and starts being a paragraph with a photo
   behind it. Set at body weight but a step up in alpha from the page's
   --light-60, because it is sitting on a photograph rather than paper. */
.mat-lede{
  margin-top:.85rem;
  max-width:32em;
  font-size:clamp(.9375rem, 1.15vw, 1.0625rem);
  font-weight:300;
  line-height:1.55;
  color:rgba(242,244,246,.82);
  text-shadow:0 1px 16px rgba(8,20,38,.6);
  text-wrap:pretty;
}

/* the micro-cap that names the row below it. Without it the marks read as a
   second headline; with it they read as a caption, which is what they are. */
.mat-brands-label{
  align-self:stretch;
  width:100%;
  margin-top:clamp(1.4rem, 2.6vh, 2rem);
  padding-top:.95rem;
  /* a touch stronger than --line-light-2: over a photograph rather than a flat
     navy panel, the site's faintest hairline disappears altogether */
  border-top:1px solid rgba(242,244,246,.22);
  font-size:.625rem;
  font-weight:500;
  letter-spacing:.24em;
  text-transform:uppercase;
  color:rgba(157,179,201,.85);
}

/* THE LOGO WALL
   One row of four marks per band, each centred in an equal column, so the row
   keeps its rhythm whatever the marks' own widths are.

   Sizing is the whole problem here. A logo's bounding box is not its visual
   weight: capped to a single common height, the one-line wordmarks that fill
   their box (Interface, Brintons, Kahrs) shout, while the light scripts
   (Flowcrete, Sika) and the stacked lockups that carry two lines of type
   inside the same height (Karndean, Junckers, Ted Todd) all but disappear.
   That is what the old row got wrong. So every mark carries its own --h, set
   on the tag and matched by eye against its neighbours rather than measured. */
.mat-brands{
  display:grid;
  grid-template-columns:repeat(4, 1fr);
  align-items:center;
  justify-items:center;
  gap:1.15rem 1.5rem;
  margin-top:.9rem;
  /* The row must measure the panel, not its own contents. .mat-copy is a
     column flex, and the moment it aligns its children (flex-start on phones)
     they stop stretching and this grid collapses to fit-content - four columns
     sized to the marks, huddled at one end. Stretching it explicitly is what
     keeps the wall spanning the band. */
  align-self:stretch;
  width:100%;
}
/* The row is stretched the full width of the panel: the outer two marks sit
   flush to the edges and only the inner pair stay centred in their columns.
   Centring all four left the row visibly inset at both ends, floating inside
   the panel instead of measuring it. */
/* Bands that carry three marks rather than four (stair nosings) size their
   row to match, so the marks keep the band's rhythm instead of leaving a
   fourth column of air at the end. */
.mat-brands[data-count="3"]{ grid-template-columns:repeat(3, 1fr); }
.mat-brands img:first-of-type{ justify-self:start; }
.mat-brands img:last-of-type{ justify-self:end; }
/* The marks are measured against the panel rather than the viewport, so they
   step down with it instead of running out of the column when the band
   narrows. Above roughly a 625px panel the flat px height governs; below it
   the cqi term takes over. */
.mat-panel{ container-type:inline-size; }
/* Every --h is scaled by the same .72 rather than re-judged one mark at a
   time: the row was balanced against itself already, it was only ever too
   large against the title. The slight step back in opacity finishes the job -
   at full white the marks still pulled the eye first.
   Only the flat cap is scaled, not the cqi term. The cap is what governs on a
   wide panel, which is where the marks were competing with the title; the cqi
   term governs on a narrow one, where the row is already two columns of small
   marks and taking another quarter off them just made them illegible. */
.mat-brands img{
  height:min(calc(var(--h, 30) * .72px), calc(var(--h, 30) * .16cqi));
  width:auto;
  max-width:100%;
  object-fit:contain;
  /* the files are single-ink navy; flatten them to white over the veil */
  filter:brightness(0) invert(1);
  opacity:.82;
}

/* ---- MORE INFO ------------------------------------------------------------
   The reversed-out ghost button the hero already uses, at caption scale so it
   closes the band rather than competing with the title. The faint navy wash
   behind it is what lets it sit over the open part of the photograph, now
   that the veil no longer flattens that corner. */
.mat-more{
  flex:0 0 auto;
  white-space:nowrap;
  display:inline-flex;
  align-items:center;
  gap:.65rem;
  min-height:44px;
  padding:.7rem 1.45rem;
  font-size:.6875rem;
  font-weight:500;
  letter-spacing:.2em;
  text-transform:uppercase;
  /* Solid, not a ghost. A reversed-out outline is the quieter thing to do over
     a photograph, but it only holds where the veil is deep, and this button
     sits at the open end of the band - on a gym mural or a sunlit window it
     all but vanished. Filled with paper it is legible on every band whatever
     is behind it, and it inverts to navy on hover. No text shadow: the fill
     carries the contrast on its own. */
  color:var(--navy);
  background:var(--paper);
  border:1px solid var(--paper);
  transition:background .35s ease, color .35s ease, border-color .35s ease;
}
.mat-more:hover{ background:var(--navy); color:var(--paper); border-color:var(--navy); }
.mat-more:focus-visible{ outline-color:var(--steel-pale); }
.mat-more .mat-arw{ transition:transform .35s ease; }
.mat-more:hover .mat-arw{ transform:translateX(3px); }

/* phones: stack. The big margin numeral is dropped, the photo's alternation is
   off and every band reads straight down. Four marks across is too tight at
   this width, so the wall halves to two columns. */
@media (max-width: 900px){
  .mat-bands{ gap:clamp(1.25rem, 3vh, 2rem); }
  .mat-band, .mat-band:nth-child(even){ flex-direction:column; align-items:stretch; }
  .mat-mark{ display:none; }
  /* the head stacks - at this width the button beside the title would leave
     the title about two words of measure */
  .mat-head{
    flex-direction:column;
    align-items:flex-start;
    gap:1.3rem;
  }
  .mat-head-text{ width:100%; }
  .mat-copy h3{ max-width:none; }
  .mat-lede{ max-width:none; }
  /* two columns: the left one flushes left and the right one flushes right, so
     the block still measures the panel rather than floating inside it */
  .mat-brands{ grid-template-columns:repeat(2, 1fr); gap:1.35rem 1rem; }
  .mat-brands img:nth-child(odd){ justify-self:start; }
  .mat-brands img:nth-child(even){ justify-self:end; }
}

/* - safety flooring fleck - */
.tx-safety{
  background:
    radial-gradient(circle at 18% 32%, rgba(242,244,246,.55) 0 1.1px, transparent 1.4px),
    radial-gradient(circle at 72% 64%, rgba(157,179,201,.6) 0 1.3px, transparent 1.6px),
    radial-gradient(circle at 44% 82%, rgba(10,26,50,.5) 0 1.2px, transparent 1.5px),
    radial-gradient(circle at 88% 18%, rgba(242,244,246,.4) 0 1px, transparent 1.3px),
    radial-gradient(circle at 30% 60%, rgba(10,26,50,.45) 0 1px, transparent 1.3px),
    linear-gradient(150deg, #6D88A6 0%, var(--steel) 55%, #54749A 100%);
  background-size:2.3rem 2.1rem, 2.7rem 2.5rem, 2.1rem 2.4rem, 3.1rem 2.9rem, 1.9rem 2.2rem, 100% 100%;
}
/* ---- THE PAIN POINT (text column beside a full-height photograph) ----
   No fixed height anywhere: the grid row is sized by .pain-copy's content
   (padding included), and .pain-fig - a grid item with nothing but an
   absolutely-positioned image inside it, so it has no intrinsic height of
   its own - stretches to match via the grid's default align-items:stretch.
   Kicker/h2/body/button are the same components and .rv reveal every other
   section uses, just in a plain two-column layout rather than the showroom
   panels' floating-card-over-photo device. */
.pain{ background:var(--paper-2); border-block:1px solid var(--line); }
.pain-grid{
  display:grid;
  grid-template-columns:minmax(0,5fr) minmax(0,7fr);
  min-height:26rem;
}
.pain-copy{
  display:flex;
  flex-direction:column;
  justify-content:center;
  gap:1.4rem;
  padding:clamp(3rem, 7vh, 5rem) clamp(2rem, 5vw, 4.5rem);
}
.pain-copy h2{
  font-size:clamp(1.7rem, 3.2vw, 2.5rem);
  font-weight:200;
  line-height:1.2;
  letter-spacing:-.01em;
  max-width:20em;
}
.pain-copy > p{
  font-size:.9375rem;
  line-height:1.65;
  color:var(--ink-60);
  max-width:30em;
}
.pain-copy .btn{ margin-top:.4rem; align-self:flex-start; }
/* .pain-fig is the grid item that stretches to match .pain-copy's height;
   .fig (position:relative, overflow:hidden - style.css ~1857) does the
   actual cover-fit and the site's standard photo grade + navy-tint wash,
   same as every other real photograph on the site. */
.pain-fig{ position:relative; }
.pain-fig .fig{ width:100%; height:100%; }

/* ============================================================
   04 - THE CHELSEA COMMISSION  (navy interlude)
   ============================================================ */

.commission{
  background:
    radial-gradient(90% 70% at 10% 100%, rgba(94,127,163,.16) 0%, rgba(94,127,163,0) 60%),
    var(--navy-deep);
  color:var(--paper);
  padding-block:clamp(6rem, 14vh, 11rem);
}
.commission-grid{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
  display:grid;
  grid-template-columns:minmax(0, 1fr) minmax(0, 1.15fr);
  gap:clamp(3rem, 7vw, 7rem);
  align-items:center;
  position:relative;
  z-index:1;
}
/* the crest, set in CSS as it was set in Polysafe */
.crest-stage{
  display:grid;
  place-items:center;
  padding-block:1rem;
}
.crest{
  position:relative;
  width:clamp(19rem, 38vw, 29rem);
  aspect-ratio:1;
  display:grid;
  place-items:center;
}
/* a soft pool of light blooms behind the crest */
.crest-glow{
  position:absolute;
  inset:-34%;
  border-radius:50%;
  background:radial-gradient(circle, rgba(94,127,163,.4) 0%, rgba(94,127,163,0) 62%);
  opacity:0;
  transform:scale(.72);
  transition:opacity 1.8s ease .35s, transform 2s cubic-bezier(.22,.61,.27,1) .35s;
  pointer-events:none;
}
.commission.in .crest-glow{ opacity:1; transform:scale(1); }
.crest-core{
  display:grid;
  place-items:center;
  padding:0;
  position:relative;
  z-index:1;
}
.crest-badge{
  width:clamp(15rem, 36vw, 24rem);
  height:auto;
  filter:drop-shadow(0 8px 26px rgba(4,10,20,.45));
  /* settles into place as the section scrolls in */
  opacity:0;
  transform:scale(.85);
  transition:transform 1.3s cubic-bezier(.22,.61,.27,1) .25s, opacity 1s ease .25s;
}
.commission.in .crest-badge{ opacity:1; transform:none; }
@media (prefers-reduced-motion: reduce){
  .crest-badge{ opacity:1; transform:none; transition:none; }
}
.commission-copy h2{
  font-size:clamp(2.1rem, 4.6vw, 4rem);
  font-weight:200;
  letter-spacing:-.02em;
  line-height:1.08;
  margin-top:1.6rem;
  text-wrap:balance;
}
.commission-copy p{
  margin-top:1.6rem;
  color:var(--light-60);
  max-width:32em;
}
.commission-copy p strong{
  color:var(--paper);
  font-weight:400;
}
.commission-detail{
  margin-top:2.6rem;
  display:grid;
  grid-template-columns:repeat(2, minmax(0,1fr));
  border-top:1px solid var(--line-light);
}
.commission-detail div{
  padding:1.2rem 0 .2rem;
  font-size:.875rem;
  color:var(--light-60);
}
.commission-detail div + div{
  border-left:1px solid var(--line-light);
  padding-left:1.5rem;
}
.commission-detail b{
  display:block;
  font-weight:500;
  font-size:.6875rem;
  letter-spacing:.3em;
  text-transform:uppercase;
  color:var(--steel-pale);
  margin-bottom:.45rem;
}

/* ============================================================
   05 - SECTORS  (light, index strip)
   ============================================================ */

.sectors{
  background:var(--paper-2);
  padding-block:clamp(6rem, 13vh, 10rem) clamp(5rem, 10vh, 8rem);
}
.sectors-head{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
  display:flex;
  justify-content:space-between;
  align-items:flex-end;
  gap:2.5rem;
  margin-bottom:clamp(3rem, 7vh, 5rem);
  position:relative;
  z-index:1;
}
.sectors-head h2{
  font-size:clamp(2.2rem, 5.4vw, 4.6rem);
  font-weight:200;
  letter-spacing:-.02em;
  line-height:1.05;
  margin-top:1.6rem;
  text-wrap:balance;
}
.sectors-head p{
  max-width:21rem;
  color:var(--ink-60);
  font-size:.9375rem;
  padding-bottom:.6rem;
}
.sector-strip{
  border-block:1px solid var(--line);
  overflow:hidden;
  position:relative;
  z-index:1;
  -webkit-mask-image:linear-gradient(90deg, transparent 0, #000 3%, #000 97%, transparent 100%);
  mask-image:linear-gradient(90deg, transparent 0, #000 3%, #000 97%, transparent 100%);
}
/* the index lays itself across the screen like boards going down, and pauses to read */
.sector-row{
  display:flex;
  width:max-content;
  animation:sector-marquee 60s linear infinite;
}
.sector-strip:hover .sector-row,
.sector-strip:focus-within .sector-row{ animation-play-state:paused; }
.sector{
  flex:0 0 auto;
  width:clamp(15rem, 20vw, 20rem);
  padding:2.1rem 1.6rem 2.3rem;
  border-right:1px solid var(--line);
  transition:background .3s ease, color .3s ease;
  position:relative;
}
.sector:hover{
  background:var(--navy);
  color:var(--paper);
  padding-left:calc(1.6rem + 8px);
}
@keyframes sector-marquee{ from{ transform:translateX(0); } to{ transform:translateX(-50%); } }
@media (prefers-reduced-motion: reduce){
  .sector-strip{ overflow-x:auto; -webkit-mask-image:none; mask-image:none; }
  .sector-row{ animation:none; }
  .sector[aria-hidden="true"]{ display:none; }
}
.sector h3::before{
  content:none;
  display:inline-block;
  max-width:0;
  overflow:hidden;
  white-space:nowrap;
  vertical-align:bottom;
  transition:max-width .45s cubic-bezier(.22,.61,.27,1), margin-right .45s cubic-bezier(.22,.61,.27,1);
}
.sector:hover h3::before{ max-width:1.1em; margin-right:.3em; }
.sector i{
  font-style:normal;
  display:block;
  font-size:.6875rem;
  font-weight:500;
  letter-spacing:.3em;
  color:var(--steel);
  margin-bottom:2.6rem;
  transition:color .4s ease;
}
.sector:hover i{ color:var(--steel-pale); }
.sector h3{
  font-size:1.2rem;
  font-weight:400;
  letter-spacing:-.005em;
  margin-bottom:.35rem;
}
.sector p{
  font-size:.8125rem;
  line-height:1.55;
  color:var(--ink-60);
  transition:color .4s ease;
}
.sector:hover p{ color:var(--light-60); }

/* One sector is called out rather than listed: reactive maintenance is the
   work clients ring about first, so it carries the navy at rest instead of
   waiting for a hover. Against a row of pale cards a solid navy block is the
   loudest thing the strip can do without introducing a colour the palette
   does not already own. It still answers to the pointer - lifting to the
   raised navy and taking the same 8px step as its neighbours - so it reads
   as part of the row rather than a panel dropped on top of it. */
.sector--flag{
  background:var(--navy);
  color:var(--paper);
  border-right-color:rgba(242,244,246,.16);
}
.sector--flag h3{ color:var(--paper); }
.sector--flag p{ color:var(--steel-pale); }
.sector--flag i{ color:var(--steel-pale); }
.sector--flag:hover{
  background:var(--navy-soft);
  color:var(--paper);
}
.sector--flag:hover h3{ color:var(--paper); }
.sector--flag:hover p{ color:var(--steel-pale); }

/* ============================================================
   04·B - SELECTED CLIENTS  (logo wall, light)
   ============================================================ */
.clients{
  background:var(--paper);
  padding-block:clamp(4.5rem, 10vh, 7rem);
}
.clients-inner{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
}
.clients-head{
  display:flex;
  justify-content:space-between;
  align-items:flex-end;
  gap:2rem;
  margin-bottom:clamp(2.5rem, 6vh, 4rem);
}
.clients-head p{ max-width:24rem; color:var(--ink-60); font-size:.9375rem; padding-bottom:.4rem; }
.client-row{
  display:grid;
  grid-template-columns:repeat(4, minmax(0, 1fr));
  gap:1px;
  background:var(--line);
  border:1px solid var(--line);
}
.client{
  background:var(--paper);
  min-height:9rem;
  display:flex;
  align-items:center;
  justify-content:center;
  padding:1.75rem;
}
.client img{
  max-height:5rem;
  max-width:100%;
  width:auto;
  /* quiet, uniform ink by default; the real mark surfaces on hover/focus */
  filter:grayscale(1) brightness(.4);
  opacity:.62;
  transition:opacity .45s ease, filter .45s ease;
}
.client:hover img,
.client:focus-within img{ opacity:1; filter:none; }
@media (max-width: 760px){
  .client-row{ grid-template-columns:repeat(2, minmax(0,1fr)); }
  .clients-head{ flex-direction:column; align-items:flex-start; gap:1.25rem; }
}
@media (prefers-reduced-motion: reduce){
  .client img{ transition:none; }
}


/* ============================================================
   06·B - RECENT WORK  (photo gallery)
   ============================================================ */
.work{
  background:var(--paper-2);
  padding-block:clamp(5rem, 11vh, 8rem);
}
.work-inner{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
  margin-bottom:clamp(2.5rem, 6vh, 4rem);
}
.work-inner h2{
  font-size:clamp(2rem, 4.6vw, 3.6rem);
  font-weight:200;
  letter-spacing:-.02em;
  line-height:1.05;
  margin-top:1.2rem;
  text-wrap:balance;
}
.work-grid{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
  display:grid;
  grid-template-columns:repeat(3, minmax(0,1fr));
  gap:clamp(.75rem, 1.5vw, 1.25rem);
}
.work-item{
  margin:0;
  overflow:hidden;
  border:1px solid var(--line);
  background:var(--navy-deep);
}
.work-item .fig{ display:block; aspect-ratio:4 / 3; }
.work-item .fig img{
  filter:saturate(.86) contrast(1.05) brightness(1.0);
  transition:transform .9s cubic-bezier(.22,.61,.27,1), filter .5s ease;
}
.work-item:hover .fig img{ filter:saturate(1.06) contrast(1.05) brightness(1.03); }
.work-item figcaption{
  padding:.8rem .1rem .2rem;
  font-size:.625rem;
  font-weight:500;
  letter-spacing:.24em;
  text-transform:uppercase;
  color:var(--steel);
}
@media (max-width: 860px){ .work-grid{ grid-template-columns:repeat(2,1fr); } }
@media (max-width: 460px){ .work-grid{ grid-template-columns:1fr; } }
@media (prefers-reduced-motion: reduce){ .work-item .fig img{ transition:none; } }

/* ---- TESTIMONIAL BANNER ----------------------------------------------------
   A single full-width client quote on navy, breaking the white page rhythm
   the way .quote and .closing already do further down. The card is a raised
   navy-soft panel rather than a light card, so the banner stays inside the
   site's own palette instead of borrowing a generic light-card-on-dark
   template look. Bracketing quote marks reuse the mat-band numeral's faint
   treatment - colour alpha, not opacity. No photo or invented name: the
   only detail on record for this quote is the role and the company. */
.testimonial{
  background:var(--navy);       /* shows while the photo loads, and behind its edges */
  padding-block:clamp(5.5rem, 13vh, 9rem);
  isolation:isolate;
}
.testimonial > .fig{ position:absolute; inset:0; z-index:0; }
/* no card now to carry the text, so the veil alone has to hold contrast -
   darker and flatter than the hero's edge-to-edge fig--scrim */
.testimonial .fig--scrim::before{
  background:linear-gradient(165deg, rgba(6,15,30,.88) 0%, rgba(8,20,38,.76) 45%, rgba(6,15,30,.9) 100%);
}
.testimonial-inner{
  position:relative;
  z-index:1;
  max-width:72rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
}
.testimonial-mark{
  font-size:clamp(4rem, 7vw, 5.5rem);
}
.testimonial-inner:has(.testimonial-content + .testimonial-content) blockquote{
  font-size:clamp(1.15rem, 1.6vw, 1.45rem);
  line-height:1.5;
}
/* the quote sits straight on the photo - no card, just the bracketing marks
   and a navy text-shadow (the hero's own glow) to hold it off a busy photo */
.testimonial-content{
  position:relative;
  padding-top:clamp(3.75rem, 8vw, 5.5rem);
  padding-bottom:clamp(3rem, 7vw, 4.5rem);
}
.testimonial-mark{
  position:absolute;
  top:0; left:0;
  font-family:var(--serif);
  font-size:clamp(6rem, 12vw, 9rem);
  line-height:1;
  color:rgba(242,244,246,.3);
  text-shadow:0 1px 24px rgba(8,20,38,.4);
  pointer-events:none;
  user-select:none;
}
.testimonial-mark.is-close{
  top:auto; left:auto;
  bottom:0; right:0;
}
.testimonial-content blockquote,
.testimonial-statement{
  font-family:var(--serif);
  font-style:italic;
  font-size:clamp(1.5rem, 2.6vw, 2.25rem);
  line-height:1.42;
  color:var(--paper);
  text-shadow:0 1px 34px rgba(8,20,38,.5);
  text-wrap:pretty;
  max-width:42em;
}
/* one short line, not a paragraph of quote - even the two lines out */
.testimonial-statement{ text-wrap:balance; }
.testimonial-content figcaption{
  margin-top:1.75rem;
  padding-top:1.5rem;
  border-top:1px solid var(--line-light);
  display:flex;
  align-items:baseline;
  flex-wrap:wrap;
  gap:.2rem .85rem;
}
.testimonial-role{
  font-size:1.0625rem;
  font-weight:600;
  color:var(--paper);
  text-shadow:0 1px 20px rgba(8,20,38,.5);
}
.testimonial-co{
  font-size:.8125rem;
  font-weight:500;
  letter-spacing:.03em;
  color:var(--steel-pale);
  text-shadow:0 1px 20px rgba(8,20,38,.5);
}
@media (max-width: 640px){
  .testimonial{ padding-block:clamp(4rem, 10vh, 6rem); }
  .testimonial-mark{ font-size:clamp(4.5rem, 22vw, 7rem); }
  .testimonial-content{ padding-top:clamp(3rem, 20vw, 4rem); padding-bottom:clamp(2.5rem, 14vw, 3.5rem); }
}

/* ============================================================
   08 - CLOSING BAND  (navy)
   ============================================================ */

address{ font-style:normal; line-height:1.7; }

.closing{
  background:var(--navy);
  color:var(--paper);
  padding-block:clamp(3.5rem, 8vh, 5.5rem) 2.25rem;
}
.closing-inner{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
}
.closing-statement{
  display:flex;
  justify-content:space-between;
  align-items:flex-end;
  gap:2.5rem;
  padding-bottom:2.75rem;
  border-bottom:1px solid var(--line-light);
}
.closing-statement p{
  font-size:clamp(1.5rem, 3.4vw, 2.6rem);
  font-weight:200;
  letter-spacing:-.015em;
  line-height:1.2;
  max-width:18em;
  text-wrap:balance;
}
.back-top{
  font-size:.6875rem;
  font-weight:500;
  letter-spacing:.3em;
  text-transform:uppercase;
  color:var(--light-60);
  white-space:nowrap;
  display:inline-flex;
  align-items:center;
  gap:.8rem;
  min-height:44px;
  transition:color .3s ease;
}
.back-top:hover{ color:var(--paper); }
.back-top::after{
  content:"\2191";
  font-size:1rem;
  letter-spacing:0;
}
/* footer contact + accreditation grid */
.footer-grid{
  margin-top:clamp(2.5rem, 5vh, 3.5rem);
  padding-top:clamp(2rem, 4vh, 2.75rem);
  border-top:1px solid var(--line-light);
  display:grid;
  grid-template-columns:repeat(4, minmax(0, 1fr));
  gap:2.5rem;
  font-size:.9375rem;
  line-height:1.7;
  color:var(--light-60);
}
.footer-col b{
  display:block;
  font-weight:500;
  font-size:.6875rem;
  letter-spacing:.3em;
  text-transform:uppercase;
  color:var(--steel-pale);
  margin-bottom:1rem;
}
.footer-col a{
  color:var(--light-60);
  border-bottom:1px solid var(--line-light);
  transition:color .3s ease, border-color .3s ease;
}
.footer-col a:hover{ color:var(--paper); border-color:var(--paper); }
.footer-col address{ font-style:normal; }
.footer-sub{ margin-top:.6rem; }
.footer-accred-logos{ display:flex; align-items:center; gap:1rem; flex-wrap:wrap; }
/* white chip so both circular badges (incl. the navy SafeContractor) read on navy */
.footer-badge{
  display:inline-flex;
  width:3.7rem; height:3.7rem;
  background:var(--paper);
  border-radius:50%;
  padding:.3rem;
}
.footer-badge img{ width:100%; height:100%; object-fit:contain; }
@media (max-width: 860px){ .footer-grid{ grid-template-columns:repeat(2, 1fr); gap:2rem; } }
@media (max-width: 460px){ .footer-grid{ grid-template-columns:1fr; } }

.closing-meta{
  margin-top:clamp(2.5rem, 5vh, 3.5rem);
  padding-top:1.75rem;
  border-top:1px solid var(--line-light);
  display:flex;
  flex-wrap:wrap;
  justify-content:space-between;
  gap:.9rem 2.5rem;
  font-size:.6875rem;
  font-weight:400;
  letter-spacing:.22em;
  text-transform:uppercase;
  /* raised from --light-40 (~3.45:1) to meet WCAG AA for small text on navy */
  color:rgba(242,244,246,.74);
}

/* ============================================================
   PHOTOGRAPHY - the star of this direction.
   Graded minimally: a crisp cool wash, never heavy duotone.
   ============================================================ */

/* shared figure: aspect box prevents layout shift, cover never stretches */
.fig{
  position:relative;
  overflow:hidden;
  background:var(--paper-3);
}
.fig img{
  display:block;
  width:100%;
  height:100%;
  object-fit:cover;
  /* the north-light grade: lift a touch, cool the shadows, hold the crisp */
  filter:saturate(.86) contrast(1.04) brightness(1.005);
}
/* a whisper of navy in the shadows - keeps photos in-palette without muddying */
.fig::after{
  content:"";
  position:absolute; inset:0;
  background:linear-gradient(170deg, rgba(94,127,163,.10) 0%, rgba(14,34,64,.05) 100%);
  mix-blend-mode:multiply;
  pointer-events:none;
}
/* hero photo lives behind text on navy - needs a gradient scrim, never flat */
.fig--scrim::before{
  content:"";
  position:absolute; inset:0;
  z-index:1;
  background:linear-gradient(186deg,
    rgba(8,20,38,.42) 0%,
    rgba(8,20,38,.10) 26%,
    rgba(8,20,38,.05) 40%,
    rgba(8,20,38,.48) 84%,
    rgba(8,20,38,.70) 100%);
  pointer-events:none;
}

/* ---- HERO photo bed ------------------------------------------ */
.hero{ isolation:isolate; }
.hero-photo{
  position:absolute;
  inset:0;
  z-index:0;
}
.hero-photo .fig{ width:100%; height:100%; }

/* The home hero runs a looping video (app.js §14); the projects hero below is
   a plain static image. Both sit over a still that carries the section
   before the video is ready, and stays put for good under reduced motion, on
   a metered link, or with no JS - which is the projects hero's permanent
   state. Covered to the stage, so the shot fills the screen at any shape. */
.hero-video,
.hero-still{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  display:block;
  object-fit:cover;
}
.hero-video{ opacity:0; transition:opacity .8s cubic-bezier(.22,.61,.27,1); }
.hero.is-painted .hero-video{ opacity:1; }
.hero.is-painted .hero-still{ opacity:0; }
.hero-scrim{
  position:absolute;
  inset:0;
  z-index:1;
  pointer-events:none;
  background:linear-gradient(186deg,
    rgba(8,20,38,.42) 0%, rgba(8,20,38,.10) 26%,
    rgba(8,20,38,.05) 40%, rgba(8,20,38,.48) 84%, rgba(8,20,38,.70) 100%);
}
/* The video hero drops the full-frame tint, but the copy still needs ground
   to sit on: a soft pool under the type and ticks, fading out well before the
   centre of the frame, so the gym itself - the equipment, the glazing, the
   mural on the right - stays clean. Desktop only, to match the text-shadow
   rules below it: on mobile the copy sits below the photo band on solid
   paper (see max-width:1024px further down), so the original light foot-scrim
   there is left alone. Higher specificity than the plain .hero-scrim rule
   above and the desktop breakpoint override below, so it wins there. */
@media (min-width: 1025px){
  .hero[data-hero-video] .hero-scrim{
    background:
      linear-gradient(100deg, rgba(8,20,38,.62) 0%, rgba(8,20,38,.32) 30%, rgba(8,20,38,0) 56%),
      linear-gradient(0deg, rgba(8,20,38,.58) 0%, rgba(8,20,38,.14) 34%, rgba(8,20,38,0) 55%);
  }
}
/* Belt and braces: a tighter, darker shadow than the rest of the site uses,
   so the type still reads over whatever lands behind it as the shot moves -
   glazing and sky included, not just the floor. Desktop only: below 1025px
   the copy sits on solid paper under the photo band, not over it (see the
   max-width:1024px rules further down), so no shadow is needed there and one
   would just muddy the type against a light background. */
@media (min-width: 1025px){
  .hero[data-hero-video] h1{
    text-shadow:0 1px 3px rgba(8,20,38,.85), 0 4px 24px rgba(8,20,38,.55);
  }
  .hero[data-hero-video] .hero-cta .btn-ghost{
    text-shadow:0 1px 3px rgba(8,20,38,.8);
  }
}
/* sit the shot on the cool light, slightly brighter than the panels */
.hero-video,
.hero-still{ filter:saturate(.82) contrast(1.03) brightness(1.02); }
/* The still drifts in on arrival. The video never does - it has its own
   motion, and a transform running underneath it would read as drag. */
.hero-still{
  transform:scale(1.04);
  transition:transform 16s linear;
}
html.is-ready .hero-still{ transform:scale(1); }
@media (prefers-reduced-motion: reduce){
  .hero-still{ transform:none; transition:none; }
}
/* headline + furniture sit over the scrimmed foot of the photo: go light */
.hero-grid{ position:relative; z-index:2; }
.hero{ color:var(--paper); }
.hero h1{ color:var(--paper); text-shadow:0 1px 34px rgba(8,20,38,.45); }
/* the projects hero reuses this bed with a kicker and a lede rather than the
   tick list, and both default to ink - illegible on a photograph */
.hero .kicker{ color:var(--steel-pale); }
.hero .res-lede{ color:var(--light-60); }
.hero ::selection{ background:var(--paper); color:var(--navy); }

/* ============================================================
   ATMOSPHERE - paper grain on light, vignette on navy
   ============================================================ */

/* Restraint: the gallery-light sections stay crisp paper - the grain was an
   accessory that fought the photography. Kept only as a whisper on the flat
   text sections; the showroom (photos are the star) carries none. */
.sectors::after,
.method::after, .firm::after{
  content:"";
  position:absolute;
  inset:0;
  z-index:4;
  pointer-events:none;
  opacity:.28;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 0.055 0 0 0 0 0.13 0 0 0 0 0.25 0 0 0 0.06 0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)'/%3E%3C/svg%3E");
}
.commission::after, .closing::after, .invite::after{
  content:"";
  position:absolute;
  inset:0;
  z-index:4;
  pointer-events:none;
  background:radial-gradient(120% 105% at 50% 42%, rgba(4,10,20,0) 56%, rgba(4,10,20,.3) 100%);
}
.closing{ position:relative; overflow:hidden; }

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

@media (max-width: 1200px){
  .nav-links{ gap:1.5rem; }
  .story-year{ font-size:clamp(5.5rem, 18vw, 11rem); }
  /* the pinned scene is one viewport tall here - drop the plate so the
     numeral + copy never overflow. It returns once the scene goes static. */
  .story-fig{ display:none; }
}

@media (max-width: 768px){
  html{ scroll-padding-top:4.5rem; }
  .nav-toggle{ display:inline-flex; }
  /* the section links drop into a panel below the bar, toggled by the button.
     It always uses the solid (paper) treatment so it reads over any section. */
  .nav-nav{
    position:absolute;
    top:100%; left:0; right:0;
    background:var(--paper);
    border-bottom:1px solid var(--line-soft);
    box-shadow:0 24px 40px -28px rgba(14,34,64,.5);
    overflow:hidden;
    max-height:0;
    visibility:hidden;
    transition:max-height .42s cubic-bezier(.22,.61,.27,1), visibility 0s linear .42s;
  }
  .nav.is-open .nav-nav{
    max-height:min(80vh, 34rem);
    visibility:visible;
    /* on short/landscape viewports the panel can exceed its cap - let it scroll
       so the lower links (Contact, Call) stay reachable rather than clipped */
    overflow-y:auto;
    -webkit-overflow-scrolling:touch;
    transition:max-height .48s cubic-bezier(.22,.61,.27,1), visibility 0s;
  }
  .nav-links{
    display:flex;
    flex-direction:column;
    gap:0;
    max-width:90rem;
    margin-inline:auto;
    padding:.5rem var(--gutter) 1.25rem;
    letter-spacing:.14em;
  }
  .nav-links li{ border-top:1px solid var(--line-soft); }
  .nav-links li:first-child{ border-top:0; }
  .nav-links a{
    display:block;
    padding:1rem .1rem;
    color:var(--navy) !important;
    min-height:44px;
  }
  .nav-links a::after{ display:none; }
  .nav-links-tel{ display:block; }
  .nav-links-tel a{ color:var(--steel) !important; font-weight:500; }
  /* no hover on touch, so the flyout just becomes a stacked, always-open
     sublist under Services rather than something to trigger */
  .nav-caret{ display:none; }
  .nav-sub{
    position:static;
    opacity:1;
    visibility:visible;
    pointer-events:auto;
    transform:none;
    margin:0;
    min-width:0;
    padding:0 0 .25rem 1rem;
    border:0;
    box-shadow:none;
    background:transparent;
  }
  .nav-sub li{ border-top:0; }
  .nav-sub a{
    padding:.6rem .1rem;
    font-size:.75rem;
    color:var(--steel) !important;
  }
  /* the toggle + brand invert with the bar; force legible ink once solid/open */
  .nav.is-open{ background:rgba(242,244,246,.98); color:var(--navy); border-bottom-color:transparent; }
  .nav.is-open .brand small{ color:var(--ink-60); }
  .nav.is-open .nav-tel{ border-color:var(--line); color:var(--navy); }
  .hero-stage{ padding-top:7rem; }
  .hero-grid{ grid-template-columns:minmax(0,1fr); gap:2.25rem; }
  .hero-brand{ display:none; }
  .commission-grid{ grid-template-columns:minmax(0,1fr); }
  .crest-stage{ order:2; }
  .sectors-head{ flex-direction:column; align-items:flex-start; gap:1.5rem; }
  /* stacked, the "stretch to match the text column" trick has nothing to
     match, so the photo needs its own height back */
  .pain-grid{ grid-template-columns:minmax(0,1fr); min-height:0; }
  .pain-fig{ height:16rem; order:-1; }
  .closing-statement{ flex-direction:column; align-items:flex-start; gap:2rem; }
}

@media (max-width: 767.98px), (prefers-reduced-motion: reduce){
  .story-foot{
    position:static;
    left:auto; right:auto;
    max-width:90rem;
    margin-inline:auto;
    padding-inline:var(--gutter);
  }
  /* static scene has free height - bring the plate back, as a wide print
     beneath the copy rather than a tall side column */
  .story-fig{
    display:block;
    justify-self:stretch;
    max-width:none;
    margin-top:1.75rem;
  }
  .story-fig .fig{ height:auto; width:100%; aspect-ratio:16 / 10; }
  .story-foot{ padding-bottom:2.5rem; }
}

@media (max-width: 480px){
  :root{ --gutter:1.25rem; }
  body{ font-size:1rem; }
  .brand small{ display:none; }
  .nav-tel{ padding:.45rem .8rem; font-size:.75rem; }
  .story-foot span:last-child{ display:none; }
  .commission-detail{ grid-template-columns:minmax(0,1fr); }
  .commission-detail div + div{ border-left:0; padding-left:0; border-top:1px solid var(--line-light); margin-top:.4rem; padding-top:1.2rem; }
  .sector-row{ grid-auto-columns:minmax(11.5rem, 1fr); }
}

/* ============================================================
   RESOURCE CENTRE  (resources.html) - shares all furniture above
   ============================================================ */
.subpage{ background:var(--paper); }
/* Dark content pages (/projects). Set on <html> so the colour is also what
   shows behind an overscroll bounce, not just under the content. */
.subpage.is-dark{ background:var(--navy-deep); color:var(--paper); }
/* on a content page the bar is solid from the top, never over a hero photo */
.subpage .nav{ position:fixed; }
.res-head{
  padding:clamp(8rem, 16vh, 11rem) 0 clamp(3rem, 7vh, 5rem);
  border-bottom:1px solid var(--line);
}
.res-head h1{
  font-size:clamp(2.6rem, 7vw, 5.5rem);
  font-weight:200;
  letter-spacing:-.025em;
  line-height:1.02;
  margin-top:1.4rem;
  max-width:14em;
  text-wrap:balance;
}
.res-lede{
  margin-top:1.6rem;
  max-width:var(--measure);
  color:var(--ink-60);
}
.res-body{ padding-block:clamp(3.5rem, 8vh, 6rem) clamp(5rem, 11vh, 8rem); }
.res-group + .res-group{ margin-top:clamp(3rem, 7vh, 5rem); }
.res-group > .kicker{ margin-bottom:1.8rem; }
.res-card{
  background:var(--paper);
  padding:1.75rem 1.75rem 1.6rem;
  display:flex;
  flex-direction:column;
  gap:.6rem;
  min-height:13rem;
  text-decoration:none;
  color:inherit;
  position:relative;
  transition:background .4s ease;
}
.res-card:hover,
.res-card:focus-visible{ background:var(--paper-2); }
.res-card .r-label{
  font-size:.625rem;
  font-weight:500;
  letter-spacing:.28em;
  text-transform:uppercase;
  color:var(--steel);
}
.res-card h3{
  font-size:1.2rem;
  font-weight:400;
  letter-spacing:-.005em;
  line-height:1.25;
  margin-top:.2rem;
}
.res-card p{
  font-size:.875rem;
  line-height:1.55;
  color:var(--ink-60);
}
.res-card .r-action{
  margin-top:auto;
  padding-top:1rem;
  font-size:.6875rem;
  font-weight:500;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--navy);
  display:inline-flex;
  align-items:center;
  gap:.5rem;
}
.res-card .r-action::after{ content:"\2192"; transition:transform .35s cubic-bezier(.22,.61,.27,1); }
.res-card:hover .r-action::after{ transform:translateX(.3rem); }

/* ============================================================
   CONVERSION COMPONENTS  (buttons, value props, stats, FAQ, form)
   Structure adopted from the Figma; styled in the north-light palette.
   ============================================================ */

/* ---- buttons ---- */
.btn{
  display:inline-flex;
  align-items:center;
  gap:.6rem;
  min-height:46px;
  padding:.9rem 1.7rem;
  font-size:.75rem;
  font-weight:500;
  letter-spacing:.14em;
  text-transform:uppercase;
  border:1px solid transparent;
  cursor:pointer;
  transition:background .35s ease, color .35s ease, border-color .35s ease;
}
.btn-primary{ background:var(--navy); color:var(--paper); border-color:var(--navy); }
.btn-primary:hover{ background:var(--navy-soft); border-color:var(--navy-soft); }
.btn:disabled{ opacity:.45; cursor:not-allowed; }
.btn-ghost{ background:transparent; color:var(--navy); border-color:var(--line); }
.btn-ghost:hover{ border-color:var(--navy); }
/* over the hero photo the buttons go light */
.hero .btn-primary{ background:var(--paper); color:var(--navy); border-color:var(--paper); }
.hero .btn-primary:hover{ background:transparent; color:var(--paper); }
.hero .btn-ghost{ color:var(--paper); border-color:var(--line-light); }
.hero .btn-ghost:hover{ border-color:var(--paper); }

/* ---- header CTA ---- */
.nav-cta{ margin-left:.2rem; }
@media (max-width: 900px){ .nav-cta{ display:none; } }

/* ---- hero CTA ---- */
.hero-cta{
  margin-top:clamp(1.6rem, 3.5vh, 2.4rem);
  display:flex;
  flex-wrap:wrap;
  gap:1rem;
  align-items:center;
}

/* ---- stats bar ---- */
.stats-bar{ background:var(--paper); border-bottom:1px solid var(--line); }
.stats-bar-inner{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
  display:grid;
  grid-template-columns:repeat(3, 1fr);
}
.stat-cell{
  padding:clamp(2rem, 5vh, 3.2rem) 1.25rem;
  text-align:center;
  border-left:1px solid var(--line);
}
.stat-cell:first-child{ border-left:0; }
.stat-cell .n{
  font-size:clamp(2.2rem, 4.4vw, 3.6rem);
  font-weight:200;
  letter-spacing:-.02em;
  line-height:1;
  color:var(--navy);
}
.stat-cell .n sup{ font-size:.4em; font-weight:300; vertical-align:super; margin-left:.05em; }
.stat-cell .l{
  margin-top:.7rem;
  font-size:.6875rem;
  font-weight:500;
  letter-spacing:.22em;
  text-transform:uppercase;
  color:var(--steel);
}
@media (max-width: 720px){
  .stats-bar-inner{ grid-template-columns:repeat(2, 1fr); }
  /* Three cells into two columns leaves the third orphaned in the left one,
     reading as a mistake rather than a third of a set. It spans the row
     instead, so it centres under the pair above it. */
  .stat-cell:nth-child(3){ grid-column:1 / -1; border-left:0; }
  .stat-cell:nth-child(-n+2){ border-bottom:1px solid var(--line); }
}

/* ---- FAQ ---- */
.faq{ background:var(--paper-2); padding-block:clamp(6rem, 13vh, 10rem); }
.faq-grid{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
  display:grid;
  grid-template-columns:minmax(0, 1fr) minmax(0, 1.4fr);
  gap:clamp(2.5rem, 6vw, 6rem);
  align-items:start;
}
.faq-head h2{
  font-size:clamp(2.1rem, 4.8vw, 4rem);
  font-weight:200;
  letter-spacing:-.02em;
  line-height:1.08;
  margin-top:1.4rem;
  text-wrap:balance;
}
.faq-head p{ margin-top:1.5rem; color:var(--ink-60); max-width:24em; }
.faq-list{ border-top:1px solid var(--line); }
.faq-item{ border-bottom:1px solid var(--line); }
.faq-item summary{
  list-style:none;
  cursor:pointer;
  padding:1.5rem .25rem;
  display:flex;
  justify-content:space-between;
  align-items:center;
  gap:1.5rem;
  font-size:1.15rem;
  font-weight:400;
  letter-spacing:-.005em;
  color:var(--navy);
}
.faq-item summary::-webkit-details-marker{ display:none; }
.faq-item summary::after{
  content:"";
  flex:0 0 auto;
  width:1rem; height:1rem;
  background:
    linear-gradient(var(--steel),var(--steel)) center/100% 1.5px no-repeat,
    linear-gradient(var(--steel),var(--steel)) center/1.5px 100% no-repeat;
  transition:transform .4s cubic-bezier(.22,.61,.27,1);
}
.faq-item[open] summary::after{ transform:rotate(90deg); opacity:.5; }
.faq-item .faq-a{
  padding:0 .25rem 1.6rem;
  max-width:44em;
  color:var(--ink-60);
  font-size:.9375rem;
  line-height:1.65;
}
@media (max-width: 820px){ .faq-grid{ grid-template-columns:minmax(0,1fr); } }

/* ---- lead-capture / quote form ---- */
.quote{ background:var(--navy); color:var(--paper); padding-block:clamp(6rem, 13vh, 10rem); position:relative; overflow:hidden; }
.quote-grid{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
  display:grid;
  grid-template-columns:minmax(0, 1fr) minmax(0, 1.1fr);
  gap:clamp(3rem, 7vw, 7rem);
  position:relative;
  z-index:1;
}
.quote-copy h2{
  font-size:clamp(2.2rem, 5vw, 4.2rem);
  font-weight:200;
  letter-spacing:-.02em;
  line-height:1.05;
  margin-top:1.4rem;
  text-wrap:balance;
}
.quote-copy p{ margin-top:1.6rem; color:var(--light-60); max-width:30em; }
.quote-copy .quote-call{
  margin-top:2.2rem;
  display:inline-block;
  font-size:clamp(1.6rem, 3vw, 2.4rem);
  font-weight:300;
  border-bottom:1px solid var(--line-light);
  padding-bottom:.3rem;
  transition:border-color .3s ease, color .3s ease;
}
.quote-copy .quote-call:hover{ border-color:var(--paper); color:var(--steel-pale); }
.quote-form{ display:grid; gap:1.1rem; align-content:start; }
.field{ display:grid; gap:.5rem; }
.field.row2{ grid-template-columns:1fr 1fr; gap:1.1rem; }
.field label{
  font-size:.625rem; font-weight:500; letter-spacing:.24em;
  text-transform:uppercase; color:var(--steel-pale);
}
.field input, .field textarea{
  font:inherit;
  font-size:1rem;
  color:var(--paper);
  background:transparent;
  border:0;
  border-bottom:1px solid var(--line-light);
  padding:.7rem .1rem;
  transition:border-color .3s ease;
}
.field textarea{ resize:vertical; min-height:4.5rem; }
.field input:focus, .field textarea:focus{ outline:none; border-bottom-color:var(--paper); }
.field input::placeholder, .field textarea::placeholder{ color:var(--light-40); }
.quote-form .btn-primary{ background:var(--paper); color:var(--navy); border-color:var(--paper); justify-self:start; margin-top:.6rem; }
.quote-form .btn-primary:hover{ background:transparent; color:var(--paper); }
.quote-note{ font-size:.75rem; color:rgba(242,244,246,.78); }
@media (max-width: 820px){ .quote-grid{ grid-template-columns:minmax(0,1fr); } .field.row2{ grid-template-columns:1fr; } }

/* screen-reader-only utility (keeps heading order without showing the text) */
.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;
}

/* ============================================================
   ABOUT PAGE - new chapters, built from the North Light palette
   (about.html only; shares every token + all existing motion)
   ============================================================ */

/* ---- hero manifesto: the belief line + a quiet meta strip ---- */
.about-hero h1{ max-width:15em; }
.about-hero h1 em.word{ font-size:.98em; }
.about-meta{
  list-style:none;
  margin-top:clamp(1.75rem, 4vh, 2.5rem);
  display:flex;
  flex-wrap:wrap;
  gap:.9rem 2.75rem;
  font-size:.6875rem;
  font-weight:500;
  letter-spacing:.26em;
  text-transform:uppercase;
  color:var(--steel);
}
.about-meta li{ position:relative; }
.about-meta li + li::before{
  content:"";
  position:absolute;
  left:-1.375rem; top:50%;
  width:1px; height:1em;
  transform:translateY(-50%);
  background:var(--line);
}

/* ---- the ledger: shared by "On site" ---- */
.method{
  background:var(--paper-2);
  border-top:1px solid var(--line-soft);
  padding-block:clamp(6rem, 13vh, 10rem);
}
.ledger{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
  position:relative;
  z-index:1;
}
.ledger-head{
  display:flex;
  justify-content:space-between;
  align-items:flex-end;
  gap:2.5rem;
  margin-bottom:clamp(2.5rem, 6vh, 4rem);
}
.ledger-head h2{
  font-size:clamp(2.1rem, 4.8vw, 3.8rem);
  font-weight:200;
  letter-spacing:-.02em;
  line-height:1.05;
  margin-top:1.4rem;
  text-wrap:balance;
}
.ledger-head > p{
  max-width:22rem;
  color:var(--ink-60);
  font-size:.9375rem;
  padding-bottom:.5rem;
}
.ledger-list{ border-top:1px solid var(--line); }
.ledger-item{
  display:grid;
  grid-template-columns:4rem minmax(0, 13rem) minmax(0, 1fr);
  gap:clamp(1.25rem, 3vw, 3rem);
  padding-block:clamp(1.9rem, 4.2vh, 2.7rem);
  border-bottom:1px solid var(--line);
  align-items:baseline;
  transition:color .3s ease;
}
.ledger-item:hover{ padding-left:.85rem; }
.ledger-num{
  font-style:normal;
  font-size:clamp(1.6rem, 2.4vw, 2.1rem);
  font-weight:200;
  letter-spacing:-.02em;
  line-height:1;
  color:var(--steel);
}
.ledger-item h3{
  font-size:clamp(1.25rem, 1.9vw, 1.6rem);
  font-weight:400;
  letter-spacing:-.01em;
  line-height:1.2;
}
.ledger-item p{
  color:var(--ink-60);
  font-size:.9375rem;
  line-height:1.6;
  max-width:42em;
}
.ledger-item p em.word{ color:var(--navy); }
@media (max-width: 860px){
  .ledger-head{ flex-direction:column; align-items:flex-start; gap:1.25rem; }
  .ledger-item{ grid-template-columns:3rem minmax(0, 1fr); gap:.35rem 1.25rem; }
  .ledger-num{ grid-row:span 2; align-self:start; padding-top:.15rem; }
}

/* ---- the firm: our own teams / our own yard ---- */
.firm{ background:var(--paper); padding-block:clamp(6rem, 13vh, 10rem); }
.firm-grid{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
  display:grid;
  grid-template-columns:minmax(0, 1.05fr) minmax(0, 1fr);
  gap:clamp(3rem, 7vw, 6rem);
  align-items:center;
  position:relative;
  z-index:1;
}
.firm-copy h2{
  font-size:clamp(2.1rem, 4.8vw, 3.8rem);
  font-weight:200;
  letter-spacing:-.02em;
  line-height:1.06;
  margin-top:1.4rem;
  text-wrap:balance;
}
.firm-copy > p{ margin-top:1.6rem; color:var(--ink-60); max-width:34em; }
.firm-copy > p strong{ color:var(--navy); font-weight:500; }
.firm-facts{ list-style:none; margin-top:2.4rem; border-top:1px solid var(--line); }
.firm-facts li{
  border-bottom:1px solid var(--line);
  padding:1rem .25rem;
  font-size:.875rem;
  color:var(--ink-60);
  display:flex;
  align-items:center;
  gap:.9rem;
}
.firm-facts li::before{
  content:"";
  flex:0 0 auto;
  width:.4rem; height:.4rem;
  background:var(--steel);
  transform:rotate(45deg);
}
.firm-fig{
  position:relative;
  border:1px solid var(--line);
  background:var(--navy-deep);
}
.firm-fig .fig{ display:block; aspect-ratio:4 / 5; }
.firm-fig .fig img{ filter:saturate(.84) contrast(1.05) brightness(.98); }
.firm-fig figcaption{
  position:absolute;
  left:0; right:0; bottom:0;
  z-index:2;
  padding:1.1rem 1.15rem .95rem;
  display:flex;
  justify-content:space-between;
  align-items:baseline;
  gap:1rem;
  font-size:.625rem;
  font-weight:500;
  letter-spacing:.24em;
  text-transform:uppercase;
  color:var(--light-60);
  background:linear-gradient(to top, rgba(6,14,28,.86) 0%, rgba(6,14,28,0) 100%);
}
.firm-fig figcaption b{ color:var(--steel-pale); font-weight:500; white-space:nowrap; }
@media (max-width: 860px){
  .firm-grid{ grid-template-columns:minmax(0, 1fr); gap:2.5rem; }
  .firm-fig{ order:-1; }
  .firm-fig .fig{ aspect-ratio:16 / 11; }
}

/* ---- invitation: the plain close, navy, echoing the homepage quote ---- */
.invite{
  background:var(--navy);
  color:var(--paper);
  padding-block:clamp(6rem, 14vh, 10rem);
  position:relative;
  overflow:hidden;
}
.invite-inner{
  max-width:66rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
  position:relative;
  z-index:1;
}
.invite h2{
  font-size:clamp(2.2rem, 5vw, 4rem);
  font-weight:200;
  letter-spacing:-.02em;
  line-height:1.05;
  margin-top:1.4rem;
  max-width:15em;
  text-wrap:balance;
}
.invite > .invite-inner p{ margin-top:1.6rem; color:var(--light-60); max-width:34em; }
.invite-cta{
  margin-top:clamp(2rem, 4vh, 3rem);
  display:flex;
  flex-wrap:wrap;
  gap:1rem;
  align-items:center;
}
.invite .btn-primary{ background:var(--paper); color:var(--navy); border-color:var(--paper); }
.invite .btn-primary:hover{ background:transparent; color:var(--paper); }
.invite .btn-ghost{ color:var(--paper); border-color:var(--line-light); }
.invite .btn-ghost:hover{ border-color:var(--paper); }

/* ============================================================
   PHASE 1 - Direction D components
   (name-roll, method strip, projects, case study, contact,
    article, legal footer, a11y furniture)
   ============================================================ */

/* ---- skip link (visible on focus only) ------------------------ */
.skip-link{
  position:absolute;
  left:1rem; top:-4rem;
  z-index:200;
  background:var(--navy);
  color:var(--paper);
  padding:.75rem 1.25rem;
  font-size:.8125rem;
  letter-spacing:.08em;
  transition:top .25s ease;
}
.skip-link:focus-visible{ top:1rem; outline-offset:2px; }

.sectors.is-paused .sector-row{ animation-play-state:paused; }

/* ---- THE BUILDINGS THAT CALL BACK (home §3 name sentence) ----- */
.roll{
  background:var(--paper);
  border-bottom:1px solid var(--line);
  padding-block:clamp(5rem, 11vh, 8.5rem);
}
.roll-inner{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
  position:relative;
  z-index:1;
}
.roll h2{
  font-size:clamp(2rem, 4.6vw, 3.6rem);
  font-weight:200;
  letter-spacing:-.02em;
  line-height:1.05;
  text-wrap:balance;
}
/* the accreditation badges - their own band between the stats bar and the
   pain section. Both neighbours carry a hairline (stats-bar below, pain
   above), so this band needs none of its own. */
.creds{ background:var(--paper); }
.creds-inner{
  max-width:90rem;
  margin-inline:auto;
  padding:clamp(2rem, 5vh, 3rem) var(--gutter);
}
.roll-creds{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:1.75rem 4.5rem;
}
/* Badge over label rather than beside it. Andy cut the second sentence from
   each of these, so the side-by-side arrangement left a short line of text
   stranded next to a round mark with a lot of air after it. Stacked and
   centred, the mark and its label read as one unit and the two badges sit as
   a matched pair. */
.roll-cred{
  display:flex;
  flex-direction:column;
  align-items:center;
  text-align:center;
  gap:.7rem;
  font-size:.8125rem;
  line-height:1.5;
  color:var(--ink-60);
}
.roll-cred img{ width:3.4rem; height:3.4rem; object-fit:contain; flex:0 0 auto; }
.roll-cred b{ color:var(--navy); font-weight:500; }

/* ---- ON SITE, IN SHORT (home §7 method strip) ------------------
   The whole section was removed from index.html, so its rules
   (.method-strip, .method-strip-inner/-head, .method-cols, .method-col)
   are gone with it. */
/* ---- PROJECTS index -------------------------------------------
   The .proj-flagship band (the centenary crest on navy) was removed from
   the page along with the photo hero, so its rules are gone with it. The
   crest's own page is still at /projects/centenary-crest, still linked
   from /resources, /safety-flooring and /about. */
/* ---- THE WORK MOSAIC -------------------------------------------
   Three tiles at three sizes: a panorama across the top, then a
   two-thirds / one-third row. The slot each project gets follows the
   photograph we hold for it - the widest goes to the only 2048px
   original, the narrow portrait slot to the 600px one, so nothing is
   asked to fill more frame than it was shot at. Captions sit on the
   photograph over the shared .fig--scrim, square-cornered like
   everything else here. */
.proj-grid-wrap{
  background:var(--paper);
  padding-block:clamp(4.5rem, 10vh, 7.5rem);
}
/* on the dark page the ground goes to navy and the tile hairlines have to
   go with it - var(--line) is navy-on-paper and vanishes here */
.proj-grid-wrap.on-navy{ background:var(--navy-deep); }
.proj-grid-wrap.on-navy .proj-card{ border-color:var(--line-light-2); }
/* The mosaic is the first thing under the nav on /projects now, and the nav
   is fixed on .subpage - so it needs the same top clearance .res-head gives
   the other content pages, not the ordinary band padding (which is shorter
   than the 5.5rem bar at small viewports and would tuck under it).
   .is-bare has no header to space off, so it sits a little tighter. */
.proj-grid-wrap.is-first{
  padding-top:clamp(8rem, 16vh, 11rem);
}
.proj-grid-wrap.is-first.is-bare{
  padding-top:clamp(7rem, 13vh, 9rem);
}
.proj-grid{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
  display:grid;
  /* six columns is the quilt's resolution - tiles span 2, 3, 4 or 6 of them,
     and a short auto-row lets height be set independently of width. dense
     backfills any hole a row leaves rather than showing navy through it. */
  grid-template-columns:repeat(6, minmax(0,1fr));
  grid-auto-rows:clamp(2.6rem, 4.6vw, 4.6rem);
  grid-auto-flow:row dense;
  gap:clamp(.5rem, 1.2vw, 1rem);
  position:relative;
  z-index:1;
}

/* ---- the tile ---- */
.proj-card{
  position:relative;
  display:block;
  overflow:hidden;
  isolation:isolate;
  border:1px solid var(--line);
  background:var(--navy-deep);   /* the bed the photograph lands on */
  color:var(--paper);            /* everything in the tile is on navy now */
}
.proj-card .fig{ position:absolute; inset:0; display:block; }
.proj-card .fig img{ transition:filter .5s ease; }

/* Placeholder tiles - a <figure>, not a link, and no caption at all (see the
   comment block in projects/index.html). figure's default margin would break
   the grid, so it goes. */
.proj-card.is-ph{ margin:0; }

/* ---- tile size ----
   Each tile carries its own --c (columns) and --r (rows) inline, so the
   sizes are irregular by design rather than three repeating slots. Height
   comes from the row span against grid-auto-rows, NOT from aspect-ratio:
   with equal-height grid rows an aspect-ratio only holds if every tile in
   the row happens to agree, and stretch silently overrides the rest. Row
   spans have no such conflict, so tiles can be any shape next to each other.

   The spans were chosen per photograph, so each crop stays near the shape
   the thing was actually shot at - Twickenham at 4x8 lands on 1.31 against
   its native 1.34, Chessington at 4x7 on 1.33 against the same. */
.proj-card{
  grid-column:span var(--c, 2);
  grid-row:span var(--r, 6);
}

/* ---- the caption, on the photograph ----
   .fig--scrim carries the base gradient (the same one the heroes use),
   but it is tuned for a full-height frame: its last two stops land in
   the bottom 16%, which on a 520px tile is less than the caption block
   itself. So the caption zone gets a second pass of the same navy
   behind it, plus the tighter text-shadow the video hero uses. */
/* At rest a tile is only its photograph: the caption and the scrim behind
   it are both unpainted, and they come up together on hover or keyboard
   focus. Opacity only - the caption is absolutely positioned, so nothing
   in the grid moves and no tile changes height. The text is never
   display:none and never aria-hidden; it is in the accessibility tree and
   the page source at all times, whether or not it is drawn. */
.proj-card .proj-cap{
  position:absolute;
  inset:auto 0 0 0;
  z-index:2;
  padding:0 clamp(1rem, 2vw, 1.75rem) clamp(1rem, 2vw, 1.75rem);
  opacity:0;
  transition:opacity .5s cubic-bezier(.22,.61,.27,1);
}
.proj-card .fig--scrim::before{
  opacity:0;
  transition:opacity .5s cubic-bezier(.22,.61,.27,1);
}
.proj-card:hover .proj-cap,
.proj-card:focus-visible .proj-cap,
.proj-card:focus-within .proj-cap,
.proj-card:hover .fig--scrim::before,
.proj-card:focus-visible .fig--scrim::before,
.proj-card:focus-within .fig--scrim::before{ opacity:1; }
.proj-card .proj-cap::before{           /* the CWC hairline, kept */
  content:"";
  display:block;
  height:1px;
  background:var(--line-light);
  margin-bottom:clamp(.7rem, 1.4vw, 1rem);
}
/* Ground for the type. Measured against the worst case we actually have -
   the bright chequerboard under the Chessington caption - where a lighter
   wash left the micro-caps at 1.7:1. These stops hold every tile's caption
   over 4.5:1 on the brightest tenth of its own backdrop. */
.proj-card .proj-cap::after{
  content:"";
  position:absolute;
  inset:-5.5rem 0 0;
  z-index:-1;
  background:linear-gradient(0deg,
    rgba(8,20,38,.94) 0%, rgba(8,20,38,.88) 34%,
    rgba(8,20,38,.64) 68%, rgba(8,20,38,0) 100%);
  pointer-events:none;
}
.proj-card .cap{
  display:flex;
  flex-wrap:wrap;
  justify-content:space-between;
  align-items:baseline;
  gap:.3rem 1rem;
  font-size:.625rem;
  font-weight:500;
  letter-spacing:.24em;
  text-transform:uppercase;
  color:var(--steel-pale);
  text-shadow:0 1px 3px rgba(8,20,38,.8);
}
.proj-card .proj-line{
  display:flex;
  align-items:flex-end;
  justify-content:space-between;
  gap:1.25rem;
  margin-top:.55rem;
}
.proj-card h2{
  font-size:clamp(1.0625rem, 1.5vw, 1.5rem);
  font-weight:300;
  letter-spacing:-.01em;
  line-height:1.15;
  color:var(--paper);
  text-wrap:balance;
  text-shadow:0 1px 3px rgba(8,20,38,.85), 0 2px 14px rgba(8,20,38,.5);
}
.proj-go{
  flex:none;
  font-style:normal;
  font-size:1rem;
  line-height:1;
  padding-bottom:.15em;
  color:var(--paper);
  text-shadow:0 1px 3px rgba(8,20,38,.8);
  transition:transform .35s cubic-bezier(.22,.61,.27,1);
}
.proj-go::after{ content:"\2192"; }

/* the description - fades with the rest of the caption above it */
.proj-card .proj-note{
  display:block;
  margin-top:.55rem;
  max-width:46ch;
  font-size:.8125rem;
  line-height:1.5;
  color:rgba(242,244,246,.86);
  text-shadow:0 1px 3px rgba(8,20,38,.85);
}

/* ---- hover: a filter shift and the arrow, nothing else.
   No scale-on-hover; see docs/PAGE_AUDIT_AND_FRAMER_STUDY.md. ---- */
.proj-card:hover .fig img,
.proj-card:focus-visible .fig img{ filter:saturate(1.06) contrast(1.05) brightness(1.03); }
.proj-card:hover .proj-go,
.proj-card:focus-visible .proj-go{ transform:translateX(.3rem); }

/* No hover to reveal anything with. A phone would otherwise show captions
   that can never be summoned, so on touch they are simply always painted -
   the collage reads as a collage on a pointer device, and as a captioned
   grid where hovering is not a thing. */
@media (hover: none){
  .proj-card .proj-cap,
  .proj-card .fig--scrim::before{ opacity:1; }
}

/* The quilt only works while a row unit and a column are in proportion to
   each other. Both scale with the viewport, but the gap between tiles does
   not - it is a floor in px - so on a narrow screen the gaps come to
   dominate a short row span and the tile shapes distort. So below 820px the
   quilt hands back to one column and plain aspect ratios: landscape tiles
   at 4/3, and the ones whose photograph is portrait keep a portrait crop
   rather than being cut to a letterbox.

   4/3 is also the floor, not a step on the way to something shorter: on a
   phone there is no hover, so captions are permanently drawn, and they wrap
   to more lines the narrower it gets. The tile has to keep its height or
   the caption crowds the photograph out. */
@media (max-width: 820px){
  .proj-grid{
    grid-template-columns:minmax(0,1fr);
    grid-auto-rows:auto;
    gap:clamp(.75rem, 2vw, 1.25rem);
  }
  .proj-card{
    grid-column:1 / -1;
    grid-row:auto;
    aspect-ratio:4 / 3;
  }
  .proj-card.is-portrait{ aspect-ratio:4 / 5; }
}
/* The caption still appears on hover, just instantly - an opacity change
   with no duration is a state change, not motion. */
@media (prefers-reduced-motion: reduce){
  .proj-card .fig img,
  .proj-card .proj-cap,
  .proj-card .fig--scrim::before,
  .proj-go{ transition:none; }
}

/* ---- CASE STUDY ------------------------------------------------ */
.cs-head{
  padding:clamp(8rem, 16vh, 11rem) 0 clamp(2.5rem, 6vh, 4rem);
}
.cs-head .standfirst{
  margin-top:1.6rem;
  font-size:clamp(1.15rem, 2vw, 1.5rem);
  font-weight:300;
  line-height:1.5;
  color:var(--ink-60);
  max-width:30em;
  text-wrap:pretty;
}
.cs-grid{
  max-width:90rem;
  margin-inline:auto;
  padding:0 var(--gutter) clamp(5rem, 11vh, 8rem);
  display:grid;
  grid-template-columns:minmax(0, 20rem) minmax(0, 1fr);
  gap:clamp(2.5rem, 6vw, 6rem);
  align-items:start;
}
.cs-facts{
  position:sticky;
  top:6.5rem;
  border-top:1px solid var(--navy);
}
.cs-facts dl{ display:block; }
.cs-facts div{
  display:grid;
  grid-template-columns:minmax(0, 7.5rem) minmax(0, 1fr);
  gap:1rem;
  padding-block:.95rem;
  border-bottom:1px solid var(--line);
  font-size:.875rem;
}
.cs-facts dt{
  font-size:.625rem;
  font-weight:500;
  letter-spacing:.28em;
  text-transform:uppercase;
  color:var(--steel);
  padding-top:.2rem;
}
.cs-facts dd{ color:var(--ink-60); }
.cs-facts dd b{ color:var(--navy); font-weight:500; }
.cs-body{ min-width:0; }
.cs-chapter{ margin-bottom:clamp(2.75rem, 6vh, 4.5rem); }
.cs-chapter i{
  font-style:normal;
  display:block;
  font-size:clamp(1.5rem, 2.4vw, 2rem);
  font-weight:200;
  color:var(--steel);
  margin-bottom:.9rem;
}
.cs-chapter h2{
  font-size:clamp(1.5rem, 2.6vw, 2.1rem);
  font-weight:400;
  letter-spacing:-.01em;
  margin-bottom:.9rem;
  text-wrap:balance;
}
.cs-chapter p{
  color:var(--ink-60);
  max-width:38em;
}
.cs-chapter p + p{ margin-top:1.1rem; }
.cs-chapter p strong{ color:var(--navy); font-weight:500; }
/* wide texture interlude - forgiving subject, may run the column width */
.cs-strip{
  margin-block:clamp(2.5rem, 5vh, 4rem);
  border:1px solid var(--line);
}
.cs-strip .fig{ display:block; aspect-ratio:21 / 9; }
.cs-next{
  border-top:1px solid var(--line);
  background:var(--paper-2);
}
.cs-next-inner{
  max-width:90rem;
  margin-inline:auto;
  padding:clamp(3rem, 7vh, 5rem) var(--gutter);
  display:flex;
  justify-content:space-between;
  align-items:center;
  gap:2rem;
  flex-wrap:wrap;
}
.cs-next-inner p{ font-size:1.05rem; color:var(--ink-60); max-width:30em; }
@media (max-width: 1023px){
  .cs-grid{ grid-template-columns:minmax(0,1fr); }
  .cs-facts{ position:static; }
}

/* ---- CONTACT --------------------------------------------------- */
.routes-grid{
  max-width:90rem;
  margin-inline:auto;
  padding:clamp(3.5rem, 8vh, 6rem) var(--gutter) clamp(5rem, 11vh, 8rem);
  display:grid;
  grid-template-columns:minmax(0, 1.05fr) minmax(0, 1fr);
  gap:clamp(2.5rem, 6vw, 6rem);
  align-items:start;
}
.route{
  border-top:1px solid var(--line);
  padding:1.6rem .25rem 1.9rem;
}
.route > b{
  display:block;
  font-weight:500;
  font-size:.6875rem;
  letter-spacing:.3em;
  text-transform:uppercase;
  color:var(--steel);
  margin-bottom:.7rem;
}
.route h2{
  font-size:1.3rem;
  font-weight:400;
  letter-spacing:-.005em;
  margin-bottom:.5rem;
}
.route p{
  font-size:.9375rem;
  color:var(--ink-60);
  max-width:34em;
}
.route a{ border-bottom:1px solid var(--line); transition:color .3s ease, border-color .3s ease; }
.route a:hover{ color:var(--navy); border-color:var(--navy); }
.route .route-mail{
  display:inline-block;
  margin-top:.8rem;
  font-size:1.1rem;
  font-weight:400;
  color:var(--navy);
}
.route ul{
  list-style:none;
  margin-top:1.1rem;
  border-top:1px solid var(--line-soft);
}
.route li{
  padding:.55rem .1rem;
  border-bottom:1px solid var(--line-soft);
  font-size:.875rem;
  color:var(--ink-60);
  display:flex;
  gap:.8rem;
  align-items:baseline;
}
.route li::before{
  content:"";
  flex:0 0 auto;
  width:.35rem; height:.35rem;
  background:var(--steel);
  transform:rotate(45deg) translateY(-.1rem);
}
.route small{ display:block; margin-top:.8rem; font-size:.8125rem; font-style:italic; color:var(--ink-60); }
/* the light form (contact page) - quote-form fields recoloured for paper */
.form-light{ display:grid; gap:1.1rem; align-content:start; }
.form-light .field label{ color:var(--steel); }
.form-light .field input,
.form-light .field textarea,
.form-light .field select{
  font:inherit;
  font-size:1rem;
  color:var(--navy);
  background:transparent;
  border:0;
  border-bottom:1px solid var(--line);
  padding:.7rem .1rem;
  transition:border-color .3s ease;
  border-radius:0;
}
.form-light .field select{
  appearance:none; -webkit-appearance:none; cursor:pointer;
  padding-right:1.75rem;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%234A6B90' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;
  background-position:right .1rem center;
  background-size:.75rem;
}
/* light-form placeholders were inheriting the on-navy near-white; make them read on paper */
.form-light .field input::placeholder,
.form-light .field textarea::placeholder{ color:var(--ink-40); }
/* the <picture> wrapper must be transparent to the .fig sizing model */
.fig picture{ display:contents; }
.form-light .field input:focus,
.form-light .field textarea:focus,
.form-light .field select:focus{ outline:none; border-bottom-color:var(--navy); }
.form-light .quote-note{ color:var(--ink-60); }
.form-note{
  font-size:.8125rem;
  color:var(--ink-60);
  border:1px solid var(--line);
  padding:1rem 1.2rem;
  line-height:1.6;
}
.form-note b{ color:var(--navy); font-weight:500; }
.visit-block{
  margin-top:2.5rem;
  border-top:1px solid var(--line);
  padding-top:1.9rem;
  font-size:.9375rem;
  color:var(--ink-60);
}
.visit-block b{
  display:block;
  font-weight:500;
  font-size:.6875rem;
  letter-spacing:.3em;
  text-transform:uppercase;
  color:var(--steel);
  margin-bottom:.8rem;
}
/* honeypot - visually removed, present for bots */
.hp-field{ position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden; }
@media (max-width: 900px){
  .routes-grid{ grid-template-columns:minmax(0,1fr); }
}

/* ---- ARTICLE (guides) ------------------------------------------ */
.article{
  max-width:90rem;
  margin-inline:auto;
  padding:clamp(3rem, 7vh, 5rem) var(--gutter) clamp(5rem, 11vh, 8rem);
  display:grid;
  grid-template-columns:minmax(0, 44rem) minmax(0, 1fr);
  gap:clamp(2.5rem, 6vw, 6rem);
}
.article-body{ min-width:0; }
.article-body > p{ color:var(--ink-60); max-width:none; }
.article-body > p + p{ margin-top:1.1rem; }
.article-body > p strong, .article-body li strong{ color:var(--navy); font-weight:500; }
.article-body h2{
  font-size:clamp(1.5rem, 2.6vw, 2rem);
  font-weight:400;
  letter-spacing:-.01em;
  margin:clamp(2.5rem, 5vh, 3.5rem) 0 1rem;
  text-wrap:balance;
}
.article-body h2::before{
  content:"";
  display:block;
  width:2.75rem;
  height:1px;
  background:var(--steel);
  opacity:.55;
  margin-bottom:1.1rem;
}
.article-body ul, .article-body ol{
  margin:1.1rem 0 1.1rem 1.1rem;
  color:var(--ink-60);
  display:grid;
  gap:.45rem;
}
.article-aside{
  align-self:start;
  position:sticky;
  top:6.5rem;
  display:grid;
  gap:1.5rem;
}
.aside-box{
  border:1px solid var(--line);
  padding:1.4rem 1.5rem 1.5rem;
  font-size:.875rem;
  color:var(--ink-60);
  line-height:1.6;
}
.aside-box b{
  display:block;
  font-weight:500;
  font-size:.625rem;
  letter-spacing:.28em;
  text-transform:uppercase;
  color:var(--steel);
  margin-bottom:.7rem;
}
.aside-box a{ border-bottom:1px solid var(--line); }
.aside-box a:hover{ color:var(--navy); border-color:var(--navy); }
.article-meta{
  display:flex;
  gap:1.5rem;
  margin-top:1.6rem;
  font-size:.6875rem;
  font-weight:500;
  letter-spacing:.26em;
  text-transform:uppercase;
  color:var(--steel);
}
@media (max-width: 900px){
  .article{ grid-template-columns:minmax(0,1fr); }
  .article-aside{ position:static; }
}

/* ---- footer legal line ----------------------------------------- */
.closing-legal{
  margin-top:1.2rem;
  padding-top:1.2rem;
  border-top:1px solid var(--line-light-2);
  font-size:.6875rem;
  letter-spacing:.06em;
  line-height:1.8;
  color:rgba(242,244,246,.74);
}
.closing-legal a{
  color:inherit;
  border-bottom:1px solid var(--line-light);
  transition:color .3s ease;
}
.closing-legal a:hover{ color:var(--paper); }

/* ---- form success page ------------------------------------------ */
.thanks{
  min-height:70vh;
  display:grid;
  align-content:center;
  padding-block:clamp(8rem, 16vh, 11rem) clamp(5rem, 10vh, 8rem);
}

/* ============================================================================
   REFINEMENT PASS — July 2026
   See docs/DESIGN_REFINEMENT_PLAN.md. Appended so the origin of each change is
   traceable; fold into the main cascade once settled.
   ========================================================================= */

/* --- C1 · Hero legibility -------------------------------------------------
   The headline used to sit over the busiest part of the photograph and, at
   desktop, collided with the CWC mark. Two fixes, matching how the premium
   architecture references solve it: give the type its own ground, and stop
   showing the mark twice.                                                   */

/* Desktop: the mark stops floating mid-right, where it collided with the
   headline, and becomes a graphic plate anchored to the foot of the hero and
   cropped by the right edge — the structure Graft, Gridform, Terahaus, Langard
   and Lorünse all converge on (see docs/FRAMER_21ST_RESEARCH.md §2). The
   headline keeps the bottom-left, over the calmest part of the photograph. */
@media (min-width: 1025px){
  .hero{ position:relative; }
  .hero-grid{ grid-template-columns:minmax(0,1fr); }
  /* the type keeps the left; the mark keeps the right. They never overlap. */
  .hero-grid > div:first-child{ max-width:min(62%, 46rem); }
  .hero h1{
    max-width:none;
    font-size:clamp(2.9rem, 5.6vw, 5.6rem);
  }
  .hero-brand{
    position:absolute;
    right:var(--gutter);
    bottom:clamp(4rem, 9vh, 7rem);
    z-index:1;               /* over the photo, under the type */
    margin:0;
    padding:0;
    pointer-events:none;
  }
  .hero-brand img{
    height:clamp(12rem, 24vw, 24rem);
    width:auto;
    opacity:.92;
  }
  /* deepen the scrim under the headline only, not across the whole photograph */
  .hero-scrim{
    background:
      linear-gradient(100deg, rgba(8,20,38,.66) 0%, rgba(8,20,38,.36) 40%, rgba(8,20,38,.05) 70%),
      linear-gradient(186deg, rgba(8,20,38,.30) 0%, rgba(8,20,38,.04) 30%,
                              rgba(8,20,38,.36) 78%, rgba(8,20,38,.64) 100%);
  }
}

/* --- Setting-out marks ----------------------------------------------------
   Small registration crosses at the corners of a band. A drafting convention,
   and the way a floor is actually set out: datum, chalk line, square to the
   room. Two pseudo-elements, no images. Applied sparingly — bands, not cards. */
.set-out{ position:relative; }
.set-out::before,
.set-out::after{
  content:"";
  position:absolute;
  width:9px; height:9px;
  pointer-events:none;
  opacity:.34;
  background:
    linear-gradient(currentColor,currentColor) center/100% 1px no-repeat,
    linear-gradient(currentColor,currentColor) center/1px 100% no-repeat;
}
.set-out::before{ top:14px; left:14px; }
.set-out::after{ bottom:14px; right:14px; }
@media (max-width: 600px){
  .set-out::before, .set-out::after{ display:none; }
}

/* Mobile: the photograph becomes a bounded band and the words move onto solid
   ground beneath it. Nothing is set over image clutter, so contrast is fixed
   by layout rather than by piling on more scrim. */
@media (max-width: 1024px){
  .hero{ background:var(--paper); color:var(--navy); }
  .hero-stage{
    min-height:0;
    padding-top:5.5rem;
    padding-bottom:clamp(2.5rem, 6vh, 4rem);
    display:block;
    overflow:visible;
  }
  .hero-photo{
    position:relative;
    inset:auto;
    width:100vw;
    margin-left:calc(50% - 50vw);
    aspect-ratio:4/3;
    height:auto;
  }
  /* a light foot-scrim only, so the band reads as a photograph with weight */
  .hero-scrim{
    background:linear-gradient(180deg, rgba(8,20,38,.18) 0%, rgba(8,20,38,0) 32%,
                                       rgba(8,20,38,0) 68%, rgba(8,20,38,.22) 100%);
  }
  .hero-grid{
    margin-top:clamp(1.75rem, 5vw, 2.75rem);
    grid-template-columns:minmax(0,1fr);
    gap:1.5rem;
  }
  .hero h1{
    color:var(--navy);
    text-shadow:none;
    max-width:14em;
    font-size:clamp(2.6rem, 11vw, 4.4rem);
  }
  /* the band layout puts the type back on paper, so the light variants above
     have to come back off */
  .hero .kicker{ color:var(--steel); }
  .hero .res-lede{ color:var(--ink-60); }
  .nav:not(.is-solid):not(.is-open) .brand-logo-light{ display:none; }
  .nav:not(.is-solid):not(.is-open) .brand-logo-dark{ display:block; }
  .nav:not(.is-solid):not(.is-open) .nav-tel,
  .nav:not(.is-solid):not(.is-open) .nav-toggle{ color:var(--navy); }
  /* the mark is already in the nav; showing it twice was the collision */
  .hero-brand{ display:none; }
  /* buttons flip back to the light-ground treatment */
  .hero .btn-primary{ background:var(--navy); color:var(--paper); border-color:var(--navy); }
  .hero .btn-primary:hover{ background:transparent; color:var(--navy); }
  .hero .btn-ghost{ color:var(--navy); border-color:var(--line); }
}

/* --- C5 · The three dates, as a static band -------------------------------
   Replaces the pinned scroll scene. Three equal columns on desktop, stacked on
   mobile, revealing once. No pinning, no absolute positioning, nothing that can
   strand at opacity:0.                                                       */
.story-band{
  position:relative;
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
  padding-block:clamp(4rem, 10vh, 7.5rem);
}
.story-band-grid{
  display:grid;
  /* The band carried three dates and now carries four. auto-fit rather than a
     fixed count so the row fills at whatever number the history has: four
     across on a desktop, two on a tablet, one on a phone - never three with a
     lone card stranded underneath. */
  grid-template-columns:repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap:clamp(1.6rem, 3vw, 2.6rem);
  align-items:start;
}
.story-item{ display:flex; flex-direction:column; gap:1.5rem; }
/* The plate is sized to the column, not to the viewport. The base .story-fig
   .fig rule sets a 23vw width, which fitted while the band ran three across;
   at four it overflowed the track and the plates touched. Overriding width
   here keeps the figure inside whatever column the auto-fit grid hands it. */
.story-item .story-fig{ order:-1; width:100%; align-self:stretch; justify-self:stretch; }
.story-item .story-fig .fig{ display:block; width:100%; max-width:100%; aspect-ratio:4/3; overflow:hidden; margin-left:0; }
.story-item .story-fig img{ width:100%; height:100%; object-fit:cover; display:block; }
.story-item .story-year{ font-size:clamp(2.4rem, 4vw, 3.6rem); line-height:1; font-weight:200; }
.story-item .story-year sup{ font-size:.26em; letter-spacing:.24em; text-transform:uppercase;
  margin-left:.7em; vertical-align:super; opacity:.62; }
.story-item .story-copy h3{ margin-top:.9rem; font-size:1.2rem; font-weight:400; }
.story-item .story-copy p{ margin-top:.65rem; font-size:.95rem; line-height:1.6; opacity:.75; }
/* caption sits under the image, not over it, so long labels can't collide */
.story-item .story-fig figcaption{
  position:static;
  display:flex; justify-content:space-between; gap:1rem; flex-wrap:wrap;
  margin-top:.7rem; padding:0; background:none;
  font-size:.625rem; letter-spacing:.22em; text-transform:uppercase; opacity:.55;
}
.story-foot{
  display:flex; justify-content:space-between; gap:1.5rem; flex-wrap:wrap;
  margin-top:clamp(3rem, 6vh, 4.5rem); padding-top:1.4rem;
  border-top:1px solid var(--line-light);
  font-size:.6875rem; letter-spacing:.26em; text-transform:uppercase; opacity:.6;
}
@media (max-width: 900px){
  .story-band-grid{ grid-template-columns:minmax(0,1fr); gap:3rem; }
}

/* --- C12 · Sector marquee: stop clipping words mid-letter -----------------
   The track was masked hard at the container edge, so words truncated and the
   strip read as broken rather than continuous. A soft fade does the same job
   without amputating letterforms. */
.sector-strip{
  -webkit-mask-image:linear-gradient(to right, transparent 0, #000 5%, #000 95%, transparent 100%);
  mask-image:linear-gradient(to right, transparent 0, #000 5%, #000 95%, transparent 100%);
}

/* --- Hero vertical rhythm --------------------------------------------------
   The stage is min-height:100svh with justify-content:flex-end and no bottom
   padding, so on a tall viewport the whole block crowded the bottom edge and
   the CTA row could sit under the browser chrome. Give the content real
   breathing room beneath it and let the block sit a little higher.

   This has to sit on the stage, not on .hero: the section is the scroll track
   now, and padding there would band the shot at both ends of the pin. */
@media (min-width: 1025px){
  .hero-stage{
    padding-top:clamp(5rem, 11vh, 8rem);
    /* real room beneath the block, so the CTA row can't sit under the chrome */
    padding-bottom:clamp(4.5rem, 10vh, 7.5rem);
    justify-content:flex-end;
  }
  /* The mark goes back into the grid as its own column rather than being
     absolutely positioned: alignment with the type is then guaranteed by the
     grid instead of guessed with offsets. The collision it originally caused
     came from the text column being unconstrained, which is fixed below. */
  .hero-brand{ position:static; align-self:center; justify-self:end; padding:0; }
  .hero-grid{
    grid-template-columns:minmax(0,1fr) auto;
    align-items:center;
    gap:clamp(2rem, 5vw, 5rem);
  }
  /* Capped so the headline still breaks over two lines. Uncapped it sets on
     one line at desktop widths and runs straight into the mark, which now
     lands beside it rather than under it. */
  .hero-grid > div:first-child{ max-width:min(62%, 44rem); }
  /* Sized on WIDTH, not height, and capped to the column it sits in.
     Height-sizing (the old clamp(9rem,15vw,15rem)) sets the mark's width
     implicitly through its aspect ratio, so nothing stops that width exceeding
     the grid column - and because .hero-stage is overflow:hidden, the surplus
     is not scrolled to, it is silently cut off. The lockup is asymmetric: its
     right-hand edge is the vertical FLOORING strip, so a clip of even 40px
     takes the wordmark off and leaves the monogram looking broken rather than
     cropped. width + max-width:100% + height:auto keeps the ratio and makes
     overflow impossible at any viewport. 13.3rem matches the previous size. */
  .hero-brand{ min-width:0; }
  .hero-brand img{
    height:auto;
    width:clamp(7.5rem, 13.3vw, 13.3rem);
    max-width:100%;
  }
}
/* The home hero's headline runs longer than the projects one this rule was
   tuned for, so it needs more room to land on two lines instead of three.
   Scoped to [data-hero-video] rather than widening the shared rule above, so
   the projects hero (tuned for its own, shorter line) is untouched. */
@media (min-width: 1025px){
  .hero[data-hero-video] .hero-grid > div:first-child{ max-width:min(78%, 62rem); }
}

/* --- Work-grid captions ---------------------------------------------------
   Was: .625rem at .24em tracking, 1px from the left edge of the navy bar, with
   almost no vertical padding — cramped, and the longest label nearly filled the
   bar. Now a proper two-part caption: the venue leads, the material follows in
   a quieter tone, with room around both. */
.work-item figcaption{
  padding:.85rem 1.1rem .9rem;
  font-size:.6875rem;
  font-weight:500;
  letter-spacing:.11em;
  line-height:1.45;
  text-transform:uppercase;
  color:var(--paper);
  background:var(--navy);
  display:flex;
  flex-wrap:wrap;
  gap:.15rem .6rem;
  align-items:baseline;
}
/* the part after the middot reads as secondary */
.work-item figcaption .sep{ opacity:.4; }
.work-item figcaption .mat{ color:var(--steel-pale); letter-spacing:.14em; }
@media (max-width: 460px){
  .work-item figcaption{ padding:.8rem .9rem; font-size:.65rem; }
}

/* ============================================================================
   TIER 2 — structure fixes from docs/PAGE_AUDIT_AND_FRAMER_STUDY.md
   ========================================================================= */

/* --- Resources: real hierarchy instead of nine identical cards -------------
   Three resources exist; six were mailto prompts dressed as cards. The three
   get a feature + pair; the six become an honest list. */
.res-feature{
  display:grid;
  grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);
  gap:clamp(2rem,4vw,4rem);
  align-items:start;
  padding:clamp(1.9rem,3.2vw,2.9rem);
  border:1px solid var(--line);
  background:var(--paper);
  transition:border-color .3s ease, background-color .3s ease;
}
.res-feature:hover{ border-color:var(--navy); background:#fff; }
.res-feature-text h3{
  margin:.85rem 0 .8rem;
  font-size:clamp(1.45rem,2.6vw,2.1rem);
  font-weight:200;
  letter-spacing:-.02em;
  line-height:1.12;
}
.res-feature-text p{ color:var(--ink-60); max-width:44ch; line-height:1.6; }
.res-feature-text .r-action{ margin-top:1.3rem; display:inline-block; }
.res-feature-meta dl{
  display:grid;
  grid-template-columns:auto 1fr;
  gap:.55rem 1.2rem;
  padding-top:.35rem;
  border-top:1px solid var(--line);
}
.res-feature-meta dt{
  font-size:.625rem; letter-spacing:.2em; text-transform:uppercase; color:var(--ink-40);
  padding-top:.55rem;
}
.res-feature-meta dd{ font-size:.9rem; color:var(--navy); text-align:right; padding-top:.5rem; }

.res-pair{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:clamp(1rem,2vw,1.6rem);
  margin-top:clamp(1rem,2vw,1.6rem);
}

.res-request{
  border:1px solid var(--line);
  padding:clamp(1.6rem,3vw,2.6rem);
  background:var(--paper);
}
.res-request-lede{ color:var(--ink-60); max-width:52ch; }
.res-request-list{
  list-style:none;
  margin:clamp(1.4rem,2.5vw,2rem) 0 0;
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:0 clamp(2rem,4vw,3.5rem);
}
.res-request-list li{
  display:flex; flex-direction:column; gap:.25rem;
  padding:.95rem 0;
  border-top:1px solid var(--line-soft);
}
.res-request-list b{ font-weight:500; font-size:.98rem; color:var(--navy); }
.res-request-list span{ font-size:.83rem; color:var(--ink-60); line-height:1.5; }
.res-request-cta{
  display:flex; flex-wrap:wrap; gap:.9rem;
  margin-top:clamp(1.5rem,3vw,2.2rem);
  padding-top:clamp(1.3rem,2.5vw,1.8rem);
  border-top:1px solid var(--line);
}
@media (max-width: 900px){
  .res-feature{ grid-template-columns:minmax(0,1fr); gap:1.6rem; }
  .res-feature-meta dl{ border-top:1px solid var(--line); }
  .res-pair{ grid-template-columns:minmax(0,1fr); }
  .res-request-list{ grid-template-columns:minmax(0,1fr); }
}

/* --- Contact: setting-out drawing -----------------------------------------
   Fills the column that ran shorter than the routes list beside it, and shows
   the survey/drawing step without a sentence of copy. Pure SVG, no asset. */
.setout-plate{
  margin-top:clamp(2rem,4vw,3rem);
  padding:clamp(1.2rem,2.4vw,1.8rem);
  border:1px solid var(--line);
  color:var(--navy);
}
.setout-plate svg{
  display:block;
  width:100%;
  height:auto;
  opacity:.34;
}
.setout-plate figcaption{
  margin-top:1rem;
  padding-top:.9rem;
  border-top:1px solid var(--line-soft);
  font-size:.625rem;
  letter-spacing:.2em;
  text-transform:uppercase;
  color:var(--ink-40);
}
@media (max-width: 900px){
  .setout-plate{ display:none; } /* the mobile column is already full height */
}

/* --- Footer: ghost wordmark ------------------------------------------------
   The site already runs oversized ghost numerals; a ghost CWC bookends the
   page in the same family rather than introducing a new device. */
.closing{ position:relative; overflow:hidden; }
.closing-mark{
  position:absolute;
  left:50%;
  bottom:-.28em;
  transform:translateX(-50%);
  margin:0;
  font-size:clamp(7rem,19vw,17rem);
  font-weight:200;
  letter-spacing:-.03em;
  line-height:.8;
  color:var(--paper);
  opacity:.045;
  pointer-events:none;
  user-select:none;
  white-space:nowrap;
  z-index:0;
}
.closing-inner{ position:relative; z-index:1; }

/* ============================================================================
   SERVICES — the four material pages (/services and its four children)
   Deliberately thin. The spine of a service page is furniture that already
   exists: .res-head for the header, .method/.ledger for "where it goes",
   .firm-grid for the discipline, .faq, .invite to close. The hub reuses the
   home page's .mat-bands wholesale, so /services and the homepage showroom
   read as the same drawer of the same cabinet rather than two takes on it.
   Only three things here are genuinely new.
   ========================================================================= */

/* --- The material plate ----------------------------------------------------
   A wide photograph directly under the page header, edge to edge. This is the
   one place a service page shows the material at full width, so it takes the
   4K rendition; everything below it is copy. Bordered top and bottom rather
   than floated, so it reads as a plate set into the page (the way .cs-strip
   does inside the case study) rather than a hero — the hero treatment belongs
   to the home and projects pages, and reusing it here would flatten the
   difference between a landing page and a content page. */
.svc-plate{
  position:relative;
  border-block:1px solid var(--line);
  background:var(--navy-deep);   /* the bed the photograph lands on */
}
/* Sized by height, not by aspect-ratio. A 21:9 ratio alone grew the band to
   ~800px on a wide screen and swallowed the page; adding max-height to an
   aspect-ratio does NOT fix that, because the ratio then shrinks the WIDTH to
   keep itself true and the plate stops short of the page edge. Giving the box
   a full width and an explicit clamped height lets object-fit:cover do the
   cropping, which is what it is for. */
.svc-plate .fig{
  display:block;
  width:100%;
  height:clamp(15rem, 32vw, 28rem);
}
/* The caption carries the material and its setting. It sits on the
   photograph over the shared scrim, same micro-caps as .work-item and
   .proj-card use, so a caption reads the same wherever it appears. */
.svc-plate figcaption{
  position:absolute;
  left:0; right:0; bottom:0;
  z-index:2;
  padding:clamp(1rem, 2.4vw, 1.9rem) var(--gutter);
  display:flex;
  flex-wrap:wrap;
  justify-content:space-between;
  align-items:baseline;
  gap:.3rem 1.5rem;
  font-size:.625rem;
  font-weight:500;
  letter-spacing:.24em;
  text-transform:uppercase;
  color:var(--light-60);
  /* The gradient is only as tall as the caption box, so on a narrow screen -
     where the caption wraps to two lines over whatever the photograph happens
     to be doing - it has to carry the type on its own. Deeper stops and a
     padded-out top edge, rather than relying on the shot being dark there. */
  background:linear-gradient(to top,
    rgba(6,14,28,.92) 0%, rgba(6,14,28,.78) 45%, rgba(6,14,28,0) 100%);
  padding-top:clamp(2.5rem, 6vw, 4rem);
  text-shadow:0 1px 3px rgba(8,20,38,.9);
}
.svc-plate figcaption b{ color:var(--steel-pale); font-weight:500; }
/* Portrait-ish phones cannot carry a 21:9 band — at 390px it is 167px tall and
   the subject disappears. Squarer crop, and the caption stops floating over a
   photograph that no longer has room underneath the subject for it. */
@media (max-width: 820px){
  .svc-plate .fig{ height:clamp(13rem, 52vw, 20rem); }
}

/* --- The specification sheet -----------------------------------------------
   What a specifier actually needs on the page: formats, the brands we hold
   accounts with, the standards the installation is written to. A description
   list, not a table — the pairs are label/value, and a real <dl> keeps that
   relationship for a screen reader without any ARIA. Two columns of pairs on
   desktop, one on a phone. Visually it is the .cs-facts panel from the case
   study, unpinned and set on the cooler ground. */
.svc-spec{
  background:var(--paper-2);
  border-top:1px solid var(--line-soft);
  padding-block:clamp(4.5rem, 10vh, 7.5rem);
}
.svc-spec-inner{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
  position:relative;
  z-index:1;
}
.svc-spec-head{
  display:flex;
  justify-content:space-between;
  align-items:flex-end;
  gap:2.5rem;
  margin-bottom:clamp(2.5rem, 6vh, 3.5rem);
}
.svc-spec-head h2{
  font-size:clamp(2.1rem, 4.8vw, 3.8rem);
  font-weight:200;
  letter-spacing:-.02em;
  line-height:1.05;
  margin-top:1.4rem;
  text-wrap:balance;
}
.svc-spec-head > p{
  max-width:22rem;
  color:var(--ink-60);
  font-size:.9375rem;
  padding-bottom:.5rem;
}
.svc-spec-grid{
  display:grid;
  grid-template-columns:repeat(2, minmax(0,1fr));
  gap:0 clamp(2.5rem, 6vw, 5rem);
}
.svc-spec-grid > div{
  display:grid;
  grid-template-columns:minmax(0, 9rem) minmax(0, 1fr);
  gap:1rem clamp(1rem, 2.5vw, 2rem);
  padding-block:1.15rem;
  border-top:1px solid var(--line);
  font-size:.9375rem;
}
/* the last pair in each column closes the list off */
.svc-spec-grid > div:nth-last-child(-n+2){ border-bottom:1px solid var(--line); }
.svc-spec dt{
  font-size:.625rem;
  font-weight:500;
  letter-spacing:.26em;
  text-transform:uppercase;
  color:var(--steel);
  padding-top:.25rem;
}
.svc-spec dd{ color:var(--ink-60); line-height:1.6; }
.svc-spec dd b{ color:var(--navy); font-weight:500; }
@media (max-width: 860px){
  .svc-spec-head{ flex-direction:column; align-items:flex-start; gap:1.25rem; }
  .svc-spec-grid{ grid-template-columns:minmax(0,1fr); }
  /* with one column the nth-last-child(-n+2) rule above would double-rule the
     second-from-last pair, so the closing hairline goes to the true last one */
  .svc-spec-grid > div:nth-last-child(2){ border-bottom:0; }
}

/* --- The other three materials ---------------------------------------------
   A family strip at the foot of every material page. The cards themselves are
   .res-card, unchanged — the resource centre already solved "a labelled card
   that is entirely a link", and a service page wanting the same thing should
   not invent a second one. This is only the row that holds them, plus the
   hairline bed the resource grid gets from its own wrapper. */
.svc-siblings{
  background:var(--paper);
  border-top:1px solid var(--line);
  padding-block:clamp(4rem, 9vh, 6.5rem);
}
.svc-siblings-inner{
  max-width:90rem;
  margin-inline:auto;
  padding-inline:var(--gutter);
}
.svc-siblings-inner > .kicker{ margin-bottom:1.8rem; }
.svc-sibling-row{
  display:grid;
  /* auto-fit rather than a fixed three: the row carries however many sibling
     materials have a page of their own, and still fills the width at one or
     two rather than leaving dead columns. */
  grid-template-columns:repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  gap:1px;
  background:var(--line);
  border:1px solid var(--line);
}
@media (max-width: 820px){ .svc-sibling-row{ grid-template-columns:minmax(0,1fr); } }

/* --- Manufacturer wall (/services) -----------------------------------------
   The marks of the manufacturers CWC holds accounts with. Sources vary wildly
   - some are supplied white-for-dark-headers, some two-tone, some a monogram
   on a plate - so every one is flattened to a single ink before it goes in
   here. That is a deliberate treatment, not a shortcut: a row of competing
   brand colours would pull harder than anything else on the page, and this is
   a credential, not a sponsor board. Flex rather than a grid so the row stays
   even whatever number of marks it holds. */
.brand-wall{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  align-items:center;
  gap:clamp(1.75rem, 4vw, 4rem) clamp(2rem, 6vw, 5.5rem);
  padding:clamp(2rem, 4vw, 3rem) clamp(1rem, 3vw, 2.5rem);
  border:1px solid var(--line);
}
.brand-wall img{
  display:block;
  height:clamp(1.5rem, 2.6vw, 2.1rem);
  width:auto;
  max-width:11rem;
  opacity:.55;
  transition:opacity .4s ease;
}
.brand-wall a:hover img,
.brand-wall a:focus-visible img{ opacity:1; }
@media (prefers-reduced-motion: reduce){ .brand-wall img{ transition:none; } }
