/* ════════════════════════════════════════════════════════════════════════
   McPherson Coatings — UI layer
   Everything the v5 handover pack does NOT provide. The handover CSS
   (mcc.css) ships 0 media queries, 0 keyframes and 0 transitions, so this
   file owns:

     1. motion tokens + the scroll-reveal system
     2. signature brand animations (trowel sweep, hairline draw, mask
        reveal, watermark drift, count-up, marquee)
     3. header chrome — sticky/shrink, scroll progress, mobile menu
     4. hover/focus states
     5. the entire responsive cascade
     6. prefers-reduced-motion + print

   Animation vocabulary matches the main McPherson Painting module
   (data-anim / data-delay) so the two codebases stay legible to the same
   developer, then extends it.
   ════════════════════════════════════════════════════════════════════════ */

:root{
  --ease:      cubic-bezier(.16,1,.3,1);      /* same curve as layouttwo/common.css */
  --ease-out:  cubic-bezier(.22,.61,.36,1);
  --ease-in:   cubic-bezier(.4,0,1,1);
  --ease-back: cubic-bezier(.34,1.56,.64,1);
  --t-fast:.28s; --t-med:.55s; --t-slow:.9s; --t-xslow:1.4s;
  --hdr-h:92px;
}

/* ─────────────────────────────────────────── 1. SCROLL REVEAL
   TWO RULES THIS SECTION MUST NEVER BREAK:

   1. Nothing is hidden unless mcc.js is confirmed running. The hidden state
      is scoped to `html.mcc-anim`, a class the script adds only once it has
      successfully installed the observer, and removes again if it throws.
      Without it every [data-anim] element renders normally. A CSS-only or
      broken-JS visit therefore shows the full page, never a blank one.

   2. No element gets `filter` and `clip-path` at the same time. That
      combination blanked every .fig-box and .devpanel in Chrome: the old
      `[data-anim].is-in` rule applied `filter:blur(0)` to everything,
      including the clip variant, so images occupied their space but painted
      nothing. `filter` is now scoped to the blur variant alone, and the
      image reveal uses opacity + scale instead of clip-path. */

[data-anim]{transition:opacity var(--t-slow) var(--ease),transform var(--t-slow) var(--ease)}

.mcc-anim [data-anim]:not(.is-in){opacity:0}
/* 34px, not the 52px the painting module uses. `transform` does not affect
   layout, so a large offset paints an element well outside its own box —
   at 52px a mono eyebrow label landed on top of the <h1> directly beneath it
   for the length of the transition. Small labels travel less again. */
.mcc-anim [data-anim="up"]:not(.is-in)    {transform:translate3d(0,34px,0)}
.mcc-anim .lbl[data-anim="up"]:not(.is-in),
.mcc-anim .credit[data-anim="up"]:not(.is-in),
.mcc-anim .meta[data-anim="up"]:not(.is-in){transform:translate3d(0,14px,0)}
.mcc-anim [data-anim="down"]:not(.is-in)  {transform:translate3d(0,-40px,0)}
.mcc-anim [data-anim="left"]:not(.is-in)  {transform:translate3d(-64px,0,0)}
.mcc-anim [data-anim="right"]:not(.is-in) {transform:translate3d(64px,0,0)}
.mcc-anim [data-anim="scale"]:not(.is-in) {transform:translate3d(0,28px,0) scale3d(.94,.94,1)}
.mcc-anim [data-anim="fade"]:not(.is-in)  {transform:translate3d(0,12px,0)}
/* blur is the ONLY variant allowed to use filter */
.mcc-anim [data-anim="blur"]:not(.is-in)  {transform:translate3d(0,22px,0);filter:blur(9px)}
[data-anim="blur"]{transition:opacity var(--t-slow) var(--ease),transform var(--t-slow) var(--ease),filter var(--t-slow) var(--ease)}
[data-anim="blur"].is-in{filter:blur(0)}
/* clip: the finish "goes on" — reads as laid-on depth, done with scale so it
   never needs clip-path. Paired with the .fig-box img scale-down and the
   trowel sweep below. */
.mcc-anim [data-anim="clip"]:not(.is-in),
.mcc-anim [data-anim="clip-l"]:not(.is-in){transform:translate3d(0,26px,0) scale3d(1.015,1.015,1)}
[data-anim="clip"],[data-anim="clip-l"]{transition:opacity 1.15s var(--ease),transform 1.15s var(--ease)}

[data-anim].is-in{opacity:1;transform:translate3d(0,0,0) scale3d(1,1,1)}

[data-delay="1"]{transition-delay:.09s}[data-delay="2"]{transition-delay:.18s}
[data-delay="3"]{transition-delay:.27s}[data-delay="4"]{transition-delay:.36s}
[data-delay="5"]{transition-delay:.45s}[data-delay="6"]{transition-delay:.54s}
[data-delay="7"]{transition-delay:.63s}[data-delay="8"]{transition-delay:.72s}
/* JS-assigned stagger (data-stagger on the parent) */
[style*="--sd"]{transition-delay:calc(var(--sd) * 70ms)}

/* ─────────────────────────────────────────── 2. SIGNATURE ANIMATIONS */

/* 2.1 hairline in .seclab draws out to the gutter.
   Every "hidden until revealed" state below is scoped to .mcc-anim for the
   same reason as section 1: without the script, it must render finished. */
