/* Elton — shared styles */
:root{--ink:#0B0C0A;--ink2:#141610;--paper:#EFEDE8;--conc:#C6C2B9;--mute:#8B877E;--line:#20211C;
 /* nav is position:fixed and out of flow, so anything it can overlay has to
    reserve its height explicitly: 18px pad + the logo + 18px pad. */
 --navh:calc(clamp(52px,6.5vw,68px) + 36px);
--r:clamp(38px,7vw,104px);--wm:#1C1F18}
*{box-sizing:border-box;margin:0;padding:0}
body{background:var(--ink);color:var(--paper);font:400 17px/1.65 "Helvetica Neue",Arial,sans-serif;
-webkit-font-smoothing:antialiased;overflow-x:hidden}
svg{display:block} a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}
.wrap{max-width:1300px;margin:0 auto;padding:0 32px}
.eyebrow{font-size:11px;letter-spacing:.32em;text-transform:uppercase;color:var(--mute);font-weight:700}

/* nav */
nav{position:fixed;inset:0 0 auto;z-index:60;display:flex;align-items:center;justify-content:space-between;
padding:18px 32px;background:linear-gradient(rgba(11,12,10,.95),rgba(11,12,10,0))}
nav .brand svg{height:clamp(52px,6.5vw,68px);width:auto;color:var(--paper)}
nav ul{display:flex;gap:30px;list-style:none;align-items:center}
nav ul a{font-size:12px;letter-spacing:.2em;text-transform:uppercase;color:#B7B3AA;transition:color .2s}
nav ul a:hover,nav ul a[aria-current]{color:var(--paper)}
.burger{display:none;width:34px;height:26px;position:relative;background:none;border:0;cursor:pointer}
.burger i{position:absolute;left:0;right:0;height:2px;background:var(--paper);transition:.3s}
.burger i:nth-child(1){top:4px} .burger i:nth-child(2){top:12px} .burger i:nth-child(3){top:20px}
.burger[aria-expanded="true"] i:nth-child(1){top:12px;transform:rotate(45deg)}
.burger[aria-expanded="true"] i:nth-child(2){opacity:0}
.burger[aria-expanded="true"] i:nth-child(3){top:12px;transform:rotate(-45deg)}
@media(max-width:860px){
 .burger{display:block}
 nav ul{position:fixed;inset:0;background:var(--ink);flex-direction:column;justify-content:center;
 gap:34px;opacity:0;pointer-events:none;transition:opacity .3s}
 nav ul.open{opacity:1;pointer-events:auto}
 nav ul a{font-size:18px;letter-spacing:.24em}
}

/* page header */
.phead{padding:180px 0 70px;border-bottom:1px solid var(--line)}
.phead h1{font-size:clamp(38px,7vw,84px);line-height:.96;font-weight:700;letter-spacing:-.035em;
text-transform:uppercase;margin:16px 0 22px}
.phead h1 .mu{color:var(--mute)}
.phead p.lede{color:var(--conc);max-width:52ch}


/* hero — same architecture as the division pages */
.hero{position:relative;min-height:100svh;display:flex;align-items:flex-end;padding:0 0 8svh;overflow:hidden}
.hero .film{position:absolute;inset:0;overflow:hidden;z-index:0}
.hero .film video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:1}
.hero .film .ph{position:absolute;inset:0;background:var(--ink2)}
.hero .film .ph svg{position:absolute;left:50%;translate:-50% 0;top:-20%;height:135%;width:auto}
.hero .film .ph svg{color:var(--wm)}
/* Flat .67 across the frame with a blend to .90 over the bottom tenth - the
   same treatment, and the same numbers, the homepage panes carry. The previous
   version was a foot blend only, leaving everything above 46% of the frame
   completely ungraded; that showed 67.7% of the clip against the panes' 30.6%,
   which is why the heroes read hot beside the homepage.

   .67 is what the h1 needs and no more. Measured against 16 sampled frames of
   each clip, through the object-fit:cover crop: the --paper lines (CONCRETE,
   FACADES, BUILDINGS) bottom out at 5.72:1 with none of the band under 4.5:1.
   The --conc .mu line reaches 3.77:1 at its brightest pixel and dips under
   4.5:1 across about 5% of its area on grc; at 104px bold the 3:1 large-text
   bar applies and it clears that everywhere. The two-tone h1 is deliberate.

   Going lighter would not help that line: both clips contain pixels at 255, so
   the binding figure is the pure-white bound - --paper needs .605, --conc .717.
   The fix for --conc is darker, not lighter, which is the wrong trade here. */
.hero .film:after{content:"";position:absolute;inset:0;z-index:2;
background:linear-gradient(to top,rgba(11,12,10,.9) 0%,rgba(11,12,10,.67) 10%,
 rgba(11,12,10,.67) 100%)}

