﻿/* ===========================================================
   AcuraGold — "Built to the millimetre"
   Brand system from acuragold.com: black + gold, Bricolage Grotesque
   over Outfit, with setting-out instrument structure.
   =========================================================== */

/* =============================================================
   LIGHT THEME — warm off-white ground, brass accent.

   THE ONE THING TO UNDERSTAND BEFORE EDITING COLOUR HERE:
   the brand gold #C9A227 measures 7.9:1 on black and only 2.4:1 on
   #FFFDF9. It cannot be text on this ground. So gold is split in two —
   `--tint` is a FILL colour (gradients, buttons, rules, washes) and
   `--tint-ink` is the TEXT colour (6.2:1). Never set `color:` to
   `--tint`; the audit in README explains how to check.

   `--tint-lt` / `--tint-pale` stay light because they are still used on
   photographs, behind dark scrims — the name plate on a project card,
   the plate caption, the hero spec badge. Those are inverse contexts
   and are correct as they are.
   ============================================================= */
:root{
  /* --- surface: page is the brief's #FFFDF9; cards sit ABOVE it in white,
         tinted bands sit BELOW it in warmer cream --- */
  --page:#FFFDF9;
  --pitch:#F6F1E6;                 /* most tinted band (was deepest dark) */
  --void:#FFFDF9;                  /* page ground                         */
  --panel:#FFFFFF;                 /* raised card — lighter than the page */
  --panel-2:#FFFBF3;               /* card, hovered                       */

  /* --- ink: warm near-black, never pure #000 on cream --- */
  --ink:#17150F;                   /* headings          18.0:1 on page    */
  --ink-2:#322E26;                 /* body copy         13.3:1            */
  --ink-3:#4A4438;                 /* micro-labels       9.5:1            */
  /* historical names, re-pointed. `--ivory` means "heading ink" now. */
  --ivory:var(--ink);
  --concrete:var(--ink-2);
  --concrete-dim:var(--ink-3);

  /* rules: gold at low alpha vanishes on cream, so these are based on the
     DEEP gold and carry more alpha than the dark theme's did */
  --rule:rgba(122,92,24,.18);
  --rule-strong:rgba(122,92,24,.36);

  /* --- gold --- */
  --tint:#C9A227;                  /* FILL ONLY  — 2.4:1, never text      */
  --tint-ink:#6E5210;              /* gold text  — 7.2:1                  */
  --tint-deep:#5E4610;             /* strongest gold text — 8.4:1         */
  --tint-mid:#A8811A;              /* shimmer peak — 3.6:1, DISPLAY ONLY   */
  --tint-mid-aa:#916E15;           /* shimmer peak — 4.7:1, small text ok  */
  --tint-lt:#F2DFA0;               /* light gold — ON PHOTOGRAPHS ONLY    */
  --tint-pale:#FFF6DA;             /* gold glow  — fills and highlights   */
  --tint-dk:#7A5C18;
  --deep:#7A5C18;
  --nebula:#7A5C18;

  /* --- elevation. Black at high alpha goes muddy grey on cream, so every
         shadow here is a warm brown at low alpha. --- */
  --sh-contact:0 1px 2px rgba(48,38,14,.05);
  --sh-near:0 2px 8px -2px rgba(48,38,14,.09);
  --sh-mid:0 18px 44px -22px rgba(48,38,14,.20);
  --sh-far:0 34px 70px -32px rgba(48,38,14,.26);
  --glow-gold:0 0 44px -18px rgba(201,162,39,.5);

  /* INVERSE CONTEXT — text sitting on a dark scrim over a photograph.
     Used by .spec, .proj-name and .tp-cap. */
  --ink-inv:#FFFDF9;

  /* --- the contrast colour ---
     Espresso bronze — the brand gold driven down in value, so the identity
     stays one hue: gold from #33270C through #7A5C18 to #C9A227.
     The practical win: on cream the brand gold is 2.4:1 and unusable as text,
     but on this bronze it is 6.0:1 — the REAL #C9A227 comes back as text
     everywhere the band appears.
     Rejected #7A5C18 (the stat unit colour) as the band: gold on it is
     2.57:1, which erases the very thing the band is for. It has to go
     this dark to carry gold text. */
  --anchor:#33270C;                /* espresso bronze — the deep band      */
  --anchor-deep:#241B08;           /* deepest step, inside .on-dark        */
  --anchor-panel:#453615;          /* raised panel on the band             */
  --anchor-panel-2:#52401A;

  --display:"Bricolage Grotesque","Outfit",system-ui,sans-serif;
  --body:"Outfit",system-ui,-apple-system,"Segoe UI",sans-serif;
  --mono:"Outfit",system-ui,sans-serif;   /* tracked-out caps, per brand */

  --card-r:14px;                   /* cards — considered, not a default 3px */
  --chip-r:6px;                    /* chips, fields, small controls        */

  --maxw:1360px;
  --gut:clamp(20px,4.5vw,68px);
  --rail:74px;                       /* width of the datum rule */
  --ease:cubic-bezier(.16,1,.3,1);   /* expo-out — the "buttery" curve */
  --ease-io:cubic-bezier(.76,0,.24,1);
}

/* =============================================================
   INVERSE SCOPE — the green anchor at the foot of every page.

   This re-points the SAME tokens rather than restyling components, so every
   card, list, rule and label inside it inverts on its own. If you add a
   component and it looks right on cream, it will look right in here too.

   Note --tint-ink: on cream it has to be the deep brass, but on green the
   real brand gold clears AA (5.1:1), so it comes back at full brightness.
   ============================================================= */
.on-dark{
  --page:var(--anchor);
  --void:var(--anchor);
  --pitch:var(--anchor-deep);
  --panel:var(--anchor-panel);
  --panel-2:var(--anchor-panel-2);

  --ink:#FFFDF9;                   /* 14.4:1 on the bronze band */
  --ink-2:#DCD6C7;                 /* 10.1:1                    */
  --ink-3:#C0BAAB;                 /*  7.6:1                    */
  --ivory:var(--ink);
  --concrete:var(--ink-2);
  --concrete-dim:var(--ink-3);

  --tint-ink:var(--tint);          /* the real brand gold, 6.0:1 here */
  --tint-deep:var(--tint-lt);      /* hover goes brighter on dark, not deeper */
  --tint-mid-aa:var(--tint-lt);

  --rule:rgba(242,223,160,.16);
  --rule-strong:rgba(242,223,160,.34);

  --sh-contact:0 1px 2px rgba(0,0,0,.2);
  --sh-near:0 2px 8px -2px rgba(0,0,0,.3);
  --sh-mid:0 18px 44px -22px rgba(0,0,0,.5);
  --sh-far:0 34px 70px -32px rgba(0,0,0,.6);

  background:var(--anchor);
  color:var(--ink-2);
}

*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{
  scroll-behavior:smooth;-webkit-text-size-adjust:100%;color-scheme:light;background:var(--page);
  /* The header is fixed, so without this EVERY in-page anchor — the Home
     submenu, the hero CTA, the footer links — lands with the section's first
     line hidden behind it. 70px is the stuck header height plus breathing room. */
  scroll-padding-top:calc(70px + 1.6rem);
}
body{
  font-family:var(--body);
  background:var(--void);
  color:var(--concrete);
  font-size:1.0625rem;
  line-height:1.68;
  -webkit-font-smoothing:antialiased;
  text-rendering:optimizeLegibility;
  overflow-x:clip;
}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
::selection{background:var(--tint-pale);color:var(--ink)}
:focus-visible{outline:2px solid var(--tint-ink);outline-offset:3px;border-radius:2px}

/* ---------- ambient grain ---------- */
.grain{
  position:fixed;inset:-120%;z-index:9;pointer-events:none;opacity:.022;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='4'/%3E%3C/filter%3E%3Crect width='260' height='260' filter='url(%23n)'/%3E%3C/svg%3E");
  animation:grainshift 7s steps(6) infinite;
}
@keyframes grainshift{
  0%{transform:translate(0,0)}     20%{transform:translate(-3%,2%)}
  40%{transform:translate(2%,-3%)} 60%{transform:translate(-2%,-2%)}
  80%{transform:translate(3%,1%)}  100%{transform:translate(0,0)}
}

/* ---------- layout ---------- */
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 var(--gut)}
.page{padding-left:var(--rail)}
/* below 900 the datum rule is hidden, so the rail collapses everywhere at once */
@media(max-width:900px){:root{--rail:0px}}

section{position:relative}
.band{padding:clamp(54px,6.4vw,104px) 0}
.band--tight{padding:clamp(40px,4.4vw,72px) 0}

/* ---------- type ---------- */
.mono{
  font-family:var(--mono);font-size:.76rem;font-weight:600;
  letter-spacing:.16em;text-transform:uppercase;color:var(--concrete-dim);
}
.mono--tint{color:var(--tint-ink)}

.display{
  font-family:var(--display);
  font-weight:800;
  font-variation-settings:'opsz' 96,'wdth' 100;
  line-height:.9;
  letter-spacing:-.028em;
  color:var(--ivory);
  text-wrap:balance;
}
/* sized so the longest word ("millimetre.") stays under its grid track —
   above ~7.8vw its min-content width starts squeezing the hero figure */
h1.display{font-size:clamp(2.7rem,7.6vw,6.6rem);line-height:.88;letter-spacing:-.038em}
h2.display{font-size:clamp(2.2rem,5.2vw,4.6rem)}
h3{font-family:var(--display);font-weight:700;font-variation-settings:'opsz' 24,'wdth' 100;color:var(--ivory);letter-spacing:-.015em;line-height:1.1}

.gild{
  /* the brand's shimmering gold, matching acuragold.com's wordmark */
  background:linear-gradient(100deg,var(--tint-deep),var(--tint-ink) 20%,var(--tint-mid) 48%,var(--tint-ink) 74%,var(--tint-deep));
  background-size:220% 100%;
  -webkit-background-clip:text;background-clip:text;color:transparent;
  animation:gild 7s var(--ease-io) infinite;
}
@keyframes gild{0%,100%{background-position:120% 0}50%{background-position:-40% 0}}

.lede{font-size:clamp(1.02rem,1.45vw,1.2rem);color:var(--concrete);max-width:56ch}
.dim{color:var(--concrete-dim)}

/* ---------- inline links in body copy ----------
   No underline at rest — a client decision, for a cleaner reading line.

   That puts a constraint on everything else here. WCAG 1.4.1 only allows
   colour to be the sole marker of a link if it clears 3:1 against the text
   around it, and this brass manages 1.85:1 — any gold dark enough to pass
   would be too muddy to read on cream. So the resting cue is deliberately NOT
   colour alone: the weight jump (600 against the paragraph's 400) is a
   non-colour difference, which is what keeps this compliant. Do not drop the
   font-weight back to 400 to "tidy" it — that is the whole cue.

   The underline returns on hover and on keyboard focus, so the affordance is
   unambiguous the moment anyone reaches for it.
   --tint-ink is re-pointed inside .on-dark, so this works in both scopes.

   Opt-in via .ilink rather than matching bare anchors. An earlier version used
   a:not([class]), which looks tidier but breaks the moment any script touches
   the element — classList.add() then remove() leaves class="" behind, the
   attribute still exists, and the link silently reverts to body text. */
main p a.ilink{
  color:var(--tint-ink);
  font-weight:600;
  text-decoration:none;
  transition:color .3s var(--ease);
}
/* thickness/offset live here only. Declaring them next to `text-decoration:none`
   above makes the shorthand and the longhand fight, and the rule serialises to
   the nonsense `text-decoration:1px`. */
main p a.ilink:hover,
main p a.ilink:focus-visible{
  color:var(--tint-deep);
  text-decoration:underline currentColor 1px;
  text-underline-offset:.19em;
}
.on-dark main p a.ilink:hover,
main .on-dark p a.ilink:hover{color:var(--tint-lt)}

/* ---------- section header (plumb line device) ---------- */
.shead{display:grid;grid-template-columns:auto minmax(0,1fr);gap:clamp(1.2rem,3vw,2.6rem);margin-bottom:clamp(2rem,3.6vw,3.2rem)}
.plumb{position:relative;width:1px;background:var(--rule-strong);transform:scaleY(0);transform-origin:top;transition:transform 1.1s var(--ease)}
.plumb::after{content:"";position:absolute;left:50%;bottom:-1px;width:7px;height:7px;translate:-50% 0;rotate:45deg;background:var(--tint-ink);box-shadow:0 0 10px rgba(201,162,39,.7)}
.in .plumb{transform:scaleY(1)}
.shead-tx{max-width:64ch}
.shead .mono{display:block;margin-bottom:1.1rem}
.shead p{margin-top:1.2rem}