.seclab .ln{transform-origin:left center;transition:transform 1.1s var(--ease) .1s}
.mcc-anim .seclab:not(.is-in) .ln{transform:scaleX(0)}
.seclab.is-in .ln,.is-in .seclab .ln{transform:scaleX(1)}

/* 2.2 rules / steps / kv / faq rows — hairline sweep then content */
.rules>div,.step,.kv>div,.faq>div{position:relative}
.rules>div::before,.step::before,.faq>div::before{content:"";position:absolute;left:0;right:0;height:1px;
  background:var(--orange);transform:scaleX(0);transform-origin:left center;
  transition:transform .85s var(--ease)}
.rules>div::before,.faq>div::before{bottom:-1px}
.step::before{top:-1px}
.rules>div.is-in::before,.step.is-in::before,.faq>div.is-in::before{transform:scaleX(1)}

/* 2.3 trowel sweep — a burnish highlight crosses the image once on reveal */
/* NB: .swatch::after and .ph::after already carry the handover's caption text,
   so the sweep uses .fig-box::after and .hero-img::before only - never those two. */
.fig-box,.mask-box,.hero-img,.swatch,.ph{position:relative;overflow:hidden}
.fig-box::after,.hero-img::before{content:"";position:absolute;inset:0;z-index:3;
  background:linear-gradient(104deg,transparent 38%,rgba(255,255,255,.30) 50%,transparent 62%);
  transform:translate3d(-120%,0,0);pointer-events:none}
.fig-box.is-in::after,.hero-img.is-in::before{animation:mccSweep 1.5s var(--ease) .25s 1 both}
@keyframes mccSweep{0%{transform:translate3d(-120%,0,0)}100%{transform:translate3d(120%,0,0)}}

/* 2.4 images settle from a slow scale — reads as depth, not motion */
.fig-box img,.proj .fig-box img{transition:transform 1.6s var(--ease)}
.mcc-anim .fig-box:not(.is-in) img{transform:scale(1.07)}
.fig-box.is-in img{transform:scale(1)}

/* 2.5 hero — headline rises word by word, photo pulls back */
/* Hero headline words.
   Driven by a CSS animation with fill-mode `both`, NOT by a JS-toggled
   class: mcc.js only splits the text and sets each word's animation-delay.
   That matters because a transition needs something to flip it, and if that
   callback never fires (throttled frame loop, headless capture, background
   tab) the heading would stay invisible. An animation runs and settles on
   its own, so the words always end up on screen. */
@keyframes mccWordIn{from{opacity:0;transform:translate3d(0,.7em,0)}to{opacity:1;transform:none}}
.hero-copy .w{display:inline-block}
.mcc-anim .hero-copy .w{animation:mccWordIn .8s var(--ease) both}
.hero-img img{animation:mccHeroZoom 14s var(--ease-out) both}
@keyframes mccHeroZoom{from{transform:scale(1.14)}to{transform:scale(1)}}
.hero-credit{opacity:0;animation:mccFadeIn .9s var(--ease) 1.1s both}

/* 2.6 brandmark watermark drifts on scroll (JS sets --p 0→1) */
.wmark{transform:translateY(calc(-50% + (var(--p,0) * 42px))) rotate(calc(var(--p,0) * 2.5deg));
  transition:transform .2s linear}

/* 2.7 count-up numerals */
.cred b,.datum .v,.stat-row .v{font-variant-numeric:tabular-nums}
.cred b{transition:opacity .7s var(--ease),transform .7s var(--ease)}
.cred span{transition:opacity .7s var(--ease) .18s}
.mcc-anim .cred:not(.is-in) b{opacity:0;transform:translate3d(0,18px,0)}
.mcc-anim .cred:not(.is-in) span{opacity:0}
.cred.is-in b{opacity:1;transform:none}
.cred.is-in span{opacity:1}
/* the vertical divider grows */
.cred{position:relative}
.cred::after{content:"";position:absolute;right:-1px;top:50%;width:1px;height:0;background:var(--orange);
  transform:translateY(-50%);transition:height .9s var(--ease) .2s}
.cred.is-in:not(:last-child)::after{height:56%}

/* 2.8 brandmark mask box — the mark scales in over the photo.
   Default is the FINISHED state (84%), so a no-JS visit shows the masked
   image rather than nothing. Only .mcc-anim starts it at 0%. */
.mask-box img{transition:-webkit-mask-size 1.5s var(--ease),mask-size 1.5s var(--ease),transform 1.5s var(--ease);
  -webkit-mask-size:84% auto;mask-size:84% auto}
.mcc-anim .mask-box:not(.is-in) img{-webkit-mask-size:0% auto;mask-size:0% auto;transform:scale(1.08)}
.mask-box.is-in img{-webkit-mask-size:84% auto;mask-size:84% auto;transform:scale(1)}

/* 2.9 logo strip marquee (only when it overflows; JS adds .run) */
.logos.run{flex-wrap:nowrap;overflow:hidden;mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent)}
.logos.run .track{display:flex;gap:56px;align-items:center;animation:mccMarquee 26s linear infinite}
.logos.run:hover .track{animation-play-state:paused}
@keyframes mccMarquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}

/* 2.10 tiles — stagger in, then lift */
.tile{transition:transform var(--t-med) var(--ease),box-shadow var(--t-med) var(--ease),
  border-color var(--t-med) var(--ease),background var(--t-med) var(--ease)}