/* Shadows on the type itself. With the wash gone these are the only thing
   standing between the copy and the footage, so they are heavier and tighter
   than before: a dense short shadow to cut a hard edge on the glyph, and a
   wide soft one to drop the local area behind it.

   They do NOT count toward a WCAG ratio - that is computed against the
   background colour, and a shadow is not the background. They are doing
   perceptual work only. Measured against a pure-white frame, everything above
   the blend now sits at 1.06:1 (--paper) to 1.42:1 (--conc); the numbers are
   real and they are bad, and the shadows do not move them. This is a knowing
   trade of the measurement for the picture - see the report, not this comment,
   for the per-element figures. */
/* Hero-only colour lift. --mute (#8B877E) needs a .913 scrim over a white
   frame to reach 4.5:1, which no soft gradient can give without erasing the
   footage, so over film it is replaced by --conc (#C6C2B9). This also settles
   the eyebrow inconsistency: every hero eyebrow is now --conc, where projects,
   about and contact were --mute and grc and facades were not. Scoped to .hero
   and specific enough (0-3-0) to beat the page-level .eyebrow rules; the
   palette is untouched everywhere else. */
.hero .inner .eyebrow,.hero h1 .mu{color:var(--conc)}

.hero .inner .eyebrow{text-shadow:0 1px 2px rgba(11,12,10,.95),0 0 6px rgba(11,12,10,.9),
 0 0 20px rgba(11,12,10,.75)}
.hero h1{text-shadow:0 2px 4px rgba(11,12,10,.92),0 0 12px rgba(11,12,10,.85),
 0 2px 40px rgba(11,12,10,.7)}
.hero p.lede{text-shadow:0 1px 3px rgba(11,12,10,.95),0 0 8px rgba(11,12,10,.88),
 0 0 26px rgba(11,12,10,.65)}
.hero .scroll-cue{text-shadow:0 1px 3px rgba(11,12,10,.9),0 0 10px rgba(11,12,10,.7)}
.hero .inner{position:relative;z-index:3;max-width:1300px;margin:0 auto;padding:0 32px;width:100%}
h1{font-size:clamp(42px,7.6vw,104px);line-height:.94;font-weight:700;letter-spacing:-.035em;
text-transform:uppercase;margin:18px 0 26px}
h1 span{display:block} h1 .mu{color:var(--mute)}
.hero p.lede{color:var(--conc);max-width:48ch}

/* numbered rows */
.caps{padding:110px 0 40px}
/* Sub-line under a section kicker. Body type, not kicker type: nine words at
   11px with .32em tracking ran to three lines at 380px, which is what put the
   sentence down here instead. */
.caps-sub{color:var(--conc);max-width:56ch;margin:0 0 34px}
.cap{display:grid;grid-template-columns:70px 1fr auto;gap:26px;align-items:baseline;
padding:32px 0;border-top:1px solid var(--line)}
.cap:last-child{border-bottom:1px solid var(--line)}
.cap .n{font-size:12px;letter-spacing:.2em;color:var(--mute)}
.cap h3{font-size:clamp(20px,2.7vw,34px);font-weight:700;letter-spacing:-.02em;text-transform:uppercase}
.cap p{color:var(--mute);font-size:15px;justify-self:end;text-align:right;max-width:34ch}
/* Narrow: the caption drops below its heading, in the same column, instead of
   being hidden - four captions a page were invisible on a phone, including the
   one carrying the manufacture correction. grid-column:2 is what puts it under
   the heading rather than under the number. */
@media(max-width:760px){
 .cap{grid-template-columns:48px 1fr;gap:14px}
 .cap p{display:block;grid-column:2;justify-self:start;text-align:left;max-width:none;margin-top:8px}
}

/* statement */
.statement{padding:120px 0;border-top:1px solid var(--line)}
.statement p{font-size:clamp(22px,3.4vw,42px);line-height:1.25;font-weight:300;letter-spacing:-.01em}
.statement span{color:var(--mute)}

/* buttons */
.cta{display:inline-block;padding:18px 40px;border:1px solid var(--paper);font-size:12px;
letter-spacing:.24em;text-transform:uppercase;transition:.25s;cursor:pointer;background:none;color:var(--paper)}
.cta:hover{background:var(--paper);color:var(--ink)}