/* ---------- the datum rule (signature) ---------- */
.datum{
  position:fixed;left:0;top:0;bottom:0;width:var(--rail);z-index:40;
  border-right:1px solid rgba(242,223,160,.16);
  background:linear-gradient(180deg,rgba(51,39,12,.97),rgba(36,27,8,.95));
  backdrop-filter:blur(6px);
  display:grid;grid-template-rows:1fr;
  padding:26px 0;                    /* the scale used to be inset by its labels */
  pointer-events:none;
}
.datum-track{position:relative;margin:0 auto;width:100%}
/* tick marks: minor every 8px, major every 40px */
.datum-track::before{
  content:"";position:absolute;right:0;top:0;bottom:0;width:11px;
  background:
    repeating-linear-gradient(180deg,rgba(242,223,160,.3) 0 1px,transparent 1px 8px);
}
.datum-track::after{
  content:"";position:absolute;right:0;top:0;bottom:0;width:20px;
  background:repeating-linear-gradient(180deg,rgba(242,223,160,.42) 0 1px,transparent 1px 40px);
}
.datum-fill{
  position:absolute;right:0;top:0;width:2px;height:0;
  background:linear-gradient(180deg,var(--tint-lt),var(--tint));
  box-shadow:0 0 14px rgba(201,162,39,.7);
}
/* The index. A zero-height anchor that JS translates to the exact fill end;
   the tick and the readout each centre themselves on it.

   It used to be a flex column carrying `translate:0 -50%`, which centred the
   whole tick+label block on the position — so half the label sat above the
   rail at 0% and below it at 100%, and the vertical text was clipped. Now the
   tick alone marks the position and the readout is nudged back into the rail
   by `datum-read` in acura.js when it would run off either end. */
.datum-head{position:absolute;right:0;top:0;width:var(--rail);height:0}
.datum-head i{
  position:absolute;top:0;right:0;translate:0 -50%;
  display:block;width:26px;height:1px;background:var(--tint-lt);box-shadow:0 0 10px rgba(201,162,39,.85);
}
.datum-read{
  position:absolute;top:0;right:30px;translate:0 -50%;
  font-family:var(--mono);font-size:.66rem;font-weight:600;letter-spacing:.08em;color:var(--tint-lt);
  writing-mode:vertical-rl;text-orientation:mixed;white-space:nowrap;
}
@media(max-width:900px){.datum{display:none}}

/* ---------- header ---------- */
.head{
  position:fixed;top:0;left:var(--rail);right:0;z-index:50;
  transition:background .5s var(--ease),border-color .5s,backdrop-filter .5s;
  border-bottom:1px solid transparent;
}
.head.stuck{background:rgba(255,253,249,.86);backdrop-filter:blur(18px) saturate(120%);border-bottom-color:var(--rule);box-shadow:0 10px 30px -22px rgba(48,38,14,.3)}
.head-in{position:relative;display:flex;align-items:center;gap:2rem;height:88px;transition:height .5s var(--ease)}
.head.stuck .head-in{height:70px}
@media(max-width:900px){.head{left:0}}

.logo{display:flex;align-items:center;gap:.72rem;flex:none}
.logo svg{width:42px;height:42px;flex:none}
.logo-tx{display:flex;flex-direction:column;line-height:1}
/* wordmark — the shimmering gold lockup from acuragold.com */
.logo-tx b{
  font-family:var(--display);font-weight:700;font-variation-settings:'opsz' 24,'wdth' 100;
  font-size:1.02rem;letter-spacing:.15em;text-transform:uppercase;line-height:1;
  /* 16px text -> 4.5:1 threshold, so this ramp peaks at --tint-mid-aa, not
     the display-only --tint-mid used by .gild */
  background:linear-gradient(100deg,var(--tint-deep),var(--tint-ink) 24%,var(--tint-mid-aa) 50%,var(--tint-ink) 74%,var(--tint-deep));
  background-size:220% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;
  animation:gild 7s linear infinite;
}
.logo-tx span{font-family:var(--body);font-size:.67rem;font-weight:600;letter-spacing:.2em;text-transform:uppercase;color:var(--concrete-dim);margin-top:.42rem}
.mobile-menu .logo-tx span,.foot .logo-tx span{color:var(--concrete-dim)}

/* --navpad is the item's side padding AND the inset of the underline beneath
   it. One value, because the two have to agree — set separately, a change to
   the padding leaves the rule overhanging the word it belongs to. It is a
   variable so the tight-desktop query below has one thing to change. */
/* Nav is absolutely centred in the header, so it sits mid-bar regardless of
   how wide the logo (left) or the actions (right) are. Below 980px it is
   display:none and the burger takes over, so this positioning is inert there. */
.nav{--navpad:.8rem;display:flex;gap:.35rem;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%)}
.nav a{
  position:relative;font-family:var(--mono);font-size:.74rem;font-weight:500;letter-spacing:.12em;text-transform:uppercase;
  color:var(--concrete);padding:.7rem var(--navpad);transition:color .4s var(--ease);
  /* "About us" is two words and will break across two lines the moment the
     padding tightens. A nav label wrapping is never the right answer — let the
     item stay wide and let the padding give way instead. */
  white-space:nowrap;
}
.nav a::after{
  content:"";position:absolute;left:var(--navpad);right:var(--navpad);bottom:.5rem;height:1px;
  background:var(--tint);transform:scaleX(0);transform-origin:right;transition:transform .55s var(--ease);
}
.nav a:hover{color:var(--ivory)}
.nav a:hover::after{transform:scaleX(1);transform-origin:left}
.nav a.on{color:var(--ivory)}
.nav a.on::after{transform:scaleX(1)}

/* ---------- Home submenu (click to open) ----------
   The homepage sections hang off Home instead of sitting at top level.
   Closed state toggles VISIBILITY, not just opacity — an opacity-0 panel
   still takes pointer events and would sit invisibly over the hero, which
   is exactly the bug the mobile drawer had. */
.nav-item{position:relative;display:flex;align-items:center}
/* the link half — navigates on click, exactly like the other nav items */
.nav-top{
  position:relative;display:inline-flex;align-items:center;
  font-family:var(--mono);font-size:.74rem;font-weight:500;letter-spacing:.12em;text-transform:uppercase;
  color:var(--concrete);padding:.7rem .3rem .7rem var(--navpad);
  transition:color .4s var(--ease);white-space:nowrap;
}
.nav-top::after{
  content:"";position:absolute;left:var(--navpad);right:.3rem;bottom:.5rem;height:1px;
  background:var(--tint);transform:scaleX(0);transform-origin:right;transition:transform .55s var(--ease);
}
/* the caret half — discloses the panel, and is the ONLY way in on touch */
.nav-caret{
  display:inline-flex;align-items:center;padding:.7rem var(--navpad) .7rem .25rem;cursor:pointer;
  color:var(--tint-ink);
}
.nav-caret svg{width:11px;height:11px;flex:none;transition:rotate .5s var(--ease)}
/* hovering either half lights the whole item, so it still reads as one thing */
.nav-item:hover .nav-top,.nav-item:focus-within .nav-top,.nav-top.on{color:var(--ivory)}
.nav-item:hover .nav-top::after,.nav-item:focus-within .nav-top::after,.nav-top.on::after{transform:scaleX(1);transform-origin:left}
.nav-item:hover .nav-caret svg,.nav-item.open .nav-caret svg,.nav-caret[aria-expanded="true"] svg{rotate:180deg}

/* The panel sits 1.75rem below the item so it clears the header edge, which
   leaves a gap the pointer would cross on its way down — and hover would drop.
   This bridges it. pointer-events only while hovering, so a dead 28px strip is
   never sitting over the hero waiting to swallow a click. */
.nav-item::after{
  content:"";position:absolute;left:0;right:0;top:100%;height:1.9rem;
  pointer-events:none;
}
.nav-item:hover::after{pointer-events:auto}

.nav-panel{
  /* clears the header's own bottom padding, so the panel hangs below the bar
     rather than notching the hairline .head.stuck draws across it */
  position:absolute;top:calc(100% + 1.75rem);left:0;z-index:60;min-width:12.5rem;
  display:flex;flex-direction:column;padding:.5rem;
  background:linear-gradient(180deg,#FFFFFF 0%,#FFFDF8 62%,#FFF9EE 100%);
  border:1px solid rgba(122,92,24,.2);border-radius:var(--card-r);
  box-shadow:var(--sh-contact),var(--sh-near),var(--sh-far);
  visibility:hidden;opacity:0;pointer-events:none;translate:0 -8px;
  transition:opacity .35s var(--ease),translate .45s var(--ease),visibility .35s;
}
/* opens on hover, on keyboard focus anywhere inside, or from the caret button */
.nav-item:hover .nav-panel,
.nav-item:focus-within .nav-panel,
.nav-item.open .nav-panel{visibility:visible;opacity:1;pointer-events:auto;translate:0 0}
/* No hover on touch, so the caret is the only opener there — and :hover must
   not latch on after a tap. */
@media(hover:none){
  .nav-item:hover .nav-panel{visibility:hidden;opacity:0;pointer-events:none;translate:0 -8px}
  .nav-item.open .nav-panel{visibility:visible;opacity:1;pointer-events:auto;translate:0 0}
}
/* gold hairline across the head of the panel, like the other card surfaces */
.nav-panel::before{
  content:"";position:absolute;left:0;right:0;top:0;height:1px;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(122,92,24,.4) 24%,var(--tint) 50%,rgba(122,92,24,.4) 76%,transparent);
}
/* panel links opt out of the underline sweep — they get a fill instead */
.nav-panel a{padding:.62rem .8rem;border-radius:var(--chip-r);white-space:nowrap;transition:color .35s var(--ease),background .35s var(--ease)}
.nav-panel a::after{display:none}
.nav-panel a:hover,.nav-panel a.on{color:var(--ivory);background:rgba(201,162,39,.1)}
@media(prefers-reduced-motion:reduce){
  .nav-panel{transition:opacity .15s linear,visibility .15s}
  .nav-item.open .nav-panel{translate:0 0}
}

/* Five top-level items plus the quote button do not fit between the left rail
   and the gutter below about 1040px — the button was being pushed past the
   wrap and clipped. Tightening the item padding buys the ~57px back. The
   alternative was raising the burger breakpoint, which would have taken the
   nav away from a 1024px tablet held landscape, and that is a real device. */
@media(min-width:980px) and (max-width:1099px){
  .nav{--navpad:.34rem;gap:0}
}

@media(max-width:979px){.nav{display:none}}

.head-act{display:flex;align-items:center;gap:1rem;margin-left:auto}
/* Nav is out of flow (absolutely centred), so the actions keep the auto margin
   and stay pinned to the right edge. */
.nav+.head-act{margin-left:auto}
/* Header stages down as it narrows. Top level is only three items now (the
   homepage sections moved into the Home panel), so the bar needs ~848px of
   viewport instead of ~1220px and the collapse point dropped accordingly.
   The nav-hide and hamburger-show breakpoints below are ONE number in two
   places (979px) — move them together or a width exists with no nav at all.
   .btn-txt is declared later, so these need the extra specificity to win. */
@media(max-width:1399px){.head-act .head-tel{display:none}}
/* the sub-line is narrower than "ACURA GOLD" above it, so it costs no extra
   header width — it only comes off on phones, where vertical space is tight */

/* ---------- mobile menu ---------- */
.mtoggle{display:none;position:relative;width:44px;height:44px;flex:none;border:1px solid var(--rule-strong);border-radius:var(--chip-r);transition:border-color .45s var(--ease),background .45s var(--ease)}
.mtoggle span{position:absolute;left:12px;width:20px;height:1px;background:var(--tint-ink);transition:transform .5s var(--ease),opacity .3s}
.mtoggle span:nth-child(1){top:18px}
.mtoggle span:nth-child(2){top:25px}
.mtoggle:hover{border-color:var(--tint);background:rgba(201,162,39,.09)}
.mtoggle[aria-expanded="true"] span:nth-child(1){transform:translateY(3.5px) rotate(45deg)}
.mtoggle[aria-expanded="true"] span:nth-child(2){transform:translateY(-3.5px) rotate(-45deg)}
@media(max-width:979px){
  .mtoggle{display:block}
  /* nav is hidden here, so restore the auto margin .nav+.head-act cancelled */
  .head-in .head-act{margin-left:auto}
}
/* keep logo + CTA + toggle inside the bar on small screens.
   These need 2 classes to outrank .btn/.head-act declared further down. */
@media(max-width:760px){
  .head-act .btn-lume{padding:.95em 1.15em}
  .head-act .btn-lume span{font-size:.72rem;letter-spacing:.1em}
  .head-act{gap:.6rem}
}
/* Phone: the CTA stays. The space is bought back from the lockup — the
   "Construction & Contracting" line is illegible at this size anyway, and
   the brand name carries it on its own. */