.tile:hover{transform:translateY(-6px);box-shadow:0 18px 46px -18px rgba(35,30,19,.30);border-color:#B4AEA2}
.dark .tile:hover{border-color:var(--on-dark-2);box-shadow:0 18px 46px -18px rgba(0,0,0,.6)}
.tile.on:hover{box-shadow:0 20px 50px -18px rgba(240,75,35,.55)}
.tile .arrow{transition:transform var(--t-fast) var(--ease),letter-spacing var(--t-fast) var(--ease)}
.tile:hover .arrow{transform:translateX(6px)}
/* the featured (orange) tile breathes once in view */
.tile.on.is-in{animation:mccBreathe 3.6s var(--ease-out) .5s 1 both}
@keyframes mccBreathe{0%,100%{box-shadow:0 0 0 0 rgba(240,75,35,0)}
  45%{box-shadow:0 0 0 14px rgba(240,75,35,.10)}}

/* 2.11 buttons */
.btn{position:relative;overflow:hidden;transition:transform var(--t-fast) var(--ease),
  background var(--t-fast) var(--ease),color var(--t-fast) var(--ease),border-color var(--t-fast) var(--ease)}
.btn::before{content:"";position:absolute;inset:0;background:currentColor;opacity:0;
  transform:translate3d(0,101%,0);transition:transform var(--t-med) var(--ease),opacity var(--t-med) var(--ease)}
.btn:hover{transform:translateY(-2px)}
.btn-s:hover{border-color:var(--orange);color:var(--orange)}
.btn-d:hover{border-color:var(--on-dark);color:#fff}
.btn-w:hover{border-color:var(--on-warm);color:#fff}
.cta .btn:active{transform:translateY(0)}
.arrow{transition:transform var(--t-fast) var(--ease)}
a:hover>.arrow,.arrow:hover{transform:translateX(5px)}

/* 2.12 links + nav underline */
.nav a{position:relative;transition:color var(--t-fast) var(--ease)}
.nav a::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:1px;background:var(--orange-dark);
  transform:scaleX(0);transform-origin:left center;transition:transform var(--t-med) var(--ease)}
.nav a:hover{color:var(--on-dark)}
.nav a:hover::after,.nav a.on::after{transform:scaleX(1)}
.ftr li{transition:color var(--t-fast),transform var(--t-fast) var(--ease)}
.ftr li:hover{color:var(--on-dark)}
.ftr a:hover li{transform:translateX(3px)}
.dl a{transition:padding-left var(--t-med) var(--ease),border-color var(--t-fast)}
.dl a:hover{padding-left:10px;border-bottom-color:var(--orange)}
.svc{transition:background var(--t-med) var(--ease)}
.svc:hover{background:rgba(240,75,35,.03)}
.svc:hover .arrow{transform:translateX(6px)}
/* chips are <label> + checkbox so they work with JS off. :has() gives the
   selected state natively; mcc.js also toggles .on for older engines. */
/* No indicator dot: the handover's chip is a plain pill and the orange fill
   already reads unambiguously as selected. A ::before circle was added here
   and has been removed — it read as a radio affordance even on the
   multi-select capability chips, and it is not the designer's chip. */
.chip{transition:all var(--t-fast) var(--ease);cursor:pointer;user-select:none;
  display:inline-flex;align-items:center}
.chip input[type=checkbox],.chip input[type=radio]{position:absolute;opacity:0;width:0;height:0;margin:0}
.chip:hover{border-color:var(--orange);color:var(--orange)}
.chip:has(input:checked){border-color:var(--orange);color:#fff;background:var(--orange)}
.chip.on:hover,.chip:has(input:checked):hover{color:#fff}
.chip:has(input:focus-visible){outline:2px solid var(--orange);outline-offset:3px}
.badge{transition:transform var(--t-med) var(--ease),border-color var(--t-fast)}
.badge:hover{transform:translateY(-3px);border-color:var(--orange)}
.proj{transition:transform var(--t-med) var(--ease)}
.proj:hover{transform:translateY(-5px)}
.swatch{transition:transform var(--t-med) var(--ease),border-radius var(--t-med) var(--ease)}
.swatch:hover{transform:scale(1.03)}

@keyframes mccFadeIn{from{opacity:0}to{opacity:1}}

/* ─────────────────────────────────────────── 2.13 BRANDED DEVICE PANEL
   Used by parts/device.phtml wherever McPherson's own photography is still to
   be shot. Brand guide p.13 sanctions the brandmark as a graphic device, so a
   pending shot reads as a designed panel instead of a broken grey image. */
.devpanel{position:relative;overflow:hidden;border-radius:var(--r-lg);display:grid;place-items:center;
  isolation:isolate}
.devpanel.dev-flat{border-radius:0}
.dev-brown {background:linear-gradient(152deg,#2C2619 0%,var(--brown) 52%,var(--brown-deep) 100%)}
.dev-warm  {background:linear-gradient(152deg,var(--warm-lift) 0%,var(--warm) 60%,#4F4A40 100%)}
.dev-orange{background:linear-gradient(152deg,#F46A47 0%,var(--orange) 55%,#C93C18 100%)}
.dev-light {background:linear-gradient(152deg,#E6E4E1 0%,var(--light) 55%,#C3C0BB 100%)}
/* a faint trowel grain so the panel has surface, like the finishes do */
.devpanel::before{content:"";position:absolute;inset:0;z-index:0;opacity:.5;
  background:repeating-linear-gradient(112deg,rgba(255,255,255,.05) 0 3px,transparent 3px 9px),
             radial-gradient(120% 90% at 26% 8%,rgba(255,255,255,.14),rgba(255,255,255,0) 62%)}
.dev-light::before{background:repeating-linear-gradient(112deg,rgba(35,30,19,.04) 0 3px,transparent 3px 9px)}
.dev-mark{position:relative;z-index:1;display:block;width:100%;text-align:center;opacity:.42;
  transition:transform 1.5s var(--ease),opacity 1.5s var(--ease)}
.dev-mark svg{display:inline-block;height:auto}
.mcc-anim .devpanel:not(.is-in) .dev-mark{opacity:.30;transform:scale(.94)}
.devpanel.is-in .dev-mark{transform:scale(1);opacity:.42}
.dev-cap{position:absolute;left:18px;right:18px;bottom:14px;z-index:2;font-family:var(--mono);
  font-size:9.5px;letter-spacing:.11em;text-transform:uppercase;line-height:1.6;color:rgba(237,234,228,.72)}
.dev-light .dev-cap{color:rgba(35,30,19,.6)}
.dev-cap i{display:block;font-style:normal;color:var(--orange-dark);margin-top:3px}
.dev-light .dev-cap i,.dev-orange .dev-cap i{color:rgba(255,255,255,.85)}

/* the handover's own .ph placeholder, made to read as deliberate too */
.ph{position:relative}
.ph::before{content:"";position:absolute;inset:0;
  background:radial-gradient(120% 90% at 26% 8%,rgba(255,255,255,.16),rgba(255,255,255,0) 62%)}
.ph[data-cap]::after{padding-right:82px}

/* ─────────────────────────────────────────── 2.14 HANDOVER LAYOUT FIXES
   The v5 pack is desktop-only, so a few of its rules only misbehave below
   ~900px. Fixed here rather than in mcc.css, which stays a verbatim copy. */

/* No element may scroll the page sideways. `clip` rather than `hidden`
   because clip does not create a scroll container, so the sticky header
   still sticks to the viewport. This is the backstop; the actual causes are
   fixed below. */
html{overflow-x:clip}
body{overflow-x:clip;max-width:100%}

/* The decorative brandmark sits at right:-6% by design, which pushed the
   document 30px wider than the viewport on every page carrying it (measured
   with _deploy/scripts/find-overflow.php). .closing already clipped it; the
   dark feature band and the 404/error heroes did not. */
.rel:has(> .wmark){overflow:hidden}
.closing,.band{overflow:hidden}

/* The closing CTA band lives in the layout now, so it is a sibling of <main>,
   not of the page's last section. That silently broke the handover's
   `.dark + .closing` / `.warm + .closing` / `.light + .closing` rules — they
   can never match through <main>, so EVERY page was getting var(--sec) of
   paper above the dark band, including the pages that end on a coloured
   full-bleed ground (/acoustics ends warm, /projects ends on a bleed band).
   The spacing decision moves to the last element inside <main>: paper
   sections keep the breathing room the design intends, coloured grounds sit
   flush against the band. */
.closing{margin-top:0}
main > *:last-child:not(.dark):not(.warm):not(.light):not(.band):not(.closing)
  {padding-bottom:var(--sec)}

/* .ftr-in is `class="shell ftr-in"`, and mcc.css declares
   `.ftr-in{padding:72px 0 32px}` AFTER .shell — a shorthand, so it reset
   .shell's left/right gutters to 0. Invisible on desktop (the shell is
   centred inside a wider viewport) but on mobile the whole footer ran edge
   to edge with no margin. Restore the gutters without touching the
   vertical rhythm. */
.ftr-in{padding-left:var(--pad);padding-right:var(--pad)}

/* Long unbreakable strings — email addresses, ABNs, mono runs — must break
   rather than push the layout wider. */
.ftr .mn,.ftr .contact,.rules p,.rules b,.body,.lede,.credit,.dl .t,.kv,.cap,
.step p,.faq p,.proj p,.tile p{overflow-wrap:anywhere}

/* Desktop column counts that the handover set with inline style attributes.
   Inline styles beat media queries, so those pages never collapsed to one
   column on mobile. Declared here as classes (BEFORE the responsive section
   below, so the breakpoints still win) and the inline styles removed from
   the views. */
.projs.cols2{grid-template-columns:repeat(2,minmax(0,1fr))}
.grid2.form-split{grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr)}

/* Full-bleed editorial band. mcc.css defines .bleed and .bleed .cap-box but
   the handover never used the component, so it has no img rule — the base
   `img{max-width:100%}` capped the photograph at its natural 1600px and
   letterboxed it, leaving bare paper to the right on wider screens. Give the
   band a ratio and let the image cover it, so it is full width at any size
   and crops taller on narrow screens instead of becoming a slit. */
.bleed{aspect-ratio:1600/685}
.bleed img{width:100%;height:100%;object-fit:cover;display:block}

/* On narrow screens the caption box is taller than a 21:9 band, and because
   .bleed clips, its heading was being cut off. Take the box out of absolute
   positioning below 900px and let it sit under the photograph — then it can
   never be clipped no matter how long the copy is. */
@media (max-width:900px){
  .bleed{aspect-ratio:auto;overflow:visible}
  .bleed img{height:auto;aspect-ratio:16/9;border-radius:0}
  .bleed .cap-box{position:static;left:auto;right:auto;bottom:auto;max-width:none;
    border-radius:0;margin:0;padding:26px var(--pad) 30px}
}
@media (max-width:620px){ .bleed img{aspect-ratio:4/3} }

/* ── COLOUR — the client's exact specification (REV1, COLOURS.md) ──────────
   Phase 2e computed its own AA-safe values here. REV1 supplies the exact
   codes the client wants used throughout, so every token now comes from
   mcc.css (= the v6 site.css) and this block only resolves small orange
   TEXT per ground, using the values in COLOURS.md §6 "Eyebrow label":

       paper #CC401E · Deep Brown #FF6242 · Warm Grey #FFD9CF · Light Grey #AA3519

   --ink-3 (#6F6A5E), --on-warm-2 (#E4DED4) and the Light Grey scope
   (--ink-2 #655E53, --ink-3 #5F5A4E, --orange-ink #AA3519, --rule #BEB8AC)
   are all set by mcc.css itself — do not restate them here.

   The primary button is back to the brand #F04B23 with the #D93F1B hover
   named in COLOURS.md §6, and control borders are the designer's. Both were
   darkened in phase 2e for AA; the client's spec supersedes that — see
   _deploy/CHANGELOG-mcc-rev1.md §2. */

:root{--orange-text:var(--orange-ink)}      /* #CC401E, 4.50:1 on paper */
.dark{--orange-text:var(--orange-dark)}     /* #FF6242, 5.59:1 on brown */
.warm{--orange-text:#FFD9CF}                /* 4.62:1 on warm grey      */
.light{--orange-text:#AA3519}               /* 4.61:1 on light grey     */

/* mcc.css already points these at --orange-ink; routing them through
   --orange-text lets one token re-key per ground (.go and .hi are ours). */
.eyebrow,.arrow,.go,.headrow a,.step .n,.flag,.hi,.faq .pm{color:var(--orange-text)}
.flag{border-color:var(--orange-text)}

.btn-p:hover{background:#D93F1B;border-color:#D93F1B}
/* selected states keep the brand orange */
.chip:has(input:checked),.chip.on{border-color:var(--orange)}

/* ── Heading levels vs heading LOOK ──────────────────────────────────────
   Several headings were promoted so the document outline has no skipped
   levels (h1 -> h3 was reported on /projects, /acoustics/products and the
   404; every page skipped h2 -> h4 at the footer). The element changed, the
   appearance must not: these rules restate the h3 / .ftr h4 typography from
   mcc.css for the promoted elements.
   `h1,h2,h3,h4` in mcc.css already sets opsz 32, margin 0 and text-wrap. */
.tile-t,.proj-t{font-size:19px;font-weight:500;letter-spacing:-.012em;line-height:1.3}
.tile .tile-t{margin-top:16px}
.proj .proj-t{margin-top:7px}
/* the bleed band caption is a figure caption, not a section heading */
.bleed .cap-box .cap-t{font-size:19px;font-weight:500;letter-spacing:-.012em;
  line-height:1.3;color:var(--on-dark);font-variation-settings:"opsz" 32;margin:0}
/* footer column labels (were .ftr h4) */
.ftr .ftr-h{font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--on-dark);font-weight:500;margin-bottom:16px;font-variation-settings:normal}
.ftr .ftr-h.gap{margin-top:28px}

/* /projects filter chips. They are real <button>s now (they actually filter),
   so the UA button styling is reset back to the handover's chip look. A chip
   whose value would return no projects is dimmed and unclickable rather than
   letting someone select an empty result. */
button.chip{font-family:inherit;font-size:13.5px;background:none;cursor:pointer;
  -webkit-appearance:none;appearance:none;line-height:normal}
button.chip.on{background:var(--orange);border-color:var(--orange);color:#fff}
.chip-off{opacity:.34;cursor:not-allowed}
.chip-off:hover{border-color:var(--rule);color:var(--ink-2)}
.proj[hidden]{display:none}
#projcount{color:var(--ink-3)}

/* ─────────────────────────────────────────── 2.15 COMING-SOON PAGE
   Shown while mcc.settings.comingsoon = 1. Same tokens and type as the rest
   of the site so it reads as the brand, not as a placeholder. */
.cs{padding-top:0;min-height:100svh;display:flex;align-items:center;overflow:hidden}
.cs-in{padding-top:72px;padding-bottom:72px;width:100%}
.cs-wmark{right:-14%;opacity:.05}
.cs-brand{display:flex;align-items:center;gap:14px;margin-bottom:56px}
.cs-brand .wm{font-size:19px}
.cs-eyebrow{margin-bottom:18px}
.cs-h1{font-size:clamp(34px,5.6vw,64px);max-width:15ch}
.cs-lede{max-width:54ch;margin-top:22px}
.cs-cta{margin-top:34px}
.cs-what{margin-top:64px;padding-top:26px;border-top:1px solid var(--dark-rule);max-width:62ch}
.cs-what-lbl{color:var(--on-dark-2);margin-bottom:14px}
.cs-list{display:grid;gap:7px}
.cs-list li{font-size:15.5px;color:var(--on-dark-2);line-height:1.5;position:relative;padding-left:18px}
.cs-list li::before{content:"";position:absolute;left:0;top:.62em;width:7px;height:1px;background:var(--orange-dark)}
.cs-badges{margin-top:44px}
.cs-badges .accred{gap:14px}
.cs-foot{margin-top:52px;font-size:11.5px;line-height:1.9;color:var(--on-dark-2);
  letter-spacing:.05em;text-transform:uppercase}
.cs-foot a{color:var(--on-dark);border-bottom:1px solid var(--dark-rule)}
.cs-foot a:hover{border-bottom-color:var(--orange-dark)}
@media (max-width:900px){
  .cs{min-height:0}
  .cs-in{padding-top:52px;padding-bottom:56px}
  .cs-brand{margin-bottom:38px}
  .cs-what{margin-top:44px}
  .cs-wmark{width:420px!important;right:-28%;opacity:.04}
}
@media (max-width:620px){
  .cs-cta .btn{flex:1 1 100%;text-align:center}
  .cs-badges .accred{flex-direction:column;align-items:stretch}
}

/* ─────────────────────────────────────────── 2.16 PREVIEW BAR
   Only present while previewing the real site behind the coming-soon gate.
   Sticks above the site header (which is offset by --pvbar-h to match) so
   the way out is always one click away, and so it is never ambiguous whether
   you are seeing the public view or the private one. */
:root{--pvbar-h:38px}
.pvbar{position:sticky;top:0;z-index:90;height:var(--pvbar-h);
  background:var(--orange);color:#fff;
  box-shadow:0 1px 0 0 rgba(0,0,0,.18)}
.pvbar-in{max-width:var(--shell);margin:0 auto;padding:0 var(--pad);height:100%;
  display:flex;align-items:center;gap:12px}
.pvbar-dot{width:7px;height:7px;border-radius:50%;background:#fff;flex:none;
  animation:pvPulse 2s var(--ease-out) infinite}
@keyframes pvPulse{0%,100%{opacity:1}50%{opacity:.35}}
.pvbar-txt{font-family:var(--mono);font-size:10.5px;letter-spacing:.13em;text-transform:uppercase;
  line-height:1.3;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pvbar-txt b{font-weight:500}
.pvbar-btn{margin-left:auto;flex:none;font-family:var(--mono);font-size:10px;letter-spacing:.14em;
  text-transform:uppercase;color:#fff;border:1px solid rgba(255,255,255,.62);
  border-radius:var(--r-sm);padding:7px 14px;transition:background var(--t-fast) var(--ease),
  border-color var(--t-fast) var(--ease)}
.pvbar-btn:hover{background:#fff;border-color:#fff;color:var(--orange)}
.pvbar-btn:focus-visible{outline:2px solid #fff;outline-offset:2px}
/* keep the sticky site header clear of the bar */
.has-preview .hdr{top:var(--pvbar-h)}
.has-preview #mccpb{top:var(--pvbar-h)}
.has-preview .mob{padding-top:calc(var(--hdr-h) + var(--pvbar-h) + 26px)}
@media (max-width:620px){
  :root{--pvbar-h:34px}
  .pvbar-sub{display:none}          /* keep the label short, keep the button */
}
@media print{ .pvbar{display:none} }

/* ─────────────────────────────────────────── 3. HEADER CHROME */
.hdr{position:sticky;top:0;z-index:60;
  transition:height var(--t-med) var(--ease),background var(--t-med) var(--ease),box-shadow var(--t-med) var(--ease)}
.hdr-in{transition:height var(--t-med) var(--ease)}
.hdr.scrolled{background:rgba(26,22,13,.92);backdrop-filter:saturate(1.4) blur(14px);
  box-shadow:0 1px 0 0 var(--dark-rule),0 18px 40px -28px rgba(0,0,0,.8)}
.hdr.scrolled .hdr-in{height:70px}
.hdr .wordmark{transition:transform var(--t-med) var(--ease)}
.hdr.scrolled .wordmark{transform:scale(.92)}
.wordmark svg path{transition:fill var(--t-med) var(--ease)}
.wordmark:hover svg path{fill:#FF6242}

/* scroll progress */
#mccpb{position:fixed;top:0;left:0;height:2px;width:0;z-index:80;
  background:linear-gradient(90deg,var(--orange),#FF8A6B);box-shadow:0 0 12px rgba(240,75,35,.7)}

/* Skip link. Clipped rather than pushed to left:-9999px — a far-offscreen
   absolute element shows up as a false positive in overflow audits and, in
   some engines, can extend the scrollable area. */
.skip{position:absolute;top:0;left:0;z-index:100;width:1px;height:1px;overflow:hidden;
  clip-path:inset(50%);white-space:nowrap;background:var(--orange);color:#fff;
  border-radius:0 0 var(--r-sm) 0;font-family:var(--mono);font-size:11px;
  letter-spacing:.14em;text-transform:uppercase}
.skip:focus{width:auto;height:auto;overflow:visible;clip-path:none;padding:12px 18px}

/* hamburger */
.ham{display:none;width:44px;height:44px;border:1px solid var(--dark-rule);border-radius:var(--r-sm);
  background:transparent;cursor:pointer;padding:0;position:relative;flex:none}
.ham i{position:absolute;left:12px;right:12px;height:1.5px;background:var(--on-dark);border-radius:2px;
  transition:transform var(--t-med) var(--ease),opacity var(--t-fast) var(--ease)}
.ham i:nth-child(1){top:15px}.ham i:nth-child(2){top:21px}.ham i:nth-child(3){top:27px}
.ham.open i:nth-child(1){transform:translateY(6px) rotate(45deg)}
.ham.open i:nth-child(2){opacity:0}
.ham.open i:nth-child(3){transform:translateY(-6px) rotate(-45deg)}

/* mobile drawer */
/* Covers the WHOLE viewport (inset:0), not just below the header. It used to
   start at var(--hdr-h), but that is a fixed guess: the header shrinks to
   70px once scrolled, and the preview bar adds more — so the drawer left a
   strip of the page showing through, which then scrolled behind it. The
   header floats above the drawer (z-index 60 vs 55) so the close button is
   still reachable; padding-top keeps the links clear of it. */
.mob{position:fixed;inset:0;z-index:55;background:var(--brown-deep);
  padding:calc(var(--hdr-h) + 26px) var(--pad) 40px;
  overflow-y:auto;overscroll-behavior:contain;
  opacity:0;visibility:hidden;transform:translate3d(0,-12px,0);
  transition:opacity var(--t-med) var(--ease),transform var(--t-med) var(--ease),visibility var(--t-med)}
.mob.open{opacity:1;visibility:visible;transform:none}
.mob a{display:block;padding:17px 0;border-bottom:1px solid var(--dark-rule);color:var(--on-dark);
  font-size:21px;font-weight:500;letter-spacing:-.02em;font-variation-settings:"opsz" 32;
  opacity:0;transform:translate3d(0,14px,0)}
.mob.open a{animation:mccMobIn .5s var(--ease) both}
.mob.open a:nth-child(1){animation-delay:.05s}.mob.open a:nth-child(2){animation-delay:.10s}
.mob.open a:nth-child(3){animation-delay:.15s}.mob.open a:nth-child(4){animation-delay:.20s}
.mob.open a:nth-child(5){animation-delay:.25s}.mob.open a:nth-child(6){animation-delay:.30s}
.mob.open a:nth-child(7){animation-delay:.35s}
.mob a.on{color:var(--orange-dark)}
.mob .mob-foot{margin-top:32px;display:flex;flex-direction:column;gap:14px}
.mob .mob-foot .btn{text-align:center}
@keyframes mccMobIn{to{opacity:1;transform:none}}

/* Scroll lock while the drawer is open. body{overflow:hidden} alone is not
   enough — the document element keeps its own scroll, which is what let the
   page move behind the menu. Locking html as well stops it, and
   overscroll-behavior on the drawer stops scroll chaining once its own list
   reaches the end. */
html.mob-open,html.mob-open body{overflow:hidden}
html.mob-open{overscroll-behavior:none}

/* back to top */
.totop{position:fixed;right:26px;bottom:26px;z-index:50;width:48px;height:48px;border-radius:50%;
  background:var(--brown);color:var(--on-dark);border:1px solid var(--dark-rule);cursor:pointer;
  display:grid;place-items:center;opacity:0;visibility:hidden;transform:translate3d(0,14px,0) scale(.9);
  transition:all var(--t-med) var(--ease)}
.totop.on{opacity:1;visibility:visible;transform:none}
.totop:hover{background:var(--orange);border-color:var(--orange);color:#fff;transform:translateY(-3px)}
.totop svg{width:16px;height:16px}

/* focus visibility — the handover pack has none */
a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible,
.chip:focus-visible,.tile:focus-visible{outline:2px solid var(--orange);outline-offset:3px;border-radius:4px}
.dark a:focus-visible,.dark button:focus-visible{outline-color:var(--orange-dark)}

/* real form controls (handover uses static divs) */
input.inp,textarea.inp,select.inp{width:100%;font-family:var(--sans);color:var(--ink);
  transition:border-color var(--t-fast),box-shadow var(--t-fast),background var(--t-fast)}
input.inp:focus,textarea.inp:focus,select.inp:focus{outline:0;border-color:var(--orange);
  background:#fff;box-shadow:0 0 0 3px rgba(240,75,35,.13)}
textarea.inp{min-height:132px;resize:vertical}
.err{margin-top:7px;font-family:var(--mono);font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;color:#C0341A}
.note{padding:16px 18px;border-radius:var(--r-sm);font-size:14.5px;margin-bottom:22px}
.note.ok{background:#EAF4EC;color:#1E5B2C;border:1px solid #BFDDC6}
.note.bad{background:#FBEAE6;color:#8E2A12;border:1px solid #F0C6BA}

/* ─────────────────────────────────────────── 5. RESPONSIVE */
@media (max-width:1360px){
  :root{--pad:48px}
  .hero-copy{padding-left:48px;padding-right:48px}
}
@media (max-width:1180px){
  :root{--sec:112px;--pad:40px}
  h1{font-size:52px}h1.sm{font-size:42px}h2{font-size:34px}h2.mid{font-size:28px}
  .grid2,.split{gap:56px}
  .tiles.t4,.projs.cols4,.spec-grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  .creds-in{grid-template-columns:repeat(2,minmax(0,1fr))}
  .cred{border-bottom:1px solid var(--rule)}
  .cred:nth-child(2n){border-right:0}
  .cred:not(:first-child){padding-left:0}
  .cred:nth-child(2n){padding-left:32px}
  .ftr-grid{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:40px}
  .swatch-list{grid-template-columns:repeat(3,minmax(0,1fr))}
  .hero{min-height:0}
  .hero-copy{padding-top:72px;padding-bottom:72px}
  .hero-img{min-height:420px}
}
/* Header collapses at the designer's 980 stop (v6 site.css). v6 turns the
   nav into a horizontally scrolling row under the lockup and makes the header
   static; we keep the sticky header + hamburger drawer instead (phase 2g), so
   its header rules are neutralised here. mcc-ui.css loads after mcc.css, so
   equal-specificity rules below win. */
@media (max-width:980px){
  :root{--hdr-h:74px}
  .hdr{position:sticky}
  .hdr-in{height:74px;flex-wrap:nowrap;padding:0 var(--pad);row-gap:0}
  .nav,.hdr-r .tel,.hdr-r .btn{display:none}
  .hdr-r{order:0;margin-left:0}
  .ham{display:block}
}
@media (max-width:900px){
  :root{--sec:88px;--pad:28px}
  h1{font-size:41px;max-width:none}h1.sm{font-size:34px}
  h2{font-size:28px;max-width:none}h2.mid{font-size:24px}
  .lede{font-size:17px;max-width:none}
  /* minmax(0,1fr), never plain 1fr: `1fr` is minmax(auto,1fr), so its
     min-content floor lets a wide child (a nowrap table cell, a long mono
     string) push the column past the viewport. */
  .grid2,.grid2.form-split,.split,.hero,.steps,.svc,.svc.rev,.kv>div,.row2
    {grid-template-columns:minmax(0,1fr);gap:36px}
  .svc.rev>div:first-child{order:0}
  .hero-copy{padding:56px var(--pad)}
  /* copy above image — the designer's v6 order (README "Responsive") */
  .hero-img{min-height:320px}
  .steps{gap:0}
  .faq>div{flex-direction:column;gap:10px}
  .bleed .cap-box{left:var(--pad);right:var(--pad);bottom:24px;max-width:none;padding:24px 22px}
  .accred{gap:16px}
  .logos{gap:32px}
  .mask-box{height:340px}
  .quote{font-size:24px;max-width:none}
  .ftr-legal{flex-direction:column;gap:10px}
  section{padding-top:var(--sec)}
  .pad{padding-top:80px;padding-bottom:80px}
  .band{margin-top:88px}
  .wmark{width:380px!important}
}
@media (max-width:620px){
  :root{--pad:20px;--sec:72px;--r-lg:16px}
  h1{font-size:33px}h2{font-size:25px}h2.mid{font-size:22px}
  body{font-size:16px}
  .tiles.t2,.tiles.t3,.tiles.t4,.projs,.projs.cols2,.projs.cols3,.projs.cols4,
  .spec-grid,.tiles.cols3,.tiles.cols4,.tiles.cols5{grid-template-columns:minmax(0,1fr)}
  .creds-in{grid-template-columns:minmax(0,1fr)}
  .cred{border-right:0;padding:28px 0!important}
  .cred b{font-size:42px}
  .cred::after{display:none}
  .ftr-grid{grid-template-columns:minmax(0,1fr);gap:32px}
  .swatch-list{grid-template-columns:repeat(2,minmax(0,1fr))}
  .form{padding:26px 22px 30px}
  .cta{gap:10px}.cta .btn{flex:1 1 100%;text-align:center}
  .tw{overflow-x:auto}
  .hero-img{min-height:250px}
  .mask-box{height:250px}
  .totop{right:14px;bottom:14px;width:42px;height:42px}
  .logos span{font-size:16px}
  .wmark{width:280px!important;opacity:.05}
}

/* tables never break the page */
.tw{max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}

/* ─────────────────────────────────────────── 6. REDUCED MOTION + PRINT */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
  [data-anim]{opacity:1!important;transform:none!important;filter:none!important;clip-path:none!important}
  .hero-copy .w{opacity:1!important;transform:none!important}
  .seclab .ln{transform:scaleX(1)!important}
  .mask-box img{-webkit-mask-size:84% auto!important;mask-size:84% auto!important;transform:none!important}
  .fig-box img{transform:none!important}
  .logos.run .track{animation:none!important}
  .wmark{transform:translateY(-50%)!important}
  .cred b,.cred span{opacity:1!important;transform:none!important}
}
@media print{
  .hdr,.mob,.ham,#mccpb,.totop,.closing .cta{display:none!important}
  [data-anim],.hero-copy .w,.cred b,.cred span{opacity:1!important;transform:none!important;clip-path:none!important}
  body{background:#fff}
  .dark,.warm,.light,.closing,.ftr{background:#fff!important;color:#000!important}
}

/* no-JS: never leave content invisible */
.no-js [data-anim],.no-js .hero-copy .w,.no-js .cred b,.no-js .cred span{opacity:1!important;transform:none!important;clip-path:none!important}
.no-js .seclab .ln{transform:scaleX(1)!important}
.no-js .mask-box img{-webkit-mask-size:84% auto!important;mask-size:84% auto!important}