/* cards */
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:22px}
.card{background:var(--ink2);border:1px solid var(--line);overflow:hidden;border-radius:0 0 var(--r) 0}
.card .thumb{aspect-ratio:16/10;background:#191B15;display:grid;place-items:center}
.card .thumb span{color:#3A3D34;font-size:11px;letter-spacing:.22em}
.card .meta{padding:20px 22px 24px}
.card h3{font-size:15px;letter-spacing:.08em;font-weight:700;margin-bottom:6px}
.card p{font-size:13px;color:var(--mute)}

/* reveal */
.r{opacity:0;transform:translateY(24px);transition:opacity .8s cubic-bezier(.2,.7,.3,1),transform .8s cubic-bezier(.2,.7,.3,1)}
.r.in{opacity:1;transform:none}
@media(prefers-reduced-motion:reduce){.r{opacity:1;transform:none}}

/* footer */
footer.site{border-top:1px solid var(--line);padding:70px 0 44px;margin-top:110px}
footer.site .cols{display:grid;grid-template-columns:1.4fr 1fr 1fr;gap:40px}
/* Narrow: the logo and address keep the full width, and the two link lists sit
   side by side under them rather than continuing one long stacked run. The
   first child spans both tracks; the other two take one each. Matches the
   homepage, which carries the same rule in its own stylesheet. */
@media(max-width:760px){
 footer.site .cols{grid-template-columns:1fr 1fr;gap:30px 22px}
 footer.site .cols>div:first-child{grid-column:1/-1}
}
/* At 360 a 22px gutter leaves 137px a column and the opening-hours line needs
   139.6, so it wrapped to "...9am to" / "5pm". Trimming the gutter to 14 clears
   it. Scoped to the footer grid, so no other section's spacing moves. */
@media(max-width:380px){footer.site .cols{column-gap:14px}}
footer.site svg{height:65px;width:auto;margin-bottom:20px;color:var(--paper)}
footer.site p,footer.site a{font-size:13.5px;line-height:1.9;color:var(--mute)}
footer.site a:hover{color:var(--paper)}
footer.site h4{font-size:11px;letter-spacing:.3em;text-transform:uppercase;color:var(--paper);
font-weight:700;margin-bottom:14px}
footer.site .base{margin-top:46px;padding-top:22px;border-top:1px solid var(--line);
display:flex;justify-content:space-between;gap:20px;flex-wrap:wrap;font-size:12px;color:#55534E;letter-spacing:.08em}

/* ==========================================================================
   SCROLL AFFORDANCE
   Persistent "Scroll" cue, so the full-height hero does not read as the
   end of the page.
   ========================================================================== */

/* --- 1. HERO HEIGHT -------------------------------------------------------
   Full viewport on every page, set once in the .hero rule above.

   This reverses an earlier decision. The hero used to default to 78svh so that
   ~22vh of the next section showed below the fold as a scroll affordance, with
   grc and facades opting out to 100svh in their own <style> blocks. In practice
   only those two ever got the full-height treatment and the other three looked
   truncated beside them, so the peek was dropped rather than kept in one place
   and broken in two. The scroll cue below is what signals there is more page.

   min-height, not height, so tall content and short viewports both grow rather
   than overflowing. Padding is set by header.hero further down, which
   out-specifies this rule and is therefore the only place it is worth
   changing. */

/* The cue occupies 8svh + ~73px at the foot of the hero (73px tall, lifted
   8svh clear of the bottom edge).
   .hero's bottom padding is only 8-9svh, which on a short viewport is less
   than that and lets the cue collide with the hero copy. Floor the padding so
   there is always clearance. Same 0-1-1 specificity note as above: this also
   has to beat the padding shorthand in the grc/facades <style> blocks. */
/* The hero is a flex box with align-items:flex-end, so .inner sits on the
   bottom edge and rises as it grows. With no top padding a tall heading pushed
   it up under the fixed nav - the eyebrow disappeared entirely and the logo
   landed on the first line of the h1. Worst on about.html, which failed at
   1366x768. Reserving the nav height plus 28px of air makes the collision
   impossible: .inner can never start above 132px, whatever the copy or the
   viewport does. min-height is a floor, not a cap, so a hero that no longer
   fits simply grows rather than overflowing upward. */
header.hero{padding-top:calc(var(--navh) + 28px);padding-bottom:max(8svh,175px)}

/* --- 2. SCROLL CUE --------------------------------------------------------
   Letterspaced label over a thin vertical rule, pinned to the bottom centre
   of the hero. Type is the site's existing small-caps treatment, copied from
   .eyebrow (11px / .32em / uppercase / 700 / --mute) rather than a new one.

   .hero has overflow:hidden and bottom padding of 8-9svh holding .inner, so
   the cue is kept short and inset to sit clear of the hero copy.
   Centring uses the `translate` property so the `transform` property stays
   free for the drift animation. */
.scroll-cue{position:absolute;left:50%;bottom:8svh;z-index:4;translate:-50% 0;
 display:flex;flex-direction:column;align-items:center;gap:11px;
 font-size:12px;letter-spacing:.32em;text-transform:uppercase;font-weight:700;color:var(--conc);
 pointer-events:none;opacity:1;transition:opacity .45s ease;
 animation:cue-drift 2s ease-in-out infinite}
.scroll-cue i{display:block;width:1px;height:40px;background:currentColor;opacity:.6}
/* Set by the per-page scroll listener once past ~15vh. */
.scroll-cue.gone{opacity:0}

@keyframes cue-drift{
 0%,100%{transform:translateY(0)}
 50%{transform:translateY(6px)}
}

/* --- 3. REDUCED MOTION ----------------------------------------------------
   No drift, no fade. The cue simply stays put and stays visible. */
@media (prefers-reduced-motion:reduce){
 .scroll-cue{animation:none;transition:none}
 .scroll-cue.gone{opacity:1}
}