@media(max-width:640px){
  .logo .logo-tx span{display:none}
  .logo svg{width:34px;height:34px}
  .head-in{gap:.7rem}
  .head-act{gap:.5rem}
  .head-act .btn-lume{padding:.85em 1.05em}
  .head-act .btn-lume span{font-size:.66rem;letter-spacing:.09em}
  .head-act .btn-lume svg{width:13px;height:13px}
}
@media(max-width:390px){
  .logo svg{width:30px;height:30px}
  .logo-tx b{font-size:.94rem;letter-spacing:.1em}
  .head-act .btn-lume{padding:.78em .82em;gap:.45rem}
  .head-act .btn-lume span{font-size:.62rem;letter-spacing:.05em}
  .mtoggle{width:40px;height:40px}
  .mtoggle span{left:10px;width:18px}
}
/* 320px-class phones: drop the arrow and tighten the wordmark so the CTA
   still fits rather than pushing the toggle off the edge */
@media(max-width:360px){
  .head-in{gap:.5rem}
  .logo-tx b{font-size:.84rem;letter-spacing:.05em}
  .head-act .btn-lume svg{display:none}
  .head-act .btn-lume{padding:.72em .7em;gap:0}
  .head-act .btn-lume span{font-size:.6rem;letter-spacing:.04em}
}

.mmenu{
  position:fixed;inset:0;z-index:45;background:var(--pitch);
  padding:clamp(96px,16vw,132px) var(--gut) clamp(28px,6vw,44px);
  display:flex;flex-direction:column;justify-content:space-between;gap:2rem;overflow-y:auto;
  opacity:0;visibility:hidden;pointer-events:none;transform:translateY(-12px);
  transition:opacity .5s var(--ease),transform .6s var(--ease),visibility 0s linear .5s;
}
.mmenu::before{content:"";position:absolute;inset:0;pointer-events:none;
  background:radial-gradient(700px 420px at 88% -6%,rgba(201,162,39,.2),transparent 62%),radial-gradient(520px 380px at -6% 92%,rgba(201,162,39,.12),transparent 62%)}
.mmenu.open{
  opacity:1;visibility:visible;pointer-events:auto;transform:none;
  transition:opacity .5s var(--ease),transform .6s var(--ease),visibility 0s linear 0s;
}
.mmenu-nav{display:flex;flex-direction:column;position:relative}
.mmenu-nav a{
  display:flex;align-items:baseline;gap:1.1rem;padding:clamp(.75rem,2.4vw,1.05rem) 0;border-bottom:1px solid var(--rule);
  opacity:0;transform:translateY(14px);transition:opacity .55s var(--ease),transform .6s var(--ease),padding-left .4s var(--ease);
}
.mmenu.open .mmenu-nav a{opacity:1;transform:none;transition-delay:calc(var(--i) * 55ms + 90ms)}
.mmenu-nav a:hover{padding-left:.5rem}
.mmenu-nav span{font-family:var(--display);font-weight:700;font-variation-settings:'opsz' 40,'wdth' 100;font-size:clamp(1.6rem,7vw,2.4rem);letter-spacing:-.025em;color:var(--ivory);line-height:1.1}
/* The drawer flattens the Home submenu: a group label, then its children
   indented. A nested disclosure inside a slide-in panel is one interaction
   too many on a phone. */
.mmenu-group{
  display:block;padding:clamp(1.1rem,3vw,1.5rem) 0 .5rem;
  color:var(--tint-ink);font-size:.66rem;font-weight:600;letter-spacing:.16em;
  opacity:0;transform:translateY(14px);transition:opacity .55s var(--ease),transform .6s var(--ease);
}
.mmenu.open .mmenu-group{opacity:1;transform:none;transition-delay:calc(var(--i) * 55ms + 90ms)}
.mmenu-nav .mmenu-child{padding-left:1rem}
.mmenu-nav .mmenu-child:hover{padding-left:1.5rem}
.mmenu-nav .mmenu-child span{font-size:clamp(1.25rem,5.4vw,1.8rem)}
.mmenu-foot{position:relative;display:flex;flex-direction:column;gap:1rem;padding-top:1.6rem;border-top:1px solid var(--rule)}
.mmenu-foot a{display:flex;align-items:center;gap:.8rem;color:var(--ivory);font-size:1rem}
.mmenu-foot svg{width:16px;height:16px;color:var(--tint-ink);flex:none}
body.locked{overflow:hidden}

/* ---------- buttons ---------- */
/* ============================================================
   BUTTONS — soft face, rising fill

   The client's second spec: a soft-shadow face, a pressed :active, and two
   overlapping ellipses that rise from below the button on hover and flood it.
   Geometry, easing and timing are theirs, unchanged — including the 0.1s
   delay and the staggered scaleX so the two ellipses read as one wave rather
   than a single disc.

   Recoloured to the site, per the standing instruction. The spec's teal
   (#009087) is the rising fill; here that role goes to the brand pair, which
   also restores the hierarchy a single flat style loses:

     primary    brass face  ->  espresso rises
     secondary  cream face  ->  brass rises

   Two deliberate departures from the spec, both to avoid breaking what is
   already on the page:

   1. Type stays 13px uppercase, not 18px sentence case. "Explore our
      capabilities" at 18px is wide enough to push the header CTA past the
      viewport at the 1141px breakpoint that has broken twice before.
   2. isolation:isolate rather than z-index:1. Both create the stacking context
      the z-index:-1 ellipses need, but isolate does it without altering how
      buttons stack against the header and the hero washes.

   Focus is kept explicitly — neither supplied spec included a :focus style,
   and without one the site cannot be used from a keyboard.
   ============================================================ */
.btn{
  --btn-face:var(--page);
  --btn-ink:var(--tint-ink);
  --btn-ink-hover:var(--anchor-deep);
  --btn-rise:var(--tint);              /* the colour that floods upward */
  --btn-hi:#FFFFFF;                    /* soft light,  top-left  */
  --btn-lo:rgba(122,92,24,.26);        /* soft shade, bottom-right */

  position:relative;display:inline-flex;align-items:center;justify-content:center;gap:10px;
  overflow:hidden;isolation:isolate;
  font-family:inherit;font-size:13px;font-weight:600;text-transform:uppercase;letter-spacing:.4px;
  white-space:nowrap;cursor:pointer;
  color:var(--btn-ink);
  background:var(--btn-face);
  border:1px solid var(--btn-face);
  border-radius:.5em;
  padding:1.15em 1.9em;
  /* The label must not change colour before the fill reaches it. The spec's
     0.2s colour against a 0.5s+0.1s fill flips the text while most of the
     button is still the old face — espresso-on-brass becomes cream-on-brass at
     1.6:1 for a few hundred milliseconds. Holding the swap until 0.28s puts it
     just after the wave passes the label. */
  transition:color .16s .28s ease-in,border-color .2s ease-in;
}

/* the two rising ellipses. Both sit below the button at rest and are clipped
   away by overflow:hidden until hover lifts them through it. */
.btn::before,
.btn::after{
  content:"";position:absolute;display:block;z-index:-1;
  border-radius:50%;background-color:var(--btn-rise);
  transition:all .5s .1s cubic-bezier(.55,0,.1,1);
}
.btn::before{
  left:50%;top:100%;width:140%;height:180%;
  transform:translateX(-50%) scaleY(1) scaleX(1.25);
  background-color:rgba(36,27,8,.05);   /* the faint leading swell */
}
.btn::after{
  left:55%;top:180%;width:160%;height:190%;
  transform:translateX(-50%) scaleY(1) scaleX(1.45);
}
.btn:hover{color:var(--btn-ink-hover);border-color:var(--btn-rise)}
.btn:hover::before{
  top:-35%;background-color:var(--btn-rise);
  transform:translateX(-50%) scaleY(1.3) scaleX(.8);
}
.btn:hover::after{
  top:-45%;
  transform:translateX(-50%) scaleY(1.3) scaleX(.8);
}

/* soft extrusion, and the pressed state the spec asks for */
.btn{box-shadow:6px 6px 12px var(--btn-lo), -6px -6px 12px var(--btn-hi)}
.btn:active{box-shadow:inset 4px 4px 12px var(--btn-lo), inset -4px -4px 12px var(--btn-hi)}

.btn svg{width:14px;height:14px;transition:translate .5s var(--ease)}
.btn:hover svg{translate:5px 0}
/* the arrow travels; a brand glyph sits still */
.btn-wa:hover svg{translate:none}

/* --- primary: brass face, espresso rises --- */
.btn-lume{
  --btn-face:var(--tint);
  --btn-ink:var(--anchor-deep);
  --btn-ink-hover:var(--tint-lt);
  --btn-rise:var(--anchor-deep);
  --btn-lo:rgba(122,92,24,.5);
}

/* --- secondary keeps the base: cream face, brass rises --- */

/* --- the bronze band ---
   A white soft-light on espresso reads as a scuff, so it drops to a faint warm
   glow and the shade carries the form. */
.on-dark .btn{
  --btn-hi:rgba(242,223,160,.08);
  --btn-lo:rgba(0,0,0,.5);
}
.on-dark .btn-line{
  --btn-face:var(--anchor);
  --btn-ink:var(--tint);
  --btn-ink-hover:var(--anchor-deep);
  --btn-rise:var(--tint);
}

.btn:focus-visible{outline:2px solid var(--tint-ink);outline-offset:3px}
.on-dark .btn:focus-visible{outline-color:var(--tint-lt)}

/* tertiary — text with a travelling rule */
.btn-txt{
  display:inline-flex;align-items:center;gap:.6rem;font-family:var(--mono);font-size:.76rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--tint-ink);padding-bottom:.45rem;position:relative;
  white-space:nowrap;
}
.btn-txt::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;background:var(--tint-dk)}
.btn-txt i{position:absolute;left:0;bottom:0;height:1px;width:100%;background:var(--tint-ink);transform:scaleX(0);transform-origin:right;transition:transform .6s var(--ease);box-shadow:0 0 8px var(--tint)}
.btn-txt:hover i{transform:scaleX(1);transform-origin:left}
.btn-txt svg{width:13px;height:13px;transition:transform .5s var(--ease)}
.btn-txt:hover svg{transform:translateX(4px)}

.btn-row{display:flex;flex-wrap:wrap;gap:.9rem;align-items:center}

/* ---------- hero ---------- */
.hero{min-height:100svh;display:flex;align-items:center;padding-top:120px;padding-bottom:60px;overflow:hidden}
.hero-atm{
  position:absolute;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(1100px 620px at 86% -8%,rgba(201,162,39,.20),transparent 62%),
    radial-gradient(820px 600px at -8% 46%,rgba(201,162,39,.10),transparent 62%),
    radial-gradient(700px 460px at 52% 112%,rgba(122,92,24,.07),transparent 66%);
}
/* faint setting-out grid */
.hero-grid{
  position:absolute;inset:0;z-index:0;pointer-events:none;opacity:.55;
  background-image:
    linear-gradient(90deg,var(--rule) 1px,transparent 1px),
    linear-gradient(180deg,var(--rule) 1px,transparent 1px);
  background-size:clamp(60px,7vw,104px) clamp(60px,7vw,104px);
  -webkit-mask-image:radial-gradient(70% 60% at 30% 40%,#000 10%,transparent 78%);
  mask-image:radial-gradient(70% 60% at 30% 40%,#000 10%,transparent 78%);
}
.hero-in{position:relative;z-index:1;display:grid;grid-template-columns:minmax(0,1.06fr) minmax(0,.94fr);gap:clamp(2rem,5vw,5rem);align-items:center;width:100%}
.hero-copy,.hero-fig{min-width:0}   /* let fr tracks shrink past min-content */
.hero-meta{display:flex;gap:1.6rem;flex-wrap:wrap;margin-bottom:clamp(1.6rem,3vw,2.4rem)}
.hero-meta span{display:inline-flex;align-items:center;gap:.55rem}
.hero-meta span::before{content:"";width:5px;height:5px;rotate:45deg;background:var(--tint)}
h1.display .l3{display:block}
.hero-sub{margin:clamp(1.6rem,3vw,2.2rem) 0 clamp(1.6rem,2.8vw,2.2rem);max-width:46ch}
/* the hero's single call to action — one button, not a row of them */
.hero-act{display:flex;flex-wrap:wrap;gap:.8rem}
@media(max-width:520px){.hero-act .btn{width:100%;justify-content:center}}

/* hero figure */
.hero-fig{position:relative}
.plate{position:relative;overflow:hidden;border-radius:var(--card-r);box-shadow:0 34px 76px -40px rgba(48,38,14,.3);background:var(--panel)}
.plate img{width:100%;height:100%;object-fit:cover;filter:saturate(1.15) contrast(1.1) brightness(.92);transition:filter 1.2s var(--ease),transform 1.4s var(--ease);will-change:transform}
/* cyan/violet grade — soft-light keeps the photograph's own colour alive
   instead of flattening it to grey the way a full duotone did */
.plate::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(168deg,rgba(201,162,39,.34),rgba(122,92,24,.26) 55%,rgba(7,7,10,.62));
  mix-blend-mode:soft-light;
}
.plate::before{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  box-shadow:inset 0 0 0 1px rgba(242,223,160,.16);
}
.plate:hover img{filter:grayscale(.35) contrast(1.08) brightness(.94);transform:scale(1.035)}
.hero-plate{aspect-ratio:4/4.6}
/* slider: stacked frames, only the active one visible */
.hero-plate .slide{position:absolute;inset:0;opacity:0;z-index:0;
  transition:opacity 1.4s var(--ease),filter 1.2s var(--ease),transform 1.4s var(--ease)}
.hero-plate .slide.on{opacity:1;z-index:1}
@media(prefers-reduced-motion:reduce){
  .hero-plate .slide{transition:none}
}

.spec{
  position:absolute;z-index:3;background:rgba(11,11,16,.82);backdrop-filter:blur(14px);
  border:1px solid var(--rule-strong);padding:1rem 1.15rem;border-radius:var(--chip-r);
  box-shadow:0 18px 40px -20px rgba(10,8,4,.5);
}
.spec b{display:block;font-family:var(--display);font-weight:800;font-size:1.7rem;color:var(--ink-inv);line-height:1;letter-spacing:-.02em}
/* inverse context: the badge is dark glass over the hero photograph */
.spec span{display:block;margin-top:.4rem;font-family:var(--mono);font-size:.64rem;font-weight:600;letter-spacing:.15em;text-transform:uppercase;color:var(--tint-lt)}
.spec-yrs{bottom:9%;right:-9%}
@media(max-width:1180px){.spec-yrs{right:-2%}}

.scroll-cue{display:flex;align-items:center;gap:.8rem;margin-top:clamp(2.4rem,4vw,3.4rem)}
.scroll-cue i{display:block;width:52px;height:1px;background:var(--rule-strong);position:relative;overflow:hidden}
.scroll-cue i::after{content:"";position:absolute;inset:0;background:var(--tint);transform:translateX(-100%);animation:cue 2.6s var(--ease-io) infinite}
@keyframes cue{0%{transform:translateX(-100%)}55%,100%{transform:translateX(100%)}}

@media(max-width:960px){
  .hero{min-height:auto;padding-top:104px}
  .hero-in{grid-template-columns:minmax(0,1fr)}
  .hero-fig{margin-top:2.6rem}
  .hero-plate{aspect-ratio:4/3.2}
  .spec-yrs{right:auto;left:4%;bottom:-5%}
}

/* ---------- ticker ---------- */
/* A solid bronze strip between two cream sections — the same value as the
   anchor band, not a second one, so the page reads as one system. Brass
   hairlines top and bottom stop it looking like a block dropped on the page. */
.ticker{
  padding:1.15rem 0;overflow:hidden;white-space:nowrap;
  background:var(--anchor);
  border-block:1px solid rgba(242,223,160,.22);
  box-shadow:inset 0 12px 24px -18px rgba(0,0,0,.6),inset 0 -12px 24px -18px rgba(0,0,0,.6);
}
.ticker-run{display:inline-flex;align-items:center;gap:2.4rem;animation:run 44s linear infinite;will-change:transform}
.ticker:hover .ticker-run{animation-play-state:paused}
/* Gold on green — this is the pairing that only works because of the green.
   On cream the brand gold is 2.4:1 and illegal as text; here it is 5.1:1. */
.ticker-run span{
  font-family:var(--display);font-weight:700;font-variation-settings:'opsz' 24,'wdth' 95;
  font-size:clamp(.95rem,1.5vw,1.22rem);letter-spacing:.09em;text-transform:uppercase;
  color:var(--tint);
}
.ticker-run span.hi{color:var(--tint-lt)}   /* every third, for rhythm */
.ticker-run i{width:5px;height:5px;rotate:45deg;background:var(--tint-lt);flex:none;opacity:.85}
@keyframes run{to{transform:translateX(-50%)}}

/* =================================================================
   CARD SURFACE — shared by project, testimonial, stage and form cards.
   Three things lift a card off a dark ground: a top-to-bottom gradient
   so it reads as a lit panel rather than a flat fill, a hairline of
   light along its top edge, and a layered shadow (tight contact +
   wide ambient). The edge warms to gold and a bloom opens on hover.
   ================================================================= */
/* Lift uses `translate`, not `transform`. .proj and .quote also carry .rv,
   and the reveal system's `.js .rv.in{transform:none}` is (0,3,0) — it would
   silently beat a (0,2,0) `.proj:hover{transform:…}` and kill the lift.
   `translate` is a separate property, so the two never collide. */
.proj,.quote,.step,.form{
  position:relative;
  background:linear-gradient(180deg,#FFFFFF 0%,#FFFDF8 58%,#FFF9EE 100%);
  border:1px solid rgba(122,92,24,.15);
  border-radius:var(--card-r);
  box-shadow:var(--sh-contact),var(--sh-near),var(--sh-mid);
  transition:translate .7s var(--ease),border-color .5s var(--ease),box-shadow .6s var(--ease);
}
.proj:hover,.quote:hover,.step:hover{
  translate:0 -7px;
  border-color:rgba(122,92,24,.4);
  box-shadow:
    inset 0 1px 0 #FFF,
    0 3px 10px -4px rgba(48,38,14,.14),
    var(--sh-far),
    var(--glow-gold);
}
@media(prefers-reduced-motion:reduce){
  .proj:hover,.quote:hover,.step:hover{translate:none}
}

.quote::after{
  content:"";position:absolute;left:0;right:0;top:0;height:1px;z-index:6;pointer-events:none;
  background:linear-gradient(90deg,transparent,var(--tint-ink) 26%,var(--tint) 50%,var(--tint-ink) 74%,transparent);
  transform:scaleX(0);transition:transform .95s var(--ease);
}
.quote:hover::after{transform:scaleX(1)}

/* ---------- flagship projects ---------- */
.projects{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:start;gap:clamp(1.4rem,2.6vw,2.2rem);
  margin-bottom:clamp(1.8rem,3.2vw,2.8rem);
}
/* A card is a photograph with a name on it. Everything else — the write-up,
   the scope, the address — lives in .proj-detail and opens on click. */
.proj{display:flex;flex-direction:column;overflow:hidden}
.proj-head{position:relative}

.proj-shot{position:relative;aspect-ratio:16/10;overflow:hidden}
.proj-shot img{
  width:100%;height:100%;object-fit:cover;
  transform:scale(1.005);transition:transform 1.4s var(--ease),filter .8s var(--ease);
  filter:saturate(.98) contrast(1.05) brightness(.96);
}
.proj:hover .proj-shot img{transform:scale(1.055);filter:saturate(1.06) contrast(1.06) brightness(1)}
/* Scrim. Full-height so the name is legible over any photograph, weighted to
   the bottom so the picture itself stays open. No mix-blend-mode here: this
   element used to inherit soft-light from .plate, which lit the shadows and
   crushed the highlights and made the photo look split light/dark. */
.proj-shot::after{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;mix-blend-mode:normal;
  background:linear-gradient(180deg,
    rgba(7,7,10,.34) 0%, rgba(7,7,10,.06) 24%,
    rgba(7,7,10,.58) 58%, rgba(7,7,10,.88) 84%, rgba(10,9,6,.95) 100%);
}
@media(prefers-reduced-motion:reduce){
  .proj:hover .proj-shot img{transform:scale(1.005)}
}

/* name plate, sitting on the photograph */
.proj-name{
  position:absolute;left:0;right:0;bottom:0;z-index:3;
  padding:clamp(1.2rem,2.2vw,1.7rem);
  transition:translate .7s var(--ease);
}
.proj:hover .proj-name{translate:0 -3px}
.proj-client{display:block;color:var(--tint-lt);margin-bottom:.45rem;text-shadow:0 1px 10px rgba(0,0,0,.85)}
.proj-name h3{
  font-size:clamp(1.25rem,2.1vw,1.6rem);line-height:1.14;
  color:var(--ink-inv);                       /* inverse: sits on the photo */
  text-shadow:0 2px 18px rgba(0,0,0,.8);
}

/* the affordance — also the accessible name for the whole header */
.proj-toggle{
  display:flex;align-items:center;justify-content:space-between;gap:1rem;width:100%;
  padding:.95rem clamp(1.2rem,2.2vw,1.7rem);
  border-top:1px solid var(--rule);color:var(--tint-ink);
  transition:color .45s var(--ease),background .45s var(--ease),box-shadow .45s var(--ease);
}
/* stretched hit area: the button is static, so this resolves against
   .proj-head and makes the photograph itself the click target */
.proj-toggle::after{content:"";position:absolute;inset:0;z-index:8}
.proj-toggle:hover,.proj-head:hover .proj-toggle{color:var(--tint-deep);background:rgba(201,162,39,.1)}
.proj-toggle svg{width:16px;height:16px;flex:none;transition:transform .6s var(--ease)}
.proj.is-open .proj-toggle svg{transform:rotate(180deg)}
.proj.is-open .proj-toggle{box-shadow:inset 0 -1px 0 var(--rule)}

/* Collapsible panel. 0fr → 1fr animates without measuring anything in JS,
   so there is no height race and no stale value after a resize.
   Default is OPEN: with no JS the details must still be readable. */
.proj-detail{display:grid;grid-template-rows:1fr}
.proj-detail-in{overflow:hidden;min-height:0}
.js .proj-detail{
  grid-template-rows:0fr;opacity:0;
  transition:grid-template-rows .78s var(--ease),opacity .45s var(--ease);
}
.js .proj.is-open .proj-detail{grid-template-rows:1fr;opacity:1}
@media(prefers-reduced-motion:reduce){
  .js .proj-detail{transition:opacity .2s linear}
}

.proj-body{padding:clamp(1.4rem,2.4vw,2rem);display:flex;flex-direction:column}
.proj-body p{font-size:.96rem;color:var(--concrete);margin-bottom:1.5rem}

.proj-scope-h{display:block;color:var(--tint-ink);margin-bottom:.9rem}
.proj-scope{
  list-style:none;display:flex;flex-wrap:wrap;gap:.4rem;margin-bottom:1.6rem;
}
.proj-scope li{
  font-size:.78rem;line-height:1.35;color:var(--concrete);
  border:1px solid var(--rule);border-radius:var(--chip-r);padding:.4em .65em;
  background:rgba(201,162,39,.08);
  transition:border-color .45s var(--ease),color .45s var(--ease),background .45s var(--ease);
}
.proj.is-open .proj-scope li,.proj-scope li:hover{border-color:rgba(122,92,24,.34);background:rgba(201,162,39,.16)}

.proj-meta{margin-top:auto;display:grid;gap:0;border-top:1px solid var(--rule)}
.proj-meta dd{max-width:62%}
.proj-meta>div{
  display:flex;align-items:baseline;justify-content:space-between;gap:1rem;
  padding:.7rem 0;border-bottom:1px solid var(--rule);
}
.proj-meta>div:last-child{border-bottom:0;padding-bottom:0}
.proj-meta dt{
  font-family:var(--mono);font-size:.62rem;font-weight:600;letter-spacing:.15em;
  text-transform:uppercase;color:var(--concrete-dim);flex:none;
}
.proj-meta dd{font-size:.92rem;color:var(--ivory);text-align:right}
@media(max-width:820px){.projects{grid-template-columns:minmax(0,1fr)}}

/* ---------- projects page ---------- */
.phero{position:relative;overflow:hidden;padding:clamp(126px,14vw,178px) 0 clamp(44px,5.4vw,76px)}
.phero-in{position:relative;z-index:1}
/* was a Home / Page breadcrumb; now just the page label, matching the .mono
   eyebrow every section on the homepage uses */
.crumb{display:block;color:var(--tint-ink);margin-bottom:clamp(1.6rem,3vw,2.4rem)}
.phero h1{font-size:clamp(2.6rem,7vw,5.6rem);max-width:16ch;margin-bottom:clamp(1.4rem,2.6vw,2rem)}
.phero .lede{max-width:62ch}

.phero-stats{
  display:flex;flex-wrap:wrap;gap:clamp(1.6rem,4vw,3.4rem);
  margin-top:clamp(2.4rem,4vw,3.4rem);padding-top:clamp(1.8rem,3vw,2.4rem);
  border-top:1px solid var(--rule);
}
.phero-stats b{
  display:block;font-family:var(--display);font-weight:800;
  font-variation-settings:'opsz' 72,'wdth' 100;
  font-size:clamp(1.9rem,3.4vw,2.7rem);line-height:1;letter-spacing:-.03em;color:var(--tint-ink);
}
.phero-stats span{
  display:block;margin-top:.55rem;font-family:var(--mono);font-size:.66rem;font-weight:600;
  letter-spacing:.15em;text-transform:uppercase;color:var(--concrete-dim);
}

/* Portfolio grid. Explicit breakpoints rather than auto-fit: these cards
   carry a dozen scope chips, so 3-up only earns its place on a wide screen.
   Two classes so it wins over .projects regardless of source order. */
.projects.projects--all{grid-template-columns:minmax(0,1fr) minmax(0,1fr);margin-bottom:0}
@media(max-width:700px){.projects.projects--all{grid-template-columns:minmax(0,1fr)}}
@media(min-width:1500px){.projects.projects--all{grid-template-columns:repeat(3,minmax(0,1fr))}}

.proj-status{
  position:absolute;top:.9rem;right:.9rem;z-index:4;
  font-family:var(--mono);font-size:.6rem;font-weight:600;letter-spacing:.15em;text-transform:uppercase;
  color:#100B02;background:linear-gradient(180deg,var(--tint-lt),var(--tint));
  padding:.35em .7em;border-radius:var(--chip-r);
  box-shadow:0 2px 10px -3px rgba(201,162,39,.65);
}

/* last child of its section — the section's padding-bottom is the spacing */
.projects-more{
  display:flex;align-items:center;gap:1.2rem;flex-wrap:wrap;
}

.work-cta-in{display:flex;align-items:center;justify-content:space-between;gap:clamp(1.8rem,4vw,3rem);flex-wrap:wrap}
.work-cta-in h2{font-size:clamp(1.8rem,3.6vw,3rem);margin-top:.9rem}
.work-cta-act{display:flex;gap:.8rem;flex-wrap:wrap}
@media(max-width:760px){
  .work-cta-in{flex-direction:column;align-items:flex-start}
  .work-cta-act{width:100%}
  .work-cta-act .btn{flex:1;justify-content:center}
}

/* ---------- measures (stats) ---------- */
/* =================================================================
   TRACK RECORD — one plinth, not four boxes.
   It was a 1px hairline table (gap:1px over a gold background), which
   read as a spreadsheet. Now it is a single raised panel on the shared
   card surface, divided by hairlines that fade out at both ends, with
   each figure standing on its own measuring rule.
   ================================================================= */
.measures{
  display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  position:relative;overflow:hidden;
  background:linear-gradient(180deg,#FFFFFF 0%,#FFFDF8 58%,#FFF9EE 100%);
  border:1px solid rgba(122,92,24,.15);
  border-radius:var(--card-r);
  box-shadow:var(--sh-contact),var(--sh-near),var(--sh-mid);
}
/* gold rule across the head of the plinth, brightest at the centre */
.measures::before{
  content:"";position:absolute;left:0;right:0;top:0;height:1px;z-index:3;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(122,92,24,.35) 20%,var(--tint) 50%,rgba(122,92,24,.35) 80%,transparent);
}

.measure{
  position:relative;
  padding:clamp(1.8rem,3vw,2.8rem) clamp(1.4rem,2.4vw,2.2rem);
}
/* divider — fades top and bottom rather than butting the panel edges */
.measure::before{
  content:"";position:absolute;left:0;top:14%;bottom:14%;width:1px;z-index:2;
  background:linear-gradient(180deg,transparent,rgba(122,92,24,.24) 24%,rgba(122,92,24,.24) 76%,transparent);
}
.measure:first-child::before{display:none}
/* brass light rising from the floor of the cell */
.measure::after{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(120% 88% at 50% 116%,rgba(201,162,39,.16),transparent 66%);
  opacity:0;transition:opacity .7s var(--ease);
}
.measure:hover::after{opacity:1}
/* copy above the glow; .mono stays absolute so it is listed separately */
.measure b,.measure p{position:relative;z-index:1}
.measure .mono{z-index:2}

.measure b{
  display:block;
  font-family:var(--display);font-weight:800;font-variation-settings:'opsz' 72,'wdth' 100;
  font-size:clamp(2.5rem,4.6vw,3.9rem);line-height:1;letter-spacing:-.035em;
  color:var(--ivory);
  padding-bottom:.3em;
}
/* the figure catches light down its face; the unit stays brand gold.
   Clipping is scoped to the inner span so b::after (the rule below) is
   unaffected — background-clip:text on the parent can swallow it. */
.measure b>span{
  background:linear-gradient(180deg,#100E09 0%,var(--ink) 40%,#4A4437 100%);
  -webkit-background-clip:text;background-clip:text;
  color:transparent;-webkit-text-fill-color:transparent;
}
.measure b em{font-style:normal;color:var(--tint-ink);-webkit-text-fill-color:var(--tint-ink)}
/* A transparent fill with no clip support would erase the figure entirely —
   and the figure is the whole point of this block. Put the ink back. */
@supports not ((-webkit-background-clip:text) or (background-clip:text)){
  .measure b>span{background:none;color:var(--ivory);-webkit-text-fill-color:var(--ivory)}
}
/* each figure stands on a measuring rule that extends when you read it */
.measure b::after{
  content:"";position:absolute;left:0;bottom:0;height:2px;width:26px;
  background:linear-gradient(90deg,var(--tint),var(--tint-deep));
  box-shadow:0 0 10px rgba(201,162,39,.4);
  transition:width .8s var(--ease);
}
.measure:hover b::after{width:68px}

.measure p{margin-top:1rem;font-size:.9rem;color:var(--concrete-dim);max-width:20ch;transition:color .5s var(--ease)}
.measure:hover p{color:var(--concrete)}
.measure .mono{
  position:absolute;top:1.15rem;right:1.15rem;font-size:.62rem;color:var(--tint-ink);
  transition:color .5s var(--ease);
}
.measure:hover .mono{color:var(--tint-deep)}

@media(prefers-reduced-motion:reduce){
  .measure:hover b::after{width:26px}
}

/* Two-up. The left rule becomes a row rule, and the column divider drops to
   an inset shadow — a faded gradient cannot do both edges from one pseudo. */
@media(max-width:820px){
  .measures{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .measure::before{
    left:9%;right:9%;top:0;bottom:auto;width:auto;height:1px;
    background:linear-gradient(90deg,transparent,rgba(122,92,24,.24) 24%,rgba(122,92,24,.24) 76%,transparent);
  }
  .measure:nth-child(-n+2)::before{display:none}   /* first row needs no rule above */
  .measure:nth-child(even){box-shadow:inset 1px 0 0 rgba(122,92,24,.18)}
}
@media(max-width:460px){
  .measures{grid-template-columns:minmax(0,1fr)}
  .measure:nth-child(2)::before{display:block}     /* every cell but the first */
  .measure:nth-child(even){box-shadow:none}
}

/* ---------- trades (sticky plate + register) ---------- */
/* minmax(0,…) — see the note on .enq-in. A bare fr floors at min-content. */
.trades-in{display:grid;grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);gap:clamp(2rem,5vw,4.4rem);align-items:start}
.trades-media{position:sticky;top:118px}
.trades-plate{position:relative;aspect-ratio:4/4.5;overflow:hidden;border-radius:var(--card-r);background:var(--panel);box-shadow:0 34px 76px -42px rgba(48,38,14,.3)}
.trades-plate::before{content:"";position:absolute;inset:0;z-index:5;pointer-events:none;box-shadow:inset 0 0 0 1px rgba(242,223,160,.16)}
.trades-plate::after{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:linear-gradient(168deg,rgba(201,162,39,.3),rgba(122,92,24,.24) 52%,rgba(7,7,10,.72));
  mix-blend-mode:soft-light;
}
.tp-shot{position:absolute;inset:0;opacity:0;transform:scale(1.07);transition:opacity 1s var(--ease),transform 1.5s var(--ease)}
.tp-shot.on{opacity:1;transform:scale(1)}
.tp-shot img{width:100%;height:100%;object-fit:cover;filter:saturate(1.15) contrast(1.08) brightness(.9)}
/* Caption scrim, done deterministically.
   A single bottom-anchored gradient does NOT work here: how far up the ramp the
   text lands depends on how many lines the name wraps to, which changes with
   the name, the font size and the breakpoint. Measured over a blown-out sky
   that gave 2.11:1 at 4-up and 2.89:1 on mobile — both failures.

   So the caption box carries its own dense fill, and the fade is a separate
   strip sitting directly above it (`bottom:100%`). Every pixel of text is then
   on >= .88 alpha no matter how the name wraps. */
.tp-cap{
  position:absolute;left:0;right:0;bottom:0;z-index:4;
  padding:1.1rem 1.5rem 1.35rem;
  background:linear-gradient(180deg,rgba(7,7,10,.88),rgba(7,7,10,.96));
  display:flex;align-items:flex-end;justify-content:space-between;gap:1rem;
}
.tp-cap::before{
  content:"";position:absolute;left:0;right:0;bottom:100%;
  height:clamp(2.6rem,6vw,4.4rem);pointer-events:none;
  background:linear-gradient(180deg,transparent,rgba(7,7,10,.5) 58%,rgba(7,7,10,.88));
}
.tp-cap b{
  font-family:var(--display);font-weight:800;font-size:1.45rem;line-height:1.12;
  color:var(--ink-inv);                       /* inverse: sits on the photo */
  letter-spacing:-.02em;
}
.tp-cap span{
  font-family:var(--mono);font-size:.68rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--tint-lt);flex:none;
}
/* Side by side, a long name is squeezed into half the width and wrapped to four
   lines — which on the 16/10 mobile plate ate 84% of the picture. Stack it. */
@media(max-width:620px){
  .tp-cap{flex-direction:column;align-items:flex-start;gap:.4rem;padding:1rem 1.2rem 1.15rem}
  .tp-cap b{font-size:1.2rem}
  .tp-cap span{font-size:.62rem}
}

.register{border-top:1px solid var(--rule)}
.trade{
  position:relative;display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:clamp(1rem,2.4vw,2rem);
  padding:clamp(1.3rem,2.4vw,1.85rem) 0;border-bottom:1px solid var(--rule);cursor:pointer;
  transition:padding-left .6s var(--ease);
}
.trade::before{
  content:"";position:absolute;left:0;right:0;top:0;bottom:0;z-index:-1;
  background:linear-gradient(90deg,rgba(201,162,39,.09),transparent 72%);
  opacity:0;transition:opacity .6s var(--ease);
}
.trade.on{padding-left:clamp(.9rem,2vw,1.6rem)}
.trade.on::before{opacity:1}
.trade-n{font-family:var(--mono);font-size:.74rem;font-weight:600;letter-spacing:.1em;color:var(--concrete-dim);transition:color .5s var(--ease)}
.trade.on .trade-n{color:var(--tint-ink)}
.trade-nm{font-family:var(--display);font-weight:700;font-variation-settings:'opsz' 40,'wdth' 100;font-size:clamp(1.35rem,2.7vw,2.05rem);letter-spacing:-.022em;color:var(--concrete);transition:color .5s var(--ease)}
.trade.on .trade-nm{color:var(--ivory)}
.trade-sp{font-family:var(--mono);font-size:.7rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--concrete);text-align:right;transition:color .5s var(--ease)}
.trade.on .trade-sp{color:var(--tint-ink)}
.trade-d{
  grid-column:2/-1;font-size:.98rem;color:var(--concrete);max-width:52ch;
  max-height:0;opacity:0;overflow:hidden;
  transition:max-height .75s var(--ease),opacity .6s var(--ease),margin-top .75s var(--ease);
}
.trade.on .trade-d{max-height:9rem;opacity:1;margin-top:.75rem}
@media(max-width:900px){
  .trades-in{grid-template-columns:minmax(0,1fr)}
  .trades-media{position:sticky;top:76px;z-index:5;margin-bottom:2rem}
  .trades-plate{aspect-ratio:16/10}
}

/* The Sequence section runs on the page ground like every other band. The
   stages are discrete cards on the shared card surface; the stats strip above
   stays a hairline grid on purpose, so data reads as data and not as cards. */

/* ---------- sequence (process) ---------- */
.seq{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(.9rem,1.5vw,1.3rem)}
.step{padding:clamp(1.8rem,3vw,2.6rem);overflow:hidden}
/* brass light rising from the floor of the card on hover */
.step::before{
  content:"";position:absolute;left:0;right:0;bottom:0;height:82%;z-index:0;pointer-events:none;
  background:linear-gradient(0deg,rgba(201,162,39,.22) 0%,rgba(201,162,39,.08) 38%,transparent 100%);
  opacity:0;transform:translateY(38%);
  transition:opacity .7s var(--ease),transform .95s var(--ease);
}
.step::after{
  content:"";position:absolute;left:0;right:0;top:0;height:1px;z-index:2;
  background:linear-gradient(90deg,var(--tint-ink),transparent);
  transform:scaleX(0);transform-origin:left;transition:transform .9s var(--ease);
}
/* keep the copy above the glow */
.step>*{position:relative;z-index:1}

.step:hover::before{opacity:1;transform:none}
.step:hover::after{transform:scaleX(1)}
.step-n{font-family:var(--mono);font-size:.7rem;font-weight:600;letter-spacing:.14em;color:var(--tint-ink);margin-bottom:clamp(2.4rem,4vw,3.6rem);display:block}
.step h3{font-size:1.24rem;margin-bottom:.7rem}
.step p{font-size:.95rem;color:var(--concrete)}
/* ---------- stage cards: glyph at rest, story on hover ----------
   Modelled on the reference card. The card carries nothing but its glyph until
   you hover it; then the glyph swells, blurs and drifts while the copy fades
   in on top of it.

   Three things the reference never had to solve, handled here:

   - A phone has no hover. Under (hover:none) the copy is shown permanently and
     the glyph falls back to a faint backdrop, otherwise the entire contents of
     these cards would be unreachable on mobile.
   - :focus-within mirrors :hover so the cards open for keyboard users too.
   - opacity:0 rather than display:none keeps the copy in the DOM, so search
     engines and screen readers still get it. Do not "optimise" that to
     display:none — it would delete four stages of real content from the page.

   The card keeps its full height at rest because the hidden copy is still in
   flow; that is what leaves the glyph centred in an apparently empty card. */
.seq .step{
  display:flex;flex-direction:column;align-items:center;justify-content:center;
  text-align:center;min-height:clamp(300px,25vw,346px);
}
.seq .step-ico{
  position:absolute;left:50%;top:50%;translate:-50% -50%;scale:1;
  width:auto;height:30%;aspect-ratio:1;
  display:grid;place-items:center;
  background:none;border:0;box-shadow:none;border-radius:0;overflow:visible;
  color:var(--tint-ink);z-index:1;
  transition:height .45s ease-in-out,filter .45s ease-in-out,
             opacity .45s ease-in-out,color .45s ease-in-out;
}
.seq .step-ico::after{display:none}        /* the old badge sheen */
.seq .step-ico svg{width:100%;height:100%}
/* Visible by default, hidden only once .js confirms a script is running to
   open it again. Without that guard a reader with JavaScript off — or one
   served a broken bundle — gets seven cards containing nothing but an icon. */
.seq .step-tx{
  position:relative;z-index:2;
  display:flex;flex-direction:column;align-items:center;gap:.45rem;
  opacity:1;transition:opacity .28s ease-in-out;
}
.js .seq .step-tx{opacity:0}
.seq .step-n{margin-bottom:0}
.seq .step h3{margin-bottom:0}
/* This copy is read against a blurred gold glyph rather than a flat card, so
   it carries more weight and the darkest ink than the same paragraph would
   need elsewhere on the site. */
.seq .step-tx p{font-weight:600;color:var(--ink)}

@keyframes stepDrift{
  0%{transform:translateY(0)}
  50%{transform:translateY(-20px)}
  100%{transform:translateY(0)}
}

@media(hover:hover){
  .seq .step{transition:scale .25s ease-in-out,rotate .25s ease-in-out}
  .seq .step:hover,.seq .step:focus-within{scale:1.04;rotate:-1deg;z-index:3}
  /* The reference blurs a LIGHT logo under WHITE text on a dark card, so the
     blur always sits darker than the copy. Invert that on a cream card and it
     breaks: the resting glyph is deep brass (--tint-ink), and body text over
     it measures 1.85:1 — unreadable exactly where the stroke lands. So as the
     glyph blurs it also lightens to the fill-only gold and drops in opacity.
     Measured over the real card at .5: body 8.8:1, heading 11.8:1, and the
     small mono stage label 4.8:1. The label is the binding constraint — it is
     11px, so it needs the full 4.5:1, and at .55 it sat at 4.55. Raising this
     value again will push it under. */
  .seq .step:hover .step-ico,
  .seq .step:focus-within .step-ico{
    height:65%;filter:blur(7px);
    color:var(--tint);opacity:.5;
    animation:stepDrift 3s ease-in-out infinite;
  }
  .seq .step:hover .step-tx,
  .seq .step:focus-within .step-tx{opacity:1}
}

/* ---------- tablet and phone ----------
   No hover to give, so the card opens itself when it reaches the middle of the
   screen — .on is set by trackStepsOnScroll() in acura.js. Same glyph swell,
   blur and drift as the pointer version, so the behaviour is identical; only
   the trigger differs.

   The tilt is dropped and the swell eased back: a 1.04 scale with a -1deg
   rotate is a nice flourish under a cursor you control, but applied to a card
   that opens on its own while you are scrolling past it, it reads as the
   layout wobbling. */
@media(hover:none){
  .js .seq .step{transition:scale .3s ease-in-out}
  .js .seq .step.on{scale:1.015;z-index:3}
  .js .seq .step.on .step-ico{
    height:65%;filter:blur(7px);
    color:var(--tint);opacity:.5;
    animation:stepDrift 3s ease-in-out infinite;
  }
  .js .seq .step.on .step-tx{opacity:1}
  /* focus still opens a card, for a keyboard attached to a touch device */
  .js .seq .step:focus-within .step-tx{opacity:1}
  .js .seq .step:focus-within .step-ico{
    height:65%;filter:blur(7px);color:var(--tint);opacity:.5;
  }
}

@media(prefers-reduced-motion:reduce){
  .seq .step:hover,.seq .step:focus-within,.js .seq .step.on{scale:1;rotate:0deg}
  .seq .step:hover .step-ico,
  .seq .step:focus-within .step-ico,
  .js .seq .step.on .step-ico{animation:none}
}

/* Two columns from 1080px down, not 900px.
   A Surface Pro is 912 CSS px and a landscape iPad is 1024 — both used to
   clear the old 900px line and get four ~200px columns of badly cramped copy.
   Worse for the reveal: four across is a single row, and the scroll trigger
   opens a row at a time, so the entire grid opened at once and there was
   nothing left to reveal. At two columns a tablet gets a readable card and the
   cards open a pair at a time, as intended. */
@media(max-width:1080px){.seq{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:520px){.seq{grid-template-columns:minmax(0,1fr)}}
/* three-up variant, declared after .seq's own breakpoints so it wins the tie */
.seq--3{grid-template-columns:repeat(3,minmax(0,1fr))}
@media(max-width:1080px){.seq--3{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(max-width:560px){.seq--3{grid-template-columns:minmax(0,1fr)}}

/* Visible to a screen reader, to nothing else. Kept here as a utility rather
   than inside a component block — it was lost once already when one of those
   blocks was replaced, and five buttons started shouting their labels. */
.sr-only{
  position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0;
}

/* ============================================================
   THE CREW — circular portraits set out on a datum

   Circles alone are the most common team section on the internet, so what
   carries this is what the circles are arranged ON: a brass datum drawn
   through the row, with each portrait stepped alternately above and below it.
   That is a levelling diagram — the language the rest of this site already
   speaks — and it stops the row reading as five identical bubbles.

   The ring around each portrait is a separate element rather than a border,
   so it can rotate and scale independently of the photograph. A border cannot
   be rotated on its own.

   There is no click target here. The cards are presentational: everything a
   reader gets is on the page already, so nothing is hidden behind an
   interaction. The hover is decoration, not an affordance.
   ============================================================ */
.crew{
  position:relative;
  display:grid;grid-template-columns:repeat(5,minmax(0,1fr));
  gap:clamp(1rem,2.2vw,2.2rem);
  padding-block:clamp(1.4rem,3vw,2.6rem);
  align-items:start;      /* captions all begin on the same line */
  justify-items:center;
}

/* the datum: stops short of both ends so it reads as a drawn line, not a rule */
.crew-datum{
  position:absolute;left:6%;right:6%;top:calc(var(--disc, 172px) * .5 + clamp(1.4rem,3vw,2.6rem));
  height:1px;background:linear-gradient(90deg,transparent,var(--rule-strong) 12%,var(--rule-strong) 88%,transparent);
  pointer-events:none;
}

.cw{
  --disc:clamp(104px,11vw,172px);
  display:flex;flex-direction:column;align-items:center;text-align:center;
}

/* --- the portrait --- */
.cw-fig{
  position:relative;display:grid;place-items:center;
  width:var(--disc);height:var(--disc);
  isolation:isolate;
}
.cw-disc{
  position:relative;z-index:2;
  /* aspect-ratio, not width+height:100% — if anything ever sizes the button
     unevenly again the disc stays round instead of becoming an oval */
  width:100%;aspect-ratio:1;border-radius:50%;overflow:hidden;flex:none;
  display:grid;place-items:center;
  background:linear-gradient(168deg,#FFFBF1 0%,#F3E5C6 58%,#E9D9B0 100%);
  /* inset, so it never adds to the box and every circle stays exactly --disc */
  box-shadow:var(--sh-contact),var(--sh-near),inset 0 0 0 1px rgba(122,92,24,.28);
  transition:transform .55s var(--ease),box-shadow .55s var(--ease);
}
.cw-disc img{
  width:100%;height:100%;object-fit:cover;object-position:center 22%;
  transition:transform 1.1s var(--ease);
}
.cw-mono{
  font-family:var(--display);font-weight:700;line-height:1;
  font-size:calc(var(--disc) * .3);letter-spacing:.04em;
  color:var(--tint-ink);opacity:.32;
}

/* the ring — its own element so it can turn without turning the photograph */
.cw-ring{
  position:absolute;inset:-9px;z-index:1;border-radius:50%;
  border:1px solid var(--rule-strong);
  /* a gap in the ring, so the rotation is visible. conic-gradient in a mask
     gives an arc that a plain border cannot. */
  -webkit-mask:conic-gradient(#000 0 292deg, transparent 292deg 360deg);
  mask:conic-gradient(#000 0 292deg, transparent 292deg 360deg);
  rotate:-90deg;
  transition:rotate 1.1s var(--ease),inset .5s var(--ease),border-color .5s var(--ease);
}
/* the station number, riding the ring */
.cw-idx{
  position:absolute;z-index:3;top:-6px;right:-2px;
  font-family:var(--mono);font-size:.58rem;font-weight:600;letter-spacing:.16em;
  color:var(--tint-ink);
  background:var(--page);border-radius:999px;padding:.15em .45em;
}

@media(hover:hover){
  .cw:hover .cw-disc{
    transform:scale(1.035);
    box-shadow:var(--sh-contact),var(--sh-near),0 22px 50px -26px rgba(122,92,24,.5);
  }
  .cw:hover .cw-disc img{transform:scale(1.05)}
  .cw:hover .cw-ring{rotate:200deg;inset:-13px;border-color:var(--tint)}
}

/* --- the caption --- */
.cw-tx h3{
  font-size:clamp(1rem,1.15vw,1.14rem);line-height:1.2;margin-bottom:.28rem;
}
.cw--tbc h3{color:var(--concrete-dim)}
.cw-role{
  display:block;font-family:var(--mono);font-size:.58rem;font-weight:600;
  letter-spacing:.15em;text-transform:uppercase;color:var(--tint-ink);
  margin-bottom:.6rem;
}
.cw-tx p{font-size:.86rem;line-height:1.55;color:var(--concrete)}

/* Everything below counts with -of-type, not -child.
   .crew-datum is the grid's first child, so every :nth-child index is one
   higher than the card's real position — which is why the fifth portrait,
   :nth-child(6) and therefore even, refused to centre on a phone. Counting
   <article> elements only makes the rule mean what it says. */
@media(max-width:1080px){
  .crew{grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(1.6rem,3vw,2.4rem)}
  .crew-datum{display:none}
  .cw{padding-top:0}
}
@media(max-width:680px){
  .crew{grid-template-columns:repeat(2,minmax(0,1fr))}
  /* an odd list leaves one alone on the last row; centre it across both
     columns rather than letting it hang to the left */
  .cw:last-of-type:nth-of-type(odd){grid-column:1 / -1}
}
@media(max-width:420px){
  .crew{grid-template-columns:minmax(0,1fr)}
  .cw{--disc:clamp(128px,42vw,168px)}
  .cw:last-of-type:nth-of-type(odd){grid-column:auto}
}

@media(prefers-reduced-motion:reduce){
  .cw-ring,.cw-disc,.cw-disc img{transition-duration:.01ms}
}


/* ============================================================
   THE READER — two columns, no card

   Clicking a portrait swaps what is shown here. Deliberately not a card and
   not a modal: no panel background, no border, no shadow. What holds it
   together is alignment and type, which is what makes it read as considered
   rather than as another boxed component.

   The section height is fixed by the square portrait, and the account scrolls
   inside the right column. So switching between a two-line bio and a ten-line
   one never moves the page — the layout is a frame, and only its contents
   change.

   Every profile is in the HTML. JavaScript only chooses which is visible, so
   with scripts off all five stack and read as one list.
   ============================================================ */
.reader{margin-top:clamp(2.4rem,5vw,4.4rem)}

.ds{
  /* one variable for both the column width and the row height, so the frame
     is exactly the square portrait and the two can never drift apart */
  --shot:clamp(230px,27vw,360px);
  display:grid;
  grid-template-columns:var(--shot) minmax(0,1fr);
  grid-template-rows:var(--shot);
  gap:clamp(1.8rem,4vw,4.2rem);
  align-items:stretch;
}
/* scripts off: every panel shows, ruled apart so they do not run together */
.ds + .ds{margin-top:2.4rem;padding-top:2.4rem;border-top:1px solid var(--rule)}
.js .ds{display:none}
.js .ds.is-on{display:grid;animation:dsIn .5s var(--ease) both}
.js .ds + .ds{margin-top:0;padding-top:0;border-top:0}

@keyframes dsIn{ from{opacity:0;translate:0 10px} to{opacity:1;translate:0 0} }

/* --- the portrait: square, which is the shape a headshot arrives in --- */
.ds-shot{
  position:relative;height:100%;overflow:hidden;
  border-radius:calc(var(--card-r) * .9);
  display:grid;place-items:center;
  background:linear-gradient(168deg,#FFFBF1 0%,#F3E5C6 58%,#E9D9B0 100%);
  box-shadow:inset 0 0 0 1px rgba(122,92,24,.22);
}
.ds-shot img{width:100%;height:100%;object-fit:cover;object-position:center 20%}
.ds-mono{
  font-family:var(--display);font-weight:700;line-height:1;
  font-size:clamp(2.6rem,6vw,4.4rem);letter-spacing:.04em;
  color:var(--tint-ink);opacity:.3;
}

/* --- the account --- */
.ds-tx{
  min-width:0;display:flex;flex-direction:column;
  padding-block:clamp(.2rem,1vw,.8rem);
}
.ds-idx{
  font-family:var(--mono);font-size:.6rem;font-weight:600;
  letter-spacing:.2em;text-transform:uppercase;color:var(--tint-ink);
  margin-bottom:.75rem;
}
.ds-tx h3{
  font-size:clamp(1.6rem,3.2vw,2.5rem);line-height:1.05;margin-bottom:.5rem;
}
.ds-role{
  font-family:var(--mono);font-size:.63rem;font-weight:600;
  letter-spacing:.17em;text-transform:uppercase;color:var(--tint-ink);
  padding-bottom:1.1rem;margin-bottom:1.2rem;
  border-bottom:1px solid var(--rule);
}

/* The account scrolls, the frame does not. min-height:0 is what allows a flex
   child to shrink below its content and therefore to scroll at all — without
   it the column just grows and the whole section jumps on every change. */
.ds-scroll{
  flex:1;min-height:0;overflow-y:auto;overscroll-behavior:contain;
  padding-right:1.15rem;
  scrollbar-width:thin;
  scrollbar-color:rgba(122,92,24,.42) transparent;
}
.ds-scroll::-webkit-scrollbar{width:4px}
.ds-scroll::-webkit-scrollbar-track{background:transparent}
.ds-scroll::-webkit-scrollbar-thumb{
  background:rgba(122,92,24,.34);border-radius:99px;
}
.ds-scroll:hover::-webkit-scrollbar-thumb{background:rgba(122,92,24,.55)}
.ds-scroll:focus-visible{outline:2px solid var(--tint-ink);outline-offset:6px;border-radius:4px}
.ds-scroll p{font-size:1rem;line-height:1.75;color:var(--ink-2);max-width:64ch}
.ds-years{
  margin-top:1rem;font-family:var(--mono);font-size:.62rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--concrete-dim);
}
.ds-tags{list-style:none;display:flex;flex-wrap:wrap;gap:.5rem;margin-top:1.3rem}
.ds-tags li{
  font-family:var(--mono);font-size:.6rem;font-weight:600;letter-spacing:.12em;
  text-transform:uppercase;color:var(--tint-deep);
  background:rgba(201,162,39,.13);border:1px solid rgba(122,92,24,.2);
  border-radius:999px;padding:.42em .85em;
}

/* --- which portrait is being read --- */
.cw-fig{
  background:none;border:0;padding:0;cursor:pointer;
  display:grid;place-items:center;position:relative;isolation:isolate;
  width:var(--disc);height:var(--disc);
}
.cw-fig:focus-visible{outline:2px solid var(--tint-ink);outline-offset:8px;border-radius:50%}
.js .cw.is-on .cw-ring{rotate:200deg;inset:-13px;border-color:var(--tint)}
.js .cw.is-on .cw-disc{
  box-shadow:var(--sh-contact),var(--sh-near),0 20px 46px -24px rgba(122,92,24,.5),
             inset 0 0 0 1px rgba(122,92,24,.28);
}
.js .cw.is-on .cw-idx{color:var(--anchor-deep);background:var(--tint)}
.js .cw.is-on .cw-tx h3{color:var(--tint-deep)}
/* the unselected step back, so the one being read leads the row */
.js .cw:not(.is-on) .cw-disc{opacity:.62;transition:opacity .45s var(--ease)}
.js .cw:not(.is-on) .cw-tx{opacity:.72;transition:opacity .45s var(--ease)}
.js .cw:not(.is-on):hover .cw-disc,
.js .cw:not(.is-on):hover .cw-tx{opacity:1}

/* the caption under each circle is now just a label — the detail lives below */
.cw-tx{margin-top:clamp(.8rem,1.4vw,1.1rem);width:100%;max-width:24ch;margin-inline:auto}
/* The short introduction, under the designation. Kept to three lines so one
   long entry cannot make its column tower over the rest of the row — the full
   account is in the reader below, which is where length belongs. */
.cw-tx p{
  margin-top:.55rem;font-size:.82rem;line-height:1.5;color:var(--concrete);
  display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;
  line-clamp:3;overflow:hidden;
}

@media(max-width:860px){
  /* image above the account, as asked. The square gets a ceiling so it does
     not swallow the screen on a tablet held in portrait. */
  .ds{grid-template-columns:minmax(0,1fr);grid-template-rows:auto auto;gap:clamp(1.4rem,4vw,2rem);height:auto}
  .ds-shot{max-width:min(340px,68vw);margin-inline:auto;width:100%;height:auto;aspect-ratio:1}
  .ds-tx{text-align:center;align-items:center}
  .ds-role{border-bottom:0;padding-bottom:.5rem;margin-bottom:.9rem}
  /* no flex frame to fill once stacked, so the account gets its own ceiling */
  .ds-scroll{max-height:min(46vh,340px);padding-right:.9rem;text-align:left}
  .ds-scroll p{margin-inline:auto}
  .ds-tags{justify-content:center}
}
@media(prefers-reduced-motion:reduce){
  .js .ds.is-on{animation:none}
}

/* ---------- about page ---------- */
.abt-in{display:grid;grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);gap:clamp(2rem,5vw,4.4rem);align-items:start}
.abt-plate{aspect-ratio:4/4.4;position:sticky;top:118px}
.abt-tx>p{font-size:1.02rem;color:var(--concrete)}
.abt-tx>p+p{margin-top:1.15rem}

/* An announcement set inside body copy. Marked off by a gold rule down the
   left rather than a card, because the section already carries a plate and a
   second boxed thing beside it starts to read as a sidebar advert.
   Its paragraphs are styled here rather than left to `.abt-tx>p` — that
   selector is a direct-child one and stops at the wrapper. */
.notice{
  margin-top:clamp(2.4rem,4vw,3.4rem);
  padding:clamp(1.5rem,2.6vw,2rem) 0 0 clamp(1.3rem,2.4vw,1.9rem);
  border-top:1px solid var(--rule);
  border-left:2px solid var(--tint-ink);
}
.notice-tag{display:block;color:var(--tint-ink);margin-bottom:.7rem}
.notice h3{
  font-family:var(--display);font-weight:700;
  font-size:clamp(1.24rem,1.9vw,1.5rem);line-height:1.24;
  color:var(--ivory);margin-bottom:1.1rem;max-width:26ch;
}
.notice p{font-size:1.02rem;color:var(--concrete)}
.notice p+p{margin-top:1.15rem}

@media(max-width:900px){
  .abt-in{grid-template-columns:minmax(0,1fr)}
  .abt-plate{aspect-ratio:16/10;position:static}
}

/* ---------- proof ---------- */
/* one review per delivered project — two up, so each gets room to be read */
.proof-in{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(1.4rem,2.4vw,2rem)}
.quote{padding:clamp(1.7rem,2.6vw,2.3rem);display:flex;flex-direction:column}

.quote-stars{display:flex;gap:.28rem;margin-bottom:1.2rem}
.quote-stars svg{width:13px;height:13px;color:var(--tint-ink)}
.quote p{font-size:1rem;color:var(--concrete);flex:1;margin-bottom:1.6rem}
.quote footer{display:flex;align-items:center;gap:.85rem;padding-top:1.15rem;border-top:1px solid var(--rule)}
.quote-av{width:38px;height:38px;border-radius:50%;flex:none;display:grid;place-items:center;font-family:var(--mono);font-size:.7rem;font-weight:600;letter-spacing:.04em;color:var(--tint-deep);background:linear-gradient(150deg,rgba(201,162,39,.34),rgba(201,162,39,.14));border:1px solid var(--rule-strong)}
.quote-av{transition:box-shadow .6s var(--ease),border-color .6s var(--ease)}
.quote:hover .quote-av{border-color:var(--tint-ink);box-shadow:0 0 20px -6px rgba(201,162,39,.6)}
.quote footer b{display:block;font-family:var(--display);font-weight:700;font-size:.96rem;color:var(--ivory);line-height:1.25}
.quote footer span{font-family:var(--mono);font-size:.64rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--concrete-dim)}
@media(max-width:960px){.proof-in{grid-template-columns:minmax(0,1fr)}}

/* ---------- night sky (behind the skyline) ---------- */
.has-sky>.wrap{position:relative;z-index:1}   /* silhouettes sit in front */
.nightsky{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
/* faint glow on the horizon, so the buildings sit in light rather than on black */
.nightsky::after{
  content:"";position:absolute;left:0;right:0;bottom:0;height:62%;
  background:radial-gradient(64% 100% at 50% 100%,rgba(201,162,39,.16),transparent 74%);
}
/* Light theme: no starfield. The moon and stars are hidden rather than
   deleted so the generator and the editor keep working unchanged. */
.moon,.stars{display:none}

.moon{
  position:absolute;top:clamp(4%,6vw,12%);right:clamp(5%,9vw,15%);
  width:clamp(56px,7vw,104px);height:auto;
  animation:moonPulse 7.5s var(--ease-io) infinite;
}
/* target the visible disc only — a bare `circle` selector would also recolour
   the black cut-out inside <mask>, and CSS fill beats the fill attribute */
.moon .moon-disc{fill:var(--tint-lt)}
@keyframes moonPulse{
  0%,100%{opacity:.5;filter:drop-shadow(0 0 14px rgba(201,162,39,.3))}
  50%    {opacity:.95;filter:drop-shadow(0 0 40px rgba(242,223,160,.55))}
}

.stars{position:absolute;inset:0}
.stars i{
  position:absolute;left:var(--x);top:var(--y);
  width:var(--s);height:var(--s);border-radius:50%;
  background:var(--tint-lt);opacity:var(--o);
  box-shadow:0 0 6px rgba(242,223,160,.55);
  animation:twinkle var(--d) ease-in-out infinite;
  animation-delay:var(--t);
  will-change:opacity,transform;
}
@keyframes twinkle{
  0%,100%{opacity:calc(var(--o) * .35);transform:scale(.8)}
  50%    {opacity:1;transform:scale(1.25)}
}
@media(prefers-reduced-motion:reduce){
  /* hold a still night rather than a frozen keyframe */
  .moon,.stars i{animation:none!important;opacity:.6!important;transform:none!important}
}

/* ---------- enquiry ---------- */
.enq{background:var(--anchor);border-top:0}

/* ---------- the green anchor ----------
   Enquiry and footer are adjacent, so together they read as one deep band
   that lands the page instead of letting it fade out on cream. A hairline of
   brass marks the join with the cream above it. */
.on-dark{position:relative}
.enq.on-dark::before{
  content:"";position:absolute;left:0;right:0;top:0;height:1px;z-index:2;
  background:linear-gradient(90deg,transparent,rgba(201,162,39,.55) 18%,var(--tint-lt) 50%,rgba(201,162,39,.55) 82%,transparent);
}
/* the card surface is a white gradient; inside the green it becomes a panel
   lifted off the band rather than a hole cut in it */
.on-dark .proj,.on-dark .quote,.on-dark .step,.on-dark .form,.on-dark .measures{
  background:linear-gradient(180deg,var(--anchor-panel) 0%,#3C2F11 58%,#33270C 100%);
  border-color:rgba(242,223,160,.16);
}
/* ---------- enquiry form: carved panel, raised controls ----------
   The client's soft-3D spec, remapped to the brand rather than copied.

   Three substitutions, each for a reason:
   - The fill was #212121. Neutral grey on a warm bronze band reads as dirt, so
     it becomes --anchor-deep, the site's own darkest espresso.
   - The light source was rgba(255,255,255,.6). Pure white against espresso
     greys the whole panel; it becomes a warm brass highlight at much lower
     alpha, which is what makes the bevel look lit rather than dusty.
   - The shade was rgba(0,0,0,1). Full-opacity black at a 10px blur on a
     mid-brown panel is a smear, not a shadow — .55 keeps the depth without
     the smudge.

   The panel is debossed (inset) and the controls sit proud of it (outer), so
   the fields read as raised out of a carved recess. On focus a control gets
   both shadows at once, which is what makes it look pressed back in. */
.on-dark .form{
  box-shadow:
    inset 2px 2px 10px rgba(0,0,0,.55),
    inset -1px -1px 5px rgba(242,223,160,.10);
}
.on-dark .field input,.on-dark .field select,.on-dark .field textarea{
  background-color:var(--anchor-deep);
  border:2px solid var(--anchor-deep);
  color:var(--ink);
  border-radius:6px;
  box-shadow:
    6px 6px 10px rgba(0,0,0,.55),
    1px 1px 10px rgba(242,223,160,.10);
  transition:transform .35s var(--ease),box-shadow .35s var(--ease),
             border-color .35s var(--ease);
}
.on-dark .field input:focus,.on-dark .field select:focus,.on-dark .field textarea:focus{
  outline:none;
  border-color:var(--tint);
  background-color:var(--anchor-deep);
  /* raised and recessed together — the spec's "pressed" state */
  box-shadow:
    6px 6px 10px rgba(0,0,0,.55),
    1px 1px 10px rgba(242,223,160,.10),
    inset 2px 2px 10px rgba(0,0,0,.55),
    inset -1px -1px 5px rgba(242,223,160,.14);
  transform:scale(1.05);
  /* the grown field must sit over its neighbour, not under it */
  position:relative;z-index:2;
}
.on-dark .field input::placeholder,.on-dark .field textarea::placeholder{color:#9E988B;opacity:1}
/* the spec fades the placeholder on focus, so the field reads as ready to type */
.on-dark .field input:focus::placeholder,
.on-dark .field textarea:focus::placeholder{opacity:0;transition:opacity .3s var(--ease)}

/* scale(1.05) on a field is a nice touch with a mouse and a liability on a
   phone, where the keyboard is already shoving the layout around. */
@media(max-width:520px),(prefers-reduced-motion:reduce){
  .on-dark .field input:focus,.on-dark .field select:focus,.on-dark .field textarea:focus{
    transform:none;
  }
}
/* Secondary button on the bronze band is handled with the rest of the button
   system — see ".on-dark .btn-line" in the BUTTONS block. */
.on-dark .wordmark{color:var(--tint);opacity:.2}
.on-dark .wordmark:hover{color:var(--tint-lt);opacity:.5;filter:drop-shadow(0 0 22px rgba(201,162,39,.5))}
.on-dark .form::before{background:linear-gradient(90deg,transparent,var(--tint),transparent)}
/* minmax(0,…) not plain fr: an fr track's implicit minimum is min-content, so
   one long word anywhere inside can force the column wider than the viewport. */
.enq-in{display:grid;grid-template-columns:minmax(0,.95fr) minmax(0,1.05fr);gap:clamp(2.4rem,5vw,5rem);align-items:start}
.enq-list{list-style:none;margin-top:2rem;display:flex;flex-direction:column;gap:1.15rem}
.enq-list li{display:flex;gap:1rem;align-items:flex-start;font-size:.96rem}
.enq-list svg{width:16px;height:16px;color:var(--tint-ink);flex:none;margin-top:.32em}
.enq-cts{margin-top:2.6rem;padding-top:2rem;border-top:1px solid var(--rule);display:grid;gap:1.2rem}
.enq-ct{display:flex;gap:1rem;align-items:flex-start;min-width:0}
.enq-ct svg{width:17px;height:17px;color:var(--tint-ink);flex:none;margin-top:.3em}
/* talha.noor@acuragold.com is a single unbreakable token 254px wide. At 320px
   it set the min-content of the whole enquiry column and pushed the page into
   horizontal scroll. `anywhere` (not `break-word`) is required: only `anywhere`
   actually reduces the min-content contribution, which is what the grid reads. */
.enq-ct b{display:block;font-family:var(--display);font-weight:700;font-size:1.02rem;color:var(--ivory);min-width:0;overflow-wrap:anywhere}
.enq-ct span{font-family:var(--mono);font-size:.64rem;font-weight:600;letter-spacing:.13em;text-transform:uppercase;color:var(--concrete-dim)}

.form{padding:clamp(1.6rem,3vw,2.6rem);display:flex;flex-direction:column;gap:1.15rem;position:relative;overflow:hidden}
.form::before{content:"";position:absolute;top:0;left:0;right:0;height:1px;background:linear-gradient(90deg,transparent,var(--tint),transparent)}
.form-hd{display:flex;align-items:baseline;justify-content:space-between;gap:1rem;margin-bottom:.4rem}
.form-hd h3{font-size:1.5rem}
.f2{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:1.15rem}
.field{display:flex;flex-direction:column;gap:.5rem}
.field>span{font-family:var(--mono);font-size:.66rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--concrete-dim)}
.field input,.field select,.field textarea{
  font-family:var(--body);font-size:.97rem;color:var(--ivory);
  background-color:#FFFCF5;border:1px solid var(--rule-strong);border-radius:var(--chip-r);padding:.92em 1em;width:100%;
  transition:border-color .45s var(--ease),box-shadow .45s var(--ease),background-color .45s var(--ease);
}
.field textarea{resize:vertical;min-height:112px}
.field input::placeholder,.field textarea::placeholder{color:var(--concrete-dim);opacity:.7}
.field input:focus,.field select:focus,.field textarea:focus{
  outline:none;border-color:var(--tint-ink);background-color:#FFF;
  box-shadow:0 0 0 3px rgba(201,162,39,.22),inset 0 1px 3px rgba(48,38,14,.06);
}
.field select{appearance:none;cursor:pointer;
  background-image:linear-gradient(45deg,transparent 50%,var(--tint) 50%),linear-gradient(135deg,var(--tint) 50%,transparent 50%);
  background-position:calc(100% - 18px) 52%,calc(100% - 13px) 52%;background-size:5px 5px,5px 5px;background-repeat:no-repeat}
.hp{position:absolute;left:-9999px}
.form-note{font-family:var(--mono);font-size:.64rem;font-weight:500;letter-spacing:.1em;text-transform:uppercase;color:var(--concrete-dim);text-align:center}
/* shown only when the POST actually fails — the visitor gets a route that works */
.form-err{
  font-size:.92rem;line-height:1.5;color:var(--ivory);
  background:rgba(190,60,45,.14);border:1px solid rgba(226,120,100,.5);
  border-radius:var(--chip-r);padding:.85rem 1rem;
}
.form-err a{color:var(--tint-lt);text-decoration:underline;text-underline-offset:2px}
.form-err a:hover{color:var(--tint-pale)}
.form [disabled]{opacity:.7;cursor:progress}
.sent{padding:2.6rem 1rem;text-align:center}
.sent svg{width:38px;height:38px;color:var(--tint-ink);margin:0 auto 1.2rem}
.sent b{display:block;font-family:var(--display);font-weight:800;font-size:1.5rem;color:var(--ivory);margin-bottom:.6rem}
.sent p{color:var(--concrete-dim);font-size:.94rem;max-width:40ch;margin:0 auto}
@media(max-width:900px){.enq-in{grid-template-columns:minmax(0,1fr)}}
@media(max-width:520px){.f2{grid-template-columns:minmax(0,1fr)}}

/* ---------- foot ---------- */
.foot{background:var(--anchor);border-top:0;padding-top:clamp(2.6rem,4.4vw,4rem);overflow:hidden}
.foot-top{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,.8fr) minmax(0,.8fr) minmax(0,1.2fr);gap:clamp(2rem,3.4vw,3rem);padding-bottom:clamp(2.2rem,3.8vw,3.4rem)}
/* head office column */
.foot address{font-style:normal;font-size:.96rem;line-height:1.65;color:var(--concrete)}
/* same unbreakable email as .enq-ct — see the note there */
.foot-ct{display:flex;align-items:center;gap:.6rem;margin-top:.9rem;font-size:.92rem;color:var(--concrete);transition:color .4s var(--ease);min-width:0;overflow-wrap:anywhere}
.foot-ct svg{width:15px;height:15px;flex:none;color:var(--tint-ink)}
.foot-ct:hover{color:var(--ivory)}
.foot-ct:hover svg{color:var(--tint-lt)}
.foot-top p{font-size:.96rem;color:var(--concrete);max-width:38ch;margin-top:1.3rem}
/* 11px tracked caps on the band — the brighter gold, not --tint-ink, so these
   read as crisply as the column links beneath them (11.0:1 rather than 6.0:1) */
.foot h2{font-family:var(--mono);font-size:.7rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--tint-lt);margin-bottom:1.4rem}
.foot ul{list-style:none;display:flex;flex-direction:column;gap:.75rem}
.foot ul a{font-size:.96rem;color:var(--concrete);transition:color .4s var(--ease),transform .4s var(--ease);display:inline-block}
.foot ul a:hover{color:var(--tint-ink);transform:translateX(4px)}
.wordmark{
  font-family:var(--display);font-weight:800;font-variation-settings:'opsz' 96,'wdth' 100;
  /* "ACURAGOLD" measures ~6.29em at these settings — divide the available
     width by that so the wordmark spans the page without ever clipping */
  font-size:calc((100vw - var(--rail) - 26px) / 6.45);
  line-height:.78;letter-spacing:-.05em;
  /* Flat gold — no gradient sweeping across the letters. The wordmark is
     one solid tone that simply brightens and blooms on hover. */
  color:var(--tint-ink);
  -webkit-text-stroke:0;
  opacity:.28;
  text-align:center;user-select:none;white-space:nowrap;padding-bottom:.06em;
  cursor:default;
  transition:opacity .6s var(--ease),color .6s var(--ease),filter .75s var(--ease);
}
.wordmark:hover{
  opacity:.9;
  color:var(--tint-deep);
  filter:drop-shadow(0 0 18px rgba(201,162,39,.45));
}
@media(prefers-reduced-motion:reduce){.wordmark{transition:none}}
.foot-bot{display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;padding:1.6rem 0;border-top:1px solid var(--rule)}
.foot-bot span{font-family:var(--mono);font-size:.65rem;font-weight:500;letter-spacing:.11em;text-transform:uppercase;color:var(--concrete-dim)}
/* Footer columns, all in one place — an earlier attempt put two of these
   above this rule, which silently lost. minmax(0,1fr) so the long address
   line cannot blow its own track out and skew the pair. */
@media(max-width:1080px){
  .foot-top{grid-template-columns:repeat(2,minmax(0,1fr))}
  .foot-top>div:first-child{grid-column:1/-1}
}
@media(max-width:560px){.foot-top{grid-template-columns:minmax(0,1fr)}}

/* ---------- trailing cursor ring (desktop pointer only) ---------- */
.ring{
  position:fixed;top:0;left:0;z-index:200;width:34px;height:34px;margin:-17px 0 0 -17px;
  border:1px solid rgba(201,162,39,.55);border-radius:50%;pointer-events:none;opacity:0;
  transition:opacity .4s,width .45s var(--ease),height .45s var(--ease),margin .45s var(--ease),background .45s var(--ease),border-color .45s var(--ease);
  will-change:transform;
}
.ring.live{opacity:1}
.ring.hot{width:58px;height:58px;margin:-29px 0 0 -29px;background:rgba(201,162,39,.12);border-color:rgba(242,223,160,.85)}
@media(hover:none),(pointer:coarse){.ring{display:none}}

/* ---------- reveal system (fail-safe: hidden only when JS runs) ---------- */
.rv{opacity:1}
.js .rv{opacity:0;transform:translateY(30px);transition:opacity 1.05s var(--ease),transform 1.15s var(--ease);transition-delay:var(--dl,0ms)}
.js .rv.in{opacity:1;transform:none}

/* line-by-line mask reveal for headlines.
   padding + equal negative margin keeps descenders (g, y, p) out of the clip */
.ln{display:block;overflow:hidden;padding-bottom:.14em;margin-bottom:-.14em}
.ln>span{display:block}
.js .ln>span{transform:translateY(115%);transition:transform 1.25s var(--ease);transition-delay:var(--dl,0ms)}
.js .in .ln>span,.js .ln.in>span{transform:none}

@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important;scroll-behavior:auto!important}
  .js .rv,.js .ln>span{opacity:1;transform:none}
  .grain,.ring{display:none}
}
